本人目前使用过的代码热更方案有XLua和HybridCLR,没用过ILRuntime,目前的项目使用的热更方案是Addressables+HybridCLR,整个热更新的框架由我一手搭建,基本实现了线上Bug无缝修复,用起来还是非常带劲的,在此强烈推荐HybridCLR,至于XLua的总结我可能不会再另外写了。
首先需要申明的是,想要做全代码热更是不太现实的,毕竟资源下载这一块的代码是必须写死的,不过只要下载完成,那后续所有的咱们自己创建的代码都可以热更,为啥这里强调是自己创建的代码呢?因为整个项目中我们还会引入其他插件,包括一些Unity注册的模块包(Package Manager里面管理的)就不适合做到代码热更里面,但是如果说你偏要把这些不适合的也要放到代码热更里面,万一哪天你想改这些代码了呢?也不是不行哈,毕竟办法总比困难多嘛~
这里我先介绍一下HybridCLR,我记得我最开始接触的时候还叫Huatuo,刚出来那会特别火,据说可以用C#直接热更,没有跨域、性能等各种问题,基本上等于原生开发,可以说是最完美的Unity代码热更方案,不得不佩服作者的想象力和创造力啊。刚开始我相信大家和我一样,即使看了HybridCLR的官方文档也是懵懵懂懂的,只有自己上手去操作去理解才能体会其中的奥秘。
在这里我先带大家上手HybridCLR,然后下篇文章我将花时间讲解一下HybridCLR的原理以及一些注意事项,助大家扫除万难,早日实现全热更。
先贴上HybridCLR的上手文档:快速上手 | HybridCLR,为什么我会先贴出这个文档呢?熟悉我写作风格的都知道我喜欢把文档链接放在最后,主要是我看了一下现在的官方文档,现在他们推荐使用的是2021.3.1版本(目前GitHub上的官方示例工程用的就是这个版本),我们立项的时候当时推荐的还是2020.3.x版本...所以我这个教程总结还是按2020.3.x来写的,避免大家有所误解,所以先把文档放前面了,大家可以看文档来尝试,也可以使用2020.3.x版本跟着我的步骤来操作(PS:我的步骤会比较详细些)。
1.我将示例工程上传了我的CSDN资源下载里,大家可以免费下载,首先是下载最新的2020.3.x版本,我当时最新的是2020.3.40,打开示例工程时会提示你是否升级版本,无脑继续就行,直到进入到Unity编辑器的界面
接下来就是要操作HybridCLR的初始化了,先生成必要的各种的文件:
我们之后热更新打出来的dll会在HotUpdateDlls文件夹的对应平台(比如Android,这里是PC平台)文件夹里,如下图的Assembly-CSharp.dll就是我们的热更代码
如果我们创建了新的程序集,并指定了该程序集为热更dll,那么就必须要在上图红框里添加该程序集名称。
点击Installer,我们来安装HybridCLR相关的库:
我这里显示的状态是已安装,我有点忘了初次安装的显示状态了,这里你们可能会显示未安装,点击右下角的安装按钮(需要提醒的是,在点安装之前,你们必须要提前安装好Git,它会使用Git来拉取代码到本地,否则会提示安装失败):
安装完之后,我们可以看到HybridCLRData文件夹里会多出来这几个子文件夹:
4.我们可以尝试对工程进行打包了,这也是必不可少的一步,这里为了演示操作我直接Build PC平台的工程,你们如果是安卓的记得切换平台再Build,不幸的是我这边打包失败了:
我猜你们也很可能会遇到这个错误,所以解决办法是我们先到Package Manager里面找到HybridCLR,然后选择升级到2.0.0(我这边目前看到最新的是2.4.2了,你们也可以尝试升级到最新,看看会有什么不同,欢迎在评论区留言),为了和我之前的工程保持一致我这边暂时按照老一点的版本来:
foreach (var dll in SettingsUtil.HotUpdateAssemblyNamesExcludePreserved)
打开上图中的文件,并且添加这行代码:#define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
亲测可以打包成功。
文字提示你已经成功运行了热更新代码...教程到此就结束了吗?NO!我们还没有对代码进行热更啊!这里我演示一下怎么修改代码,然后进行代码“热更”(这里并不是走那种下载流程,我在本地手动操作,原理是一样的)。我们先来看看工程的代码,回到Unity工程里面,打开LoadDll这个脚本:
代码我就不贴了,简单讲解一下LoadDll这个脚本做了些什么事:
<1> 加载了StreamingAssets里的这些dll和资源(除了build_info)
<2> 从prefabs这个ab包里加载并生成HotUpdatePrefab.prefab
<3> HotUpdateMain这个脚本执行,并且输出"hello, HybridCLR"以及添加了CreateByCode脚本
void Start()
{
Debug.Log("这个热更新脚本挂载在prefab上,打包成ab。通过从ab中实例化prefab成功还原");
Debug.LogFormat("hello, {0}.", text);
gameObject.AddComponent();
Debug.Log("=======看到此条日志代表你成功运行了示例项目的热更新代码=======");
}
CreateByCode脚本只做了一件事:Debug.Log("这个脚本是通过代码AddComponent直接创建的");
6.既然如此,那么我们是不是只需要修改CreateByCode脚本的代码,并且替换exe本地的Assembly-CSharp.dll文件,重新运行exe程序,不就等于完成了热更了吗(走ab包更新也是同样的原理)?那我们修改CreateByCode的脚本吧:
找到Assembly-CSharp.dll文件,修改它的后缀(增加.bytes后缀),与工程里的名字保持一致,然后复制到exe工程替换之前的Assembly-CSharp.dll.bytes文件
替换好了之后,我们再重新打开exe,看看是不是代码“热更”了?
整个操作流程基本就是这样,但是我们知道StreamingAssets这个文件夹本身就不能做热更新,所以要实现真正的代码热更,我们需要让这些dll和资源从StreamingAssets拿出来放到合适的文件夹里,并且打成ab包使用persistentDataPath目录,即可实现真正意义上的代码热更。至于怎么去优化这一系列流程以及原理剖析,请关注我的后续文章。