HybridCLRxLua
介绍
HybridCLR(代号wolong)是一个特性完整、零成本、高性能、低内存的近乎完美的Unity全平台原生c#热更方案.
HybridCLR扩充了il2cpp的代码,使它由纯AOT runtime变成‘AOT+Interpreter’ 混合runtime,进而原生支持动态加载assembly,使得基于il2cpp backend打包的游戏不仅能在Android平台,也能在IOS、Consoles等限制了JIT的平台上高效地以AOT+interpreter混合模式执行,从底层彻底支持了热更新.更详细的特性、平台支持介绍请看这里.
xLua为Unity、 .Net、 Mono等C#环境增加Lua脚本编程的能力,借助xLua,这些Lua代码可以方便的和C#相互调用.
xLua在功能、性能、易用性都有不少突破,这几方面分别最具代表性的是:
- 可以运行时把C#实现(方法,操作符,属性,事件等等)替换成lua实现;
- 出色的GC优化,自定义struct,枚举在Lua和C#间传递无C# gc alloc;
- 编辑器下无需生成代码,开发更轻量;
更详细的特性、平台支持介绍请看这里.
由于热更特性的需求,之前Cocos游戏很多是使用lua或者js来实现热更的,这其中lua的使用率最高,在Unity3d上也有很多热更方案(ToLua,ULua,xLua,ILRuntime等).综合考虑之下,创建HybridCLRxLua工程用于演示在接入HybridCLR的情况下还能正确的使用xLua,这样将更新的粒度切到很细.之前的更新粒度一般是
- 更新APK(IPA)
- 更新业务脚本(lua, ilruntime.dll)
- 更新资源
而使用HybridCLRxLua流程,可以将粒度细分为
- 更新apk(IPA)
- 更新HybridCLR hotfix.dll
- 更新业务脚本(lua)
- 更新资源
有数据显示,更新apk(ipa)对用户的损失可以达到20%+,热更存在的意义就是尽可能减少强更app的可能性.
兼容性
- 支持PC(WIN,MacOS)、Android和iOS版本
- 在2020.3.3、2020.3.33、2020.3.39测试通过,后续会继续测试其他版本
- 目前win,android平台下支持使用2020.3.3导出执行文件,ios不行,只能用2020.3.33或更新版本
重点修改项
- 修改出包流程,与hybridclr_trial相比,简化了出包流程,不需要二次打包即可产出可直接运行的产出.
- 热更dll和lua抛弃assetbundle转由使用二进制文件的方式来达到简化出包流程的目的
- xLua修改
- 将xLua原生代码拆分成两部分,编辑器脚本放在主工程,其他部分放在Hotfix工程.
- 修改LuaDLL.cs,原生LuaDLL.cs放在主工程并将namespace修改为其他名称(比如XLuaBase),新的LuaDLL.cs放在Hotfix工程,其中,Hotfix工程里的LuaDLL.cs调用主工程里的函数.
- 修改xLua相关的模板文件(*.tpl.txt),将using LuaCSFunction = XLua.LuaDLL.lua_CSFunction; 全局替换为 using LuaCSFunction = XLuaBase.lua_CSFunction;
- 按需生成ReversePInvokeMethodStub函数,根据MonoPInvokeCallback的函数数量生成相应数量的函数(为了尽可能减少出包次数,本工程使用个数*1.5来作为函数数量)
- 为非标准版本准备了CopyBuildToolsPath方法,比如在Unity2020.3.3上编译而HybridCLR使用的是2020.3.33的工具包,如果不使用相应版本的编译工具,就会导致编译失败(可能是xlua使用了比较复杂的用法).
添加global-metadata.dat加密功能
- 在mono模式下,游戏C#代码被编译为IL(中间代码)并生成dll文件,然后dll被打包进最后的游戏包文件.由于IL非常容易被ILSpy/.NETReflector等专业反编译软件分析逆向,所以在无保护情况下,游戏的安全性极差.NETReflector几乎可以还原出C#文件,外挂开发者可以凭此迅速制作出强大的外挂.
- 对于mono,il2cpp将游戏C#代码转换为C++代码,然后编译为各平台Native代码.由于Native代码的逆向/反编译难度大大增加,可以有效提高外挂开发/游戏破解的门槛.另外,il2cpp具有执行效率高/平台兼容性好等原因,所以il2cpp已经逐步被绝大多数游戏采用.在il2cpp模式下,虽然游戏逻辑是以Native代码运行,但依然要实现C#某些语言特性(如GC),il2cpp将所有的C#中的类名/属性名/字符串等信息记录在global-metadata.dat文件.il2cpp启动时会从这个文件读取所需要的类名/属性名等信息.正是这一机制为外挂制作/游戏破解带来了便利,使用IL2cppDumper可以解析global-metadata.dat文件,并将文件里的类名等字符串信息对应到Native代码中去,极大地方便了逆向分析.
- 基于这种情况,本项目开发了global-metadata.dat加密方案(同时支持Android/iOS/Windows),防止global-metadata.dat被IL2cppDumper解析.该方案主要包括两个部分:
- 加密global-metadata.dat文件
- 同步创建适用于解密此文件的c++文件
后续计划
性能测试
问题及FAQ