• 【Unity3D热更新】Unity3D 零成本、高性能的C#的热更新框架:HybridCLR


    推荐阅读

    大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。

    一、前言

    相信只要做过热更新的小伙伴,都被热更新搞过心态吧。

    我有一个小伙伴,本来是面向Unity做可视化开发,结果去做热更新,直接面对代码开发,非常难受。

    首先,来介绍一下什么是热更新、热更新的优点、热更新的解决方案,最后再引出这篇文章的主角HybridCLR C#热更新方案。

    想要省流的小伙伴可以直接跳到第三节:C#热更新方案HybridCLR的使用。

    1-1、什么是热更新

    热更新就是游戏或软件更新的时候,不用再重新下载安装包进行安装。

    而是在启动应用程序的时候,在内部进行资源或代码的更新。

    1-2、热更新的优点

    1、可以迅速修复Bug,避免用户再去重新下载安装包,在游戏或软件内部就更新BUG
    2、减少安装包的体积,将资源上传到服务器,在运行时动态下载剩余资源
    3、迅速进行游戏更新,可以不用再上架应用商店,直接对游戏或软件进行更新

    1-3、热更新的基本流程

    开发端:

    1、开发端更新了游戏或软件内容,比如更新了脚本、替换了资源
    2、将需要更新的代码或资源,打包成AssetBundle放到服务器
    3、在服务器上,修改记录版本号的文件
    4、修改服务器上的对比文件

    客户端:

    1、运行程序,进行版本号的比较,版本号不同则进行下面操作
    2、下载服务器上的对比文件,类似于目录,确定下载列表
    3、根据下载列表,下载所需的资源
    4、解压资源,用最新的对比文件覆盖本地的对比文件

    1-4、热更新的解决方案

    1-4-1、基于Lua的热更新解决方案

    简介:

    基于Lua的热更新解决方案主要有xLua、toLua、sLua、uLua

    这些热更新方案都是基于Lua语言的。

    也可以叫做Lua插件,运行Lua,并实现了Lua和C#交互的插件。

    为什么用Lua语言做热更新

    至于为什么用Lua语言做热更新,主要是因为Lua语言是解释性语言,并不需要事先编译,而是运行动态解释执行的。

    在解释Lua语言的时候不是翻译成机器码,而是使用C代码记性解释,不用开辟可执行权限的内存空间,也不会有新代码执行,执行解释的是C语言写出来的虚拟机。

    为什么不用C#做热更新

    至于为什么不用C#语言做热更新,因为C#的定位是一个追求效率且功能强大的编译型语言,在运行时需要代码,就将C#的中间语言MSIL转换成机器码的编译 JIT

    在Android环境中支持 JIT ,但是IOS不允许获取具有可执行权限的内存空间,不能通过DLL文件直接更新代码。

    uLua

    Lua插件的原生版本,不会产生静态代码,反射机制,效率低下,速度慢,GC频繁,已停止更新。

    xLua

    XLua是腾讯开发的开源Lua插件,为Unity、.Net、Mono等环境增加Lua脚本编程的能力,借助xLua可以使Lua代码与C#代码相互调用。

    所以xLua可以很方便地实现Lua在Unity3D中的使用。

    本质是实现了运行在C#环境上的Lua虚拟机使得Lua可以和C#相互调用和访问,利用 IL 注入,实现用Lua函数替换C#原函数。

    toLua

    toLua基于LuaInterface。

    LuaInterface是一个实现lua和微软.Net平台的 CLR 混合编程的开源库,使得lua脚本可以实例化 CLR 对象,访问属性,调用方法甚至使用lua函数来处理事件。

    本质就是提供一个Lua的运行环境(虚拟机),为Unity提供编程的能力,让C#和Lua可以相互调用合访问。

    sLua

    sLua代码执行好,性能比toLua低。

    1-4-2、使用Lua热更新方案的优缺点

    优点:

    • Lua语言由C语言编写,通用性强,可以运行在各类操作系统
    • Lua语言是解释性语言,由虚拟器解释执行,无需进行编译
    • 有很多成熟的项目在使用Lua,有较多的使用文档

    缺点:

    • 学使用一门Lua语言,增加学习和开发成本(心酸泪)
    • Lua是弱类型的非面向对象的语言,在大型项目中容易造成结构混乱和维护困难的问题
    • Lua需要在C#环境中提供运行环境,对Lua和C#进行相互转换和调用,效率低下,不如原生C#进行开发

    1-4-3、基于C#的热更新方案

    使用C#进行热更新方案,上面已经提到过了,可以使用DLL替换进行代码更新。

    在Android环境中支持 JIT ,但是IOS不允许获取具有可执行权限的内存空间,这就直接要求 JIT 要以full
    AOT 模式,这种模式把IL直接翻译成机器码而不是在运行期间。不能通过DLL文件直接更新代码。

    这种形式下,要不就放弃IOS平台,只针对Android或Win环境进行热更新。

    要不就使用其他方式。

    总结一下就是更新DLL。

    1-4-4、基于C#热更新方案的优缺点

    优点:

    • Unity开发均使用C#,开发语言统一,编码更容易。
    • 使用纯C#开发无需另创虚拟机等环境,效率高,性能远高于Lua

    缺点:

    • 方案均有各自的局限性,直接反射方式不仅损耗性能,在不支持JIT的系统(IOS)上无法使用。
    • ILRuntime解决了 JIT 的问题但不够成熟,使用问题较多,需要较高的动手解决问题能力。

    解决方案:

    • DLL反射热更新: 使用编译后的DLL文件进行替换,利用反射方式把所需C#组件绑定到相应的对象上使用。
    • ILRuntime:本质还是DLL的替换,但实现了一个 ILR 使其能够在不支持 JIT 的硬件环境(IOS)下实现代码热更新。

    二、C#热更新方案HybridCLR介绍

    介绍了C#热更新方案的优缺点,就说一下这篇文章的主角,HybridCLR: C#热更新方案。

    2-1、简介

    HybridCLR是一个特性完整、零成本、高性能、低内存的近乎完美的c#热更新方案。

    HybridCLR提供一个非常完整的跨平台 CLR 运行时,不仅能在Android平台,也能在IOS、Consoles等限制了JIT的平台上高效地以 AOT +interpreter混合模式执行。

    Unity开发者从此可以完全使用c#开发,并且零成本使用几乎所有的c#特性,再也不需要使用各种脚本或者不完整的热更新方案了。

    >> github 仓库hybridclr <<

    2-2、优点

    • 特性完整。 近乎完整实现了ECMA-335规范,除了 下文中"限制和注意事项" 之外的特性都支持。
    • 零学习和使用成本。 HybridCLR是完整的 CLR 运行时,热更新代码与 AOT 代码无缝工作。不需要额外写- - 任何特殊代码、没有代码生成,也没有什么特殊限制。脚本类与 AOT 类在同一个运行时内,即使反射、多线程(volatile、ThreadStatic、Task、async)之类的代码都能够正常工作。
    • 执行高效。实现了一个极其高效的寄存器解释器,所有指标都大幅优于其他热更新方案。性能测试报告
    • 内存高效。 热更新脚本中定义的类跟普通c#类占用一样的内存空间,远优于其他热更新方案。内存占用报告
    • 原生支持修复 AOT 部分代码。不额外增加任何开发和运行开销。

    2-3、工作原理

    HybridCLR扩充了unity的 il2cpp runtime,将它由纯AOT运行时改造为"AOT + Interpreter"混合运行方式,从底层彻底支持了热更新dll。

    在这里插入图片描述
    更具体地说,HybridCLR做了一下几点工作:

    • 实现了一个高效的元数据(dll)解析库
    • 改造了 il2cpp 的元数据管理模块,实现了元数据的动态注册
    • 实现了一个IL指令集到自定义的寄存器指令集的compiler
    • 实现了一个高效的寄存器解释器
    • 额外提供大量的instinct函数,提升解释器性能
    • 提供hotfix AOT 的支持

    2-4、与其他热更新方案的区别

    其他热更新方案方案:

    使用独立虚拟机,与 il2cpp 的关系本质上相当于mono中嵌入lua。

    因为类型系统不统一,为了让热更新类型能够继承 AOT 类型,需要写适配器,而且解释器中的类型不能为主工程点的类型系统所识别。

    特性不不完整、开发麻烦、运行效率底下。

    HybridCLR热更新方案

    这是原生的C#热更新方案,il2cpp 相当于mono的 AOT 模块,HybridCLR相当于 monoiterpreter 模块,两者合一成为完成 mono

    HybridCLR通过System.Reflection.Assembly.Load动态加载dll,从而支持ios平台的热更新。

    HybridCLR由原生runtime实现,可以与其他主工程AOT部分类型相等并且统一,可以任意调用、继承、反射、多线程,不需要再写适配器。

    2-5、支持版本

    • 支持所有il2cpp平台,包括PC(Win32和Win64)、Android(armv7、armv8)、NS、WEBGL平台。
    • 支持Unity 2020-2021所有LTS版本

    三、C#热更新方案HybridCLR的使用

    3-1、快速开始

    说在前面:本教程了为了适应更多童鞋,教程比较详细,动手能力强的小伙伴可以直接访问 官网地址 自行摸索也可。

    3-1-1、将示例项目下载下来

    https://github.com/focus-creative-games/hybridclr_trial

    在这里插入图片描述
    打不开Github的也可以直接使用CSDN下载:https://download.csdn.net/download/q764424567/86338805

    3-1-2、安装Unity,安装C++模块,打开项目

    (1)安装Unity 2020.3.33,版本:2020.3.33f1

    安装Unity 2020.3.33f1 记得安装WIndows Build Support (II2CPP)模块:
    在这里插入图片描述
    PS:没有这个版本的记得安装一下,HybridCLR目前只支持2020-2021的LTS版本。

    (2)Visual Studio 添加 C++模块:
    在这里插入图片描述
    PS:IL2CPP模块和C++模块是必须安装的

    (3)打开示例工程:
    在这里插入图片描述
    打开后,控制台会报一个错误:
    在这里插入图片描述
    是让我们安装il2cpp。

    3-1-3、安装il2cpp

    (1)找到自己 Unity/2020.3.33f1c2/Editor/Data/il2cpp文件夹:
    在这里插入图片描述
    比如我的路径:
    F:\Frank_Software\Unity\2020.3.33f1c2\Editor\Data\il2cpp

    (2)找到项目目录下的HybridCLRDData文件夹,进入这个文件夹:
    在这里插入图片描述
    找到init_local_il2cpp_data.bat文件,右键选择编辑:
    在这里插入图片描述
    将IL2CPP_PATH的路径改成自己的Unity/2020.3.33的il2cpp路径:
    在这里插入图片描述
    (3)保存文件后,双击init_local_il2cpp_data.bat文件:

    在这里插入图片描述
    这种情况是git没有安装,安装Git后重试。
    在这里插入图片描述

    3-1-4、打包运行程序

    在菜单栏选择Build→Win64:
    在这里插入图片描述
    运行之后:
    在这里插入图片描述
    在打包的过程中可能会遇到很多问题,打包失败。

    可能但不包括的问题有:

    • Unity没有安装II2CPP模块
    • VS没有安装c++模块
    • bat脚本没有更新,要用最新的bat脚本

    出现问题后排查一下问题。

    3-1-5、进行热更新

    先运行一下打包出来的程序:
    在这里插入图片描述
    打开Unity工程,修改Assets/HotFix2/App.cs脚本的内容,在Main函数中增加一行Log:

    在这里插入图片描述

    HotFix和HotFix2文件存放的热更新的文件

    在菜单栏点击HybridCLR→BuildBundles→ActiveBuildTarget,重新打一个ab包:

    在这里插入图片描述
    将目录hybridclr_trial-main\Assets\StreamingAssets下的文件复制到
    Release-Win64\HybridCLRTrial_Data\StreamingAssets目录:
    在这里插入图片描述
    这就完成了热更新文件的替换,重新运行程序就可以看到刚刚修改的日志输出代码已经生效:

    在这里插入图片描述

    3-2、常见问题

    总结一下遇到的问题吧。

    3-2-1、目前选择的脚本后端(IL2CPP)没有安装。

    在这里插入图片描述
    解决方法:

    安装Unity 2020.3.33f1 记得安装WIndows Build Support (II2CPP)模块。
    在这里插入图片描述
    VS记得安装c++模块
    在这里插入图片描述

    3-2-2、打包错误:IL2CPP.Building.BuilderFaiedeXcveption il2cpp-api.cpp

    在这里插入图片描述
    解决方法:

    更新一个bat脚本,也就是这个东西:
    在这里插入图片描述
    最新的bat文件可以看这里:
    https://github.com/focus-creative-games/hybridclr_trial/blob/main/HybridCLRData/init_local_il2cpp_data.bat

    在这里插入图片描述
    全选替换一下即可。

    3-2-3、在“GameAssembly”中找不到名为“HuatuoApi_LoadMetadataForAOTAssembly”的入口点。

    这个主要是HotFix2文件中App.cs的这个函数:
    在这里插入图片描述
    在LoadMetadataForAOTAssembly方法中,载入了dll,使用了裁剪之前的版本。

    可以参照HybridCLR_trial项目,在BuildProcessor中,生成裁剪后的dll后,将dll拷贝到他处。

    更简单的方法是:干掉这个函数(用上的时候再研究)。

    3-3、相关工具推荐

    3-3-1、热更新框架UnityGameFramework_HybridCLR

    在这里插入图片描述
    一键生成环境:
    在这里插入图片描述

    3-3-2、无感知逻辑热更工具 Assemblies-Hotfix-Toolkit-Unity

    在这里插入图片描述
    主要功能:
    (1)对指定的热更程序集进行校验:
    a. 引用框为空则警示
    b. 识别编辑器程序集并警示
    c. 识别被默认程序集引用并警示(默认程序集:Assembly-CSharp.dll,Assembly-CSharp-firstpass.dll)
    d. 如果热更程序集被引用,则展示被引用的程序集并提示需要修复
    (2)热更程序集在 Addressables 打包时自动转存为 .bytes 文件并打包到 ab 中
    (3)将 .bytes 文件及其配置文件 自动加入 Addressables Group
    (4)对加载的程序集自动进行拓扑排序,保证程序集按正确的引用顺序加载

    3-3–3、Unity框架 TEngine

    TEngine是一个简单(新手友好)且强大的Unity框架,对于需要一套上手快、文档清晰、高性能且可拓展性极强的开发者或者团队来说是一个很好的游戏开发框架解决方案。

    在这里插入图片描述

    四、后记

    官方网站HybridCLR文档 (focus-creative-games.github.io)

    HybridCLR(卧龙wolong)
    新手群:428404198
    进阶群:651188171

    仓库:
    HybridCLR
    https://github.com/focus-creative-games/hybridclr
    https://gitee.com/focus-creative-games/hybridclr

    il2cpp_plus
    https://github.com/focus-creative-games/il2cpp_plus
    https://gitee.com/focus-creative-games/il2cpp_plus


    你的点赞就是对博主的支持,有问题记得留言:

    Unity爱好者交流群:1040082875

    主页有联系方式。

    博主还有跟多宝藏文章等待你的发掘哦:

    专栏方向简介
    Unity3D开发小游戏小游戏开发教程分享一些使用Unity3D引擎开发的小游戏,分享一些制作小游戏的教程。
    Unity3D从入门到进阶入门从自学Unity中获取灵感,总结从零开始学习Unity的路线,有C#和Unity的知识。
    Unity3D之UGUIUGUIUnity的UI系统UGUI全解析,从UGUI的基础控件开始讲起,然后将UGUI的原理,UGUI的使用全面教学。
    Unity3D之读取数据文件读取使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。
    Unity3D之数据集合数据集合数组集合:数组、List、字典、堆栈、链表等数据集合知识分享。
    Unity3D之VR/AR(虚拟仿真)开发虚拟仿真总结博主工作常见的虚拟仿真需求进行案例讲解。
    Unity3D之插件插件主要分享在Unity开发中用到的一些插件使用方法,插件介绍等
    Unity3D之日常开发日常记录主要是博主日常开发中用到的,用到的方法技巧,开发思路,代码分享等
    Unity3D之日常BUG日常记录记录在使用Unity3D编辑器开发项目过程中,遇到的BUG和坑,让后来人可以有些参考。
  • 相关阅读:
    测试环境搭建教程(APP+WEB)
    DAMA-第三章(数据治理)
    计算机专业英语
    硬核!Apache Hudi Schema演变深度分析与应用
    Git的远程仓库
    puzzle(102.1)不规则数独、变种数独
    Spring Cloud项目(六)——使用sentinel作为流控管理
    详解VUE脚手架之安装
    SpringBoot 打包与运行
    基于单片机设计的气压与海拔高度检测计(采用MPL3115A2芯片实现)
  • 原文地址:https://blog.csdn.net/q764424567/article/details/124835067