Unity 开源代码混淆插件 Obfuz
文章目录
介绍
Obfuz 是一款开源、强大、易用及稳定可靠的充分满足商业化游戏项目需求的Unity代码混淆和加固解决方案。
这个插件比较新,2025 年 5 月 17 日首次提交。项目是由 HybridCLR 的作者编写的。
文档
环境
- Unity 2022.3.62f1
- Obfuz 20250728 38ad0de746979c2df8adad0f1f442d9e4478c522
需求
- 支持游戏中使用的
Assembly Definition
。 - 必须直接使用源代码,而不是使用包管理器安装,以支持离线无网环境打包。
- 支持混淆部分代码,需要改动尽量小。
快速上手
按照文档搭建一个测试环境,首先将游戏代码放到单独的 Game.asmdef 中,然后使用源码直接放到 Assets/Plugins
目录中。
经过测试可以直接满足上面的 1 和 2 两点。
混淆功能
- 符号混淆:支持丰富的配置规则和增量混淆,灵活高效地保护代码。
将所有的符号改名,符号包括方法名、类名、成员名等等。
Unity 中存在大量依赖符号名字的功能,例如 MonoBehaviour 事件方法、Animation 动画事件方法。
游戏中也可能存在使用反射获取符号或类型的方法,例如序列化与反序列化。
如果需要游戏正常运行,必须将所有需要的符号保留不进行混淆。
符号混淆 Debug 模式
默认情况下,生成的混淆名类似于
$a
之类,如果不去查看symbol mapping文件,很难从代码中得知原始名是哪个。这给追踪符号混淆引发的bug时,带来较多不便, 因此Obfuz特地支持了Debug模式。在Debug模式下,会将Name
映射为$Name
,可以直接看出原始名是什么,方便调试追踪。Debug模式下的混淆规则是固定的,即
Name
映射为$Name
。如果遇到名称冲突,会尝试$Name1
、$Name2
直到找到不冲突的名字。因此Debug模式下会 忽略symbol mapping文件,既不会加载它,也不会混淆完成后更新它。
Mono 版本混淆
使用 Windows 打包测试 Mono 版本是否正常
EncrytionService 初始化
|
|
还未初始化
EncrytionService<T>::Encryptor
就运行了混淆代码。解决办法为先初始化EncryptionService<T>::Encryptor
,详细文档见初始化Encryptor。
不需要混淆的符号
|
|
直接将这些类型忽略。
GameFramework 混淆方法
有人已经将 GameFramework 使用 Obfuz 混淆了,使用属性 [Obfuz.ObfuzIgnore]
来控制哪些内容不混淆。
混淆用时过长
加入混淆后打包时间增加了 25 分钟,迭代效率太低,因此必须控制混淆的代码数量,只混淆需要的部分。
拆分需要混淆的代码
首先将混淆的代码放入单独的 DLL 中,其他的代码也放入单独的 DLL 引用这个混淆 DLL,或者其他代码放到 Assembly-CSharp
中默认自动引用所有的 DLL。
使用依赖注入拆分需要混淆的游戏代码。将所有混淆代码使用到的方法定义到一个单独的接口中,在外部代码中实现这个接口,并在运行时将实例注入到混淆代码中。
反射兼容性问题
|
|
将所有 Obfuz 提示的反射兼容性问题都使用属性 [Obfuz.ObfuzIgnore]
禁止混淆。
ScriptableObject 问题
ScriptableObject
的 OnEnable
被混淆了,Obfuz 应该是忽略了这个类与 MonoBehaviour
相同也需要忽略,因此手工忽略一下。
IL2CPP 版本混淆
使用 Android 打包测试 IL2CPP 版本是否正常
|
|
Mono 版本中没问题,但是 IL2CPP 版本中异常,手动将这个类型忽略混淆。
使用 iOS 打包测试 IL2CPP 版本是否正常
无问题。