unity3d的代码怎么写( 二 )


背景Unity引擎上的程序执行在Mono运行时上,使用Mono编译出的程序集格式与.NET标准一致 。C#是Unity引擎下主要的开发语言,它具备不少高级语言特性,如反射、元数据、内置序列化等 。
但C#同时也是很容易被反编译的语言,如果不采用任何保护措施,使用常用的工具(.NET Reflector)便能很容易得到可二次编译的代码 。对项目运营带来了比较大的风险 。
.NET平台下通常的保护手段是混淆编译出的程序集 。VisualStudio自带了一个混淆工具Dotfuscator可以对程序集进行混淆 。
功能包括名称修改,流程混淆,字符串加密等 。经过Dotfuscator混淆后的程序集,能够避免被常用反编译工具破解 。
变量的表意性被破坏,同时函数的内部流程也被混淆(如下[B1] ) 。能有效起到保护源代码的效果 。
publicclass181: 218{// Fieldspublicuint0;publicushort1;;;// Methodsstatic181();public181();public95.02();public95.02(ref515A_0, uintA_1);public95.02(79A_0, refuintA_1);public95.02(ref79A_0, uintA_1);public95.02(byte[] A_0, intA_1, refuintA_2);public95.02(ref481A_0, intA_1, charA_2);public95.02(refstringA_0, intA_1, charA_2);public95.02(refbyte[] A_0, intA_1, refintA_2, uintA_3);public95.03(ref79A_0, uintA_1);public95.03(refbyte[] A_0, intA_1, refintA_2, uintA_3);public95.04(refbyte[] A_0, intA_1, refintA_2, uintA_3);}public95.00(refsbyteA_0, intA_1){// This item is obfuscated and can not be translated.goto Label_0006;if(1!= 0){}95.0local= 95.0.0;bytenum= 0;local = this.0(refnum,A_1);A_0 = (sbyte) num;returnlocal;Unity引擎下,Mono编译出的程序集,由于采用与.NET相同的格式标准 。能够直接被Dotfuscator混淆 。
但Unity引擎有一些特殊的地方,使混淆工作与一般的.NET程序存在差异 。第三节将主要讨论这些特殊点 。
Unity引擎下代码混淆的特殊性代码被资源引用[B2]。Unity的可视化编辑特性在设计上的关键之处在于使代码能够以组件的形式依附到资源实例上 。
相比传统游戏,Unity的两类资源(scene和prefab)不仅包括数据,还包括附加在资源上的类对象 。也就是说,这两类资源的存储格式中存在唯一标识某代码类型的数据 。
混淆流程必须不破环这种对应关系才能使资源上的代码逻辑正确被执行 。(Unity这样设计的意义并不是本文讨论的重点,而另一篇分享个人对Unity可视化编辑的理解的文章中将会详细说明 。)
发布到Web的Unity项目,在生成播放器可执行包(*.unity)的接口中,将编译程序集和打包这两个步骤捆绑在的一起 。我们没办法像普通.NET程序那样,对编译出的程序集进行混淆后再打到播放器可执行包中 。
UnityEngine按函数名进行调用 。MonoBehaviour是Unity引擎的一个重要的组件基类 。
其上的很多方法,Unity是通过方法名称进行访问的,如Awake、Start、Update等等 。这些方法如果在混淆中被改名,将使方法调用失败 。
这个问题相对比较好处理,Dotfuscator的重命名功能提供了排除配置 。我们只要得到继承于MonoBehaviour的所有类型,就能生成相应的排除配置,告知Dotfuscator不要对这些方法进行重命名 。
生成的配置节选如下[B3] :xmlserialization思路何时混淆?由于Web项目编译和打包的过程是捆绑在一起的,官方没有提供独立的接口 。(之前有跟官方反馈,但目前官方并没有提供具体计划 。)
想自己来分析官方的打包格式是行不通并且不太科学的 。仅剩的办法就是自己将代码编译成DLL,混淆之后再添加到Unity项目中 。
顺着这条思路,笔者在《QQ乐团》项目上作了尝试 。将项目中所有执行相关的代码(不包括编辑器扩展的代码)移出,指定相关的Unity依赖库,编译成DLL 。
再将此DLL复制到原项目中 。这时意料之中的事情发生了——项目中所有资源上的代码引用全部丢失 。