C#hybridCLR热更新方案初探

前言

暂时处于初步研究状态,目前的框架使用还是尚少,本篇文章旨在同步给大家大概的使用流程和使用心得,在初步建立新项目时可以适当考虑。

介绍

热更新

与强制更新相对应,移动平台上App的可执行程序没有发生变化,仅需要更新游戏资产就可以实现新版本的分发,这种更新称之为热更新。由于不需要经过App商店审核,这种更新内容可以非常快速地分发给玩家。玩家也不需要重新下载App全量包,仅需要下载变动的资产部分即可正常进行游戏,相对而言减小了玩家流失的风险。

为什么会诞生第三方热更新方案,而非系统原生支持

IOS上的反射是部分支持,支持使用反射读取源代码,但不支持使用反射动态生成可执行代码。总而言之,IOS不支持以动态方式创建新的方法和类型。资源热更新采用我们目前的assetbundle是没有任何问题的,如果我们把部分逻辑提取至一个单独的代码库工程中,打包为DLL,再用DLL打包成AB包,用户下载完这个AB包后动态加载DLL文件,按理说是可行的,但是ios不支持动态运行代码,所以是没办法的。

第三方热更新方案

目前市面上主流的,我了解到的热更新方案有lua、ILRunTime、HybridCLR。

从unity到底层二进制代码的流程主要是Unity->.net字节码->il2cpp->C++静态代码->二进制代码

lua分xlua和ulua。xlua是腾讯写的lua热更新框架,目前项目在使用,主要逻辑是自己会生成一个虚拟机管理lua数据,在初始阶段用dostring或者loader的方式加载lua,中期通过挂载luabehaviour的方式和lua侧的luatable进行交流,中间有关unity的obj生成wrap文件让lua侧能get、set数据。具体参考前文Lua与C#交互初析-CSDN博客

ILRuntime项目为基于C#的平台(例如Unity)提供了一个纯C#实现,快速、方便且可靠的IL运行环境,使得能够在不支持JIT的硬件环境(如iOS)能够实现代码的热更新。由于unity可以解释执行.net字节码,所以ilruntime采取C#侧的一个虚拟环境来对C#代码作.net字节码更新,交给unity。

HybridCLR改写了il2cpp模块,给il2cpp新增了原生的interpreter模块,使其能够通过Assembly.Load的方式动态加载dll。没有数据跨域的问题。

简要概括,为了能让游戏运行过程中动态更新代码,有两种流派:lua和ILRuntime在unity内部实现一个虚拟机,用虚拟机解释执行.net代码,在这里面进行代码热更;hybridCLR改写了更底层的il2cpp模块,我们在运行时只需要确保更新到最新的.dll模块,即可完成代码更新。

HybridCLR操作流程

AssetBundle

在说明代码热更新之前,首先需要研究AB包的热更新流程。打包方式采用BuildPipeline.BuildAssetBundles实现,在运行过程中调用AB包资源时采用AssetBundle.LoadFromFile/AssetBundle.LoadFromMemoryAssetBundle.LoadAsset实现。

下载

为了模拟热更新,客户端本地需要在网络上请求到最新的资源并且下载到本地,再用新下载的文件加载进游戏中才算真正实现。于是服务器端我临时搭建了一个python的http服务器用来处理简单的上传下载功能。客户端采用项目里的下载流程。

HybridCLR框架使用

根据官方文档的流程做,新建一个2021稳定版本的unity工程,在内部安装HybridCLR package并初始化HybridCLR,并对playerSettings做出一些改动(比如关闭增量式GC(Use Incremental GC) 选项、Scripting Backend 切换为 il2cpp等操作)。具体流程参照官方文档

在进程刚启动时就更新主链接库Assembly-CSharp.dll,参考以下代码,时间类似于项目组目前的startup更新,只不过这里更新的是dll文件,组内更新的是assetbundle然后解包注入lua bytes。

load完Assembly-CSharp.dll就直接开始走内部加载方式了,直接在热更新的代码片段里驱动调用更新代码把其他资源更新过来即可。

最后就可以开展其他工作了,比如在这些资源上增删改查代码。

更新前:

更新后:

如果后期要增加外部dll(大部分时候用Assembly-CSharp.dll就已经可以了),也没啥问题,直接在热更新C#代码里更新热更资源就行。比如现在我增加一个新的dll,只需要导入进来并且设置project的HybridCLR settings即可(类似assetbundle kit设置)。

导入ClassLibrary1.dll后改写上述的hotupdatemain即可。

这个时候不用换包,还是用之前的那个包,依然可以达到热更新效果。

相关推荐
向宇it4 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
九鼎科技-Leo5 小时前
什么是 WPF 中的依赖属性?有什么作用?
windows·c#·.net·wpf
Heaphaestus,RC6 小时前
【Unity3D】获取 GameObject 的完整层级结构
unity·c#
芋芋qwq6 小时前
Unity UI射线检测 道具拖拽
ui·unity·游戏引擎
baivfhpwxf20236 小时前
C# 5000 转16进制 字节(激光器串口通讯生成指定格式命令)
开发语言·c#
直裾6 小时前
Scala全文单词统计
开发语言·c#·scala
tealcwu7 小时前
【Unity服务】关于Unity LevelPlay的基本情况
unity·游戏引擎
ZwaterZ8 小时前
vue el-table表格点击某行触发事件&&操作栏点击和row-click冲突问题
前端·vue.js·elementui·c#·vue
大眼睛姑娘9 小时前
Unity3d场景童话梦幻卡通Q版城镇建筑植物山石3D模型游戏美术素材
unity·游戏美术
ZwaterZ10 小时前
el-table-column自动生成序号&&在序号前插入图标
前端·javascript·c#·vue