HybridCLR本身接入并不难,安装参考官方文档即可:官方教程
主要在于程序集的规划以及打包流程的调整,如果项目原先使用XLua(我们就是),还要解决与XLua的兼容问题。
程序集
HybridCLR是按照程序集来进行热更的,所以如何拆分、定义热更和非热更程序集就成了关键,Unity项目可以使用AssemblyDefinition定义程序集,合理的程序集划分可以减少代码的耦合,便于管理,同时可以缩短编译时间。建议将性能敏感部分的代码单独放在一个程序集中,比如:游戏内的核心代码、物理底层及框架等,其他代码可以按照框架代码、业务代码、外围系统,这样来划分,需要注意的是,热更程序集不能被其他非热更程序集(以下简称AOT)直接引用,原因是在正常编译时会过滤掉热更程序集,此时AOT程序集中访问热更程序集的部分就会发生编译错误。如果将所有程序集都加入热更列表可以解决这个问题,但是性能和AOT会有一定的差距。详情可参考前面的评测。旗舰版HybridCLR提供了混合差分的方法,可以热更修改的部分,这样即使所有代码皆热更,理论上来说性能也不会有太大的损失,不过我们项目战斗代码热更的需求并不急迫,所以先只用了社区版。
此外,Unity会创建一个默认的程序集:Assembly-CSharp,所有不在我们自定义程序集的代码都在这里。而且这个程序集默认引用其它所有Editor之外的程序集。这个程序集也是可以被热更的,只不过不便于管理。
我们项目原来并没有程序集这方面的规划,所有代码都在Assembly-CSharp里,互相引用,所以在接入热更时遇到了一些问题,经过好一通梳理才将需要热更的代码拆分出来(主要是外围部分)
打包流程
打包流程的调整主要涉及到热更Dll的编译与加密,还有iOS打包时编译lib。
热更Dll的编译比较简单,编译出Dll后可以转为bytes文件,在写入之前可以使用Aes函数对其进行简单加密,且可以对文件与AA生成的bundle进行混淆。这样就可以避免一般反编译软件的破解。
iOS打包需要先编译lib,再在导出XCode后对XCode工程中的lib进行替换。
与XLua的兼容问题
我们项目之前外围代码基本是用Lua写的,而此次接入有一个目标是让老的代码能正常工作,因为重写的成本太高了,所以就需要一定的C#与Lua互相访问的能力。又由于Lua相关的代码需要生成Bind Code,所以有几个关键的XLua类无法脱离业务代码,主要是LuaTable这个类,这就导致我们在热更层无法直接访问LuaTable,只能通过反射的方式,所以需要定义一个CodeBridge,来为C#热更层和Lua层提供一些互相访问的方法:
- C#访问Lua函数
- 获取全局的LuaTable
- 创建新Table
- 修改、读取LuaTable中的值
这个桥接函数是放在AOT层的,可以被所有代码访问,这样一来,C#层和Lua层可以通过这个中间层来互相通信。
还需要注意一点,XLua本身的Dll是无法热更的,暂时不支持外部Dll的热更。
总结
踩过一些坑后,HybridCLR总算顺利接入了,在线上也没有遇到什么问题,稳定性还是比较高的。终于摆脱了Lua较差的可读性(并没有完全摆脱),性能也会提高不少。