基于 ET 框架接入 HybridCLR:Unity 全平台原生 C 热更新方案实践
基于 ET 框架接入 HybridCLRUnity 全平台原生 C# 热更新方案实践【免费下载链接】ETUnity3D Client And C# Server Framework项目地址: https://gitcode.com/GitHub_Trending/et/ET导读本文以 ET 仓库中的cn.etetet.hybridclr包版本 8.5.1为主线系统讲解 HybridCLR 这一 Unity 全平台原生 C# 热更新方案的核心原理、关键特性以及它在 ET 框架中的完整落地方式——包括 HybridCLRSettings.asset 的配置项、RuntimeApi.cs 的运行时 API、CodeLoader.cs 中的热更程序集加载流程以及编辑器侧的一键编译与构建命令。阅读完本文你将掌握在 ET 项目上启用 HybridCLR 的完整配置路径、理解 AOT 与解释器混合运行时的底层机制并能结合仓库源码看懂热更新程序集从编译、裁剪到运行时装载的全链路。HybridCLR 是什么从纯 AOT 到 AOT Interpreter 的混合运行时HybridCLR 是官方 README 中定位为“特性完整、零成本、高性能、低内存”的 Unity 全平台原生 C# 热更新解决方案。它的本质是扩充 il2cpp 运行时代码将原本纯 AOT 的运行时改造成 “AOT Interpreter” 混合运行时从而原生支持动态加载 assembly从底层彻底支持 C# 代码热更新。这一能力带来的直接价值是采用 HybridCLR 的游戏不仅能在 Android 上运行也能在 iOS、主机、WebGL 等所有 il2cpp 支持的平台上高效运行热更新代码而开发者在编写热更代码时几乎不需要改变日常的编码习惯。在 ET 仓库中HybridCLR 被打包为独立的 UPM 包cn.etetet.hybridclrdisplayName 为ET.HybridCLRcategory 为 Runtime其 package.json 中给出的 keywords 为HybridCLR、hotupdate、hotfix、focus-creative-games、code-philosophy。根据包内 AGENTS.md 的说明该包“包含热更新相关运行时、插件和编辑器工具”其中Scripts/Editor下的编辑器代码通过AssemblyReference.asmref汇入ET.Editor程序集。HybridCLR 的核心特性官方 README.md 对 HybridCLR 的能力做了系统列举以下逐条展开并结合仓库源码印证近乎完整的 ECMA-335 规范实现HybridCLR 近乎完整地实现了 ECMA-335 规范仅存在极少量官方文档列出的不支持特性。这意味着热更新代码与 AOT 代码可以无缝协作开发者可以随意编写继承、泛型、反射等代码不需要额外写特殊代码也没有代码生成步骤。零学习成本与无缝 AOT/热更互操作对绝大多数开发者来说接入 HybridCLR 后写代码近乎没有限制热更新代码与 AOT 代码可以自由互相调用、互相继承泛型、反射、Lambda、LINQ 等语法都正常工作。官方将其描述为“零学习和使用成本”。完整的多线程支持HybridCLR 完全支持多线程包含且不限于volatile、ThreadStatic、async Task等特性。仓库 RuntimeApi.cs 中也提供了与解释器线程栈相关的配置 API见下文“运行时 API”一节进一步印证了解释器线程模型的存在。几乎完全兼容 Unity 工作流支持热更新MonoBehaviour、ScriptableObject、DOTS 技术资源上挂载的热更新脚本可以被正确实例化。这点对 ET 这类以组件化、实体系统为核心的框架尤为重要——热更代码与 Unity 生命周期深度绑定是常态。高效的寄存器解释器与内存占用HybridCLR 实现了一个高效的寄存器解释器热更新脚本中定义的类与普通 C# 类占用相同的内存空间。官方提供了独立的性能测试报告与内存占用报告可在官方文档站查看本文不展开外部链接。原生互操作能力支持MonoPInvokeCallback可以与 native 代码或其他语言如 Lua、JavaScript、Python良好交互支持PInvoke支持一些 il2cpp 本身不支持的指令如__makeref、__reftype、__refvalue。独创的 DHE 差分混合执行技术官方 README 特别强调的Differential Hybrid ExecutionDHE技术允许对 AOT dll 任意增删改未改动的函数继续以 AOT 方式运行变化或新增的函数以 interpreter 模式运行从而让热更新游戏逻辑的运行性能基本达到原生 AOT 的水平。热重载、动态 Hotfix 与 dll 加密支持热重载技术可以 100% 卸载程序集支持动态 Hotfix可在运行过程中无感修复代码 bug支持现代的 dll 加密技术保障代码安全。工作原理从 mono 混合执行到自定义寄存器解释器HybridCLR 的设计灵感来自 mono 的 mixed mode execution 技术为 il2cpp 这类 AOT 运行时额外提供一个 interpreter 模块将其从纯 AOT 运行时改造为 “AOT Interpreter” 混合运行方式。官方 README 将其核心工作归纳为以下五点实现了一个高效的元数据dll解析库改造了元数据管理模块实现元数据的动态注册实现了一个将 IL 指令集编译为自定义寄存器指令集的 compiler实现了一个高效的寄存器解释器额外提供大量 instinct 函数提升解释器性能。这套机制在 ET 仓库中有直观的对应物Data~ 目录存放了构建期所需的支撑文件如ModifiedUnityAssemblies中针对 2019.4.40 的Unity.IL2CPP补丁 dll、NetStandard下的netstandard2.0/2.1dll、Templates下的AssemblyManifest.cpp.tpl、MethodBridge.cpp.tpl、UnityVersion.h.tpl以及hybridclr_version.json版本信息Scripts/Editor/Share/Il2CppDef 与 MethodBridge 目录则对应着“元数据定义生成”与“方法桥生成”等构建期步骤。在 ET 项目中的配置HybridCLRSettings.asset 全字段解析HybridCLR 的全部构建期配置集中在ProjectSettings/HybridCLRSettings.asset由 HybridCLRSettings.cs 定义并序列化。该文件通过InternalEditorUtility.LoadSerializedFileAndForget/SaveToSerializedFileAndForget读写配置类是继承ScriptableObject的HybridCLRSettings并以单例Instance暴露给编辑器工具。以下是 ET 仓库中该配置文件的真实内容enable: 1 useGlobalIl2cpp: 0 hybridclrRepoURL: https://gitee.com/focus-creative-games/hybridclr il2cppPlusRepoURL: https://gitee.com/focus-creative-games/il2cpp_plus hotUpdateAssemblyDefinitions: [] hotUpdateAssemblies: - ET.Model - ET.Hotfix - ET.ModelView - ET.HotfixView preserveHotUpdateAssemblies: [] hotUpdateDllCompileOutputRootDir: HybridCLRData/HotUpdateDlls externalHotUpdateAssembliyDirs: - Temp/Bin/Debug strippedAOTDllOutputRootDir: HybridCLRData/AssembliesPostIl2CppStrip patchAOTAssemblies: - ET.Loader.dll - ET.Core.dll - ET.YooAssets.dll - MongoDB.Bson.dll - CommandLine.dll - System.dll - System.Core.dll - mscorlib.dll - ET.MemoryPack.dll - System.Runtime.CompilerServices.Unsafe.dll - ET.Recast.dll outputLinkFile: HybridCLR/link.xml outputAOTGenericReferenceFile: HybridCLR/AOTGenericReferences.cs maxGenericReferenceIteration: 10 maxMethodBridgeGenericIteration: 10各字段含义依据 HybridCLRSettings.cs 中的 Tooltip 注释字段类型含义ET 仓库当前值enablebool是否启用 HybridCLR1启用useGlobalIl2cppbool是否使用 Unity 编辑器安装目录中的 il2cpp0使用本地拷贝hybridclrRepoURLstringhybridclr 仓库地址用于拉取本地 hybridclr 源码gitee 官方仓库il2cppPlusRepoURLstringil2cpp_plus 仓库地址gitee 官方仓库hotUpdateAssemblyDefinitionsAssemblyDefinitionAsset[]热更新程序集对应的 asmdef 资产空数组hotUpdateAssembliesstring[]热更新程序集名称不带 .dll 后缀ET.Model、ET.Hotfix、ET.ModelView、ET.HotfixViewpreserveHotUpdateAssembliesstring[]需要保留的热更新程序集名称空hotUpdateDllCompileOutputRootDirstring编译热更新程序集的输出根目录HybridCLRData/HotUpdateDllsexternalHotUpdateAssembliyDirsstring[]外部热更新程序集的搜索路径Temp/Bin/Debug即 VS/Rider 生成的 dll 目录strippedAOTDllOutputRootDirstringil2cpp 裁剪后 AOT 程序集的输出根目录HybridCLRData/AssembliesPostIl2CppStrippatchAOTAssembliesstring[]需要补充元数据的 AOT 程序集名称带 .dll 后缀ET.Loader.dll、ET.Core.dll、ET.YooAssets.dll、MongoDB.Bson.dll、CommandLine.dll、System.dll、System.Core.dll、mscorlib.dll、ET.MemoryPack.dll、System.Runtime.CompilerServices.Unsafe.dll、ET.Recast.dlloutputLinkFilestring扫描热更新程序集自动生成的 link.xml 输出路径HybridCLR/link.xmloutputAOTGenericReferenceFilestring自动生成的 AOTGenericReferences.cs 输出路径HybridCLR/AOTGenericReferences.csmaxGenericReferenceIterationint搜索热更新程序集中泛型方法的最大迭代次数10maxMethodBridgeGenericIterationint搜索 AOT 程序集中方法桥泛型方法的最大迭代次数10其中两点值得特别注意hotUpdateAssemblies恰好对应 ET 框架的四个热更新程序集ET.Model、ET.Hotfix、ET.ModelView、ET.HotfixView这与 CodeLoader.cs 中运行时动态加载的程序集一一对应patchAOTAssemblies中除了mscorlib、System等基础库还包含ET.Core、ET.Loader、ET.Recast、MongoDB.Bson、ET.MemoryPack等 ET 自身及依赖的 AOT 程序集——这些程序集的补充元数据正是为了支撑热更代码中对这些 AOT 类型尤其是泛型实例化与反射的访问。运行时 API 与热更新程序集的加载流程RuntimeApi 核心接口RuntimeApi.cs 定义了运行期与 HybridCLR 解释器交互的静态 API其关键方法如下LoadMetadataForAOTAssembly(byte[] dllBytes, HomologousImageMode mode)加载 AOT 程序集的补充元数据。返回LoadImageErrorCode表示结果。在UNITY_EDITOR下为空实现直接返回OK真机!UNITY_EDITOR下通过[MethodImpl(MethodImplOptions.InternalCall)]调用原生实现PreJitMethod(MethodInfo method)/PreJitClass(Type type)预 JIT 单个方法或整个类的所有方法以避免首次运行时的 JIT 开销。返回true表示 JIT 成功false表示无法 JITGetInterpreterThreadObjectStackSize()/SetInterpreterThreadObjectStackSize(int size)读取/设置解释器线程栈中 StackObject 的最大数量size * 8为最终内存占用GetInterpreterThreadFrameStackSize()/SetInterpreterThreadFrameStackSize(int size)读取/设置解释器线程函数帧数量sizeof(InterpreterFrame) * size为最终内存占用SetRuntimeOption(RuntimeOptionId, int)/GetRuntimeOption(RuntimeOptionId)通用运行时选项读写编辑器下维护在DictionaryRuntimeOptionId, int中真机下走原生实现。同源镜像模式与错误码HomologousImageMode定义了两个模式Consistent补充元数据与 AOT 程序集完全一致SuperSet补充元数据是 AOT 程序集的超集。ET 项目在运行时实际使用的是SuperSet模式见下文 CodeLoader 代码。LoadImageErrorCode则定义了元数据加载的完整错误码便于接入方排查问题public enum LoadImageErrorCode { OK 0, BAD_IMAGE, // 无效的 dll 文件 NOT_IMPLEMENT, // 未实现的特性 AOT_ASSEMBLY_NOT_FIND, // 未找到 AOT 程序集 HOMOLOGOUS_ONLY_SUPPORT_AOT_ASSEMBLY, // 只能为非 AOT 程序集加载补充元数据 HOMOLOGOUS_ASSEMBLY_HAS_LOADED, // 同一程序集的补充元数据已加载 INVALID_HOMOLOGOUS_MODE, // 无效的同源镜像模式 PDB_BAD_FILE, // 无效的 pdb 文件 UNKNOWN_IMAGE_FORMAT, UNSUPPORT_FORMAT_VERSION, UNMATCH_FORMAT_VARIANT, };ET 的启动加载流程CodeLoaderET 框架把 HybridCLR 的运行时调用集成在 CodeLoader.cs 的Start()中。真机环境下#if !UNITY_EDITOR加载顺序如下从下载好的 dll 字节流中取出ET.Model.dll、ET.Model.pdb、ET.ModelView.dll、ET.ModelView.pdb遍历aotDlls即构建期拷贝的 AOT 程序集对每个TextAsset调用foreach (var kv in this.aotDlls) { TextAsset textAsset kv.Value; HybridCLR.RuntimeApi.LoadMetadataForAOTAssembly(textAsset.bytes, HybridCLR.HomologousImageMode.SuperSet); }这一步为patchAOTAssemblies中列出的 AOT 程序集补齐补充元数据通过Assembly.Load(modelAssBytes, modelPdbBytes)动态加载 Model / ModelView 程序集调用LoadHotfix()加载ET.Hotfix/ET.HotfixViewEditor 下直接引用已编译程序集热重载时则从 Define.CodeDir 指定的Packages/cn.etetet.loader/Bundles/Code目录读取 dll 字节流将全部程序集交给CodeTypes注册并通过new StaticMethod(hotfixAssembly, ET.Entry, Start)反射调用热更入口ET.Entry.Start。从源码结构可以清晰地看出先补 AOT 元数据、再加载热更程序集、最后反射启动是 ET HybridCLR 的标准启动时序这也解释了为什么patchAOTAssemblies的配置必须在构建期就准备好。编辑器构建流程与菜单命令HybridCLR 的构建期能力全部由编辑器代码提供位于 Scripts/Editor/Share/Commands 与 BuildProcessors 等目录。编译热更新 dllCompileDllCommand.cs 提供了HybridCLR/CompileDll菜单按优先级组织ActiveBuildTargetpriority 100、ActiveBuildTarget_Release102、ActiveBuildTarget_Development104针对当前激活平台编译并可选择 Release / Development 变体Win32/Win64/MacOS/Linux200~203桌面平台Android210、IOS220、WebGL230移动与网页平台。编译输出的 dll 默认写入HybridCLRData/HotUpdateDlls即配置中的hotUpdateDllCompileOutputRootDir。其他关键构建命令Commands 目录 中还包含PrebuildCommand构建前准备如初始化 hybridclr 本地仓库源码、修改 il2cpp 相关文件AOTReferenceGeneratorCommand扫描热更新程序集生成AOTGenericReferences.csIl2CppDefGeneratorCommand生成UnityVersion.h等 il2cpp 定义文件MethodBridgeGeneratorCommand生成MethodBridge.cpp用于 AOT 与解释器之间的方法桥接LinkGeneratorCommand生成link.xml防止 AOT 程序集被错误裁剪StripAOTDllCommand对 il2cpp 裁剪后的 AOT dll 进行提取输出到HybridCLRData/AssembliesPostIl2CppStrip。构建处理器BuildProcessorsBuildProcessors 目录实现了挂接到 Unity 构建流程的IPreprocessBuildWithReport/IPostprocessBuildWithReport处理器例如CopyStrippedAOTAssemblies将 il2cpp 裁剪后的 AOT 程序集拷贝到配置的输出目录PatchScriptingAssemblyList/ScriptingAssembliesJsonPatcher在构建产物中补丁scriptingAssemblies.json把热更程序集排除出 AOT 编译列表FilterHotFixAssemblies过滤热更程序集确保它们不被静态链接进主包CheckSettings构建前校验配置合法性各 Unity 版本对应的AddLil2cppSourceCodeToXcodeproj*为 iOS 工程注入 il2cpp 修改源码。安装器与第三方支撑Installer 提供安装窗口与控制逻辑InstallerWindow、InstallerController用于首次接入时拉取并安装本地 hybridclr / il2cpp_plus 源码UnityHook 提供运行时 hook 能力如CopyStrippedAOTAssembliesHook、PatchScriptingAssembliesJsonHook、GetIl2CppFolderHookUnityFS 与 7zip 分别用于解析 Unity 资源包格式与 LZMA 压缩是补丁与裁剪流程的底层依赖。支持的版本与平台官方 README 声明支持的 Unity 版本为 2019.4.x、2020.3.x、2021.3.x、2022.3.x、2023.2.x、6000.x.y 的所有 LTS 版本支持所有 il2cpp 支持的平台并支持团结引擎Tuanjie Engine与鸿蒙平台。仓库Data~中保留了针对 2019.4.40 的Unity.IL2CPP修改版 dll构建处理器也按 Unity 版本分别实现了 xcodeproj 补丁逻辑2019 / 2020~2021 / 2022 / 2023说明该包对多版本 Unity 做了显式的兼容适配。稳定性与商业应用情况官方声明官方 README 声称 HybridCLR 已被大量商业项目验证达到大中型商业项目对稳定性与性能的要求并列举了 iOS 免费榜与各类重度游戏品类的上线案例。需要说明的是这些商业数据与项目清单属于 HybridCLR 官方在文档站官方文档、商业项目案例、商业化支持页面中对外发布的信息并非本仓库内部代码可验证的事实引用时应以官方渠道为准。对于接入决策而言建议在自有设备与目标平台特别是 iOS 与 WebGL上自行进行性能与稳定性验证。许可证HybridCLR 采用 MIT 许可证见包内 LICENSE这也是它能够以源码形式完整打入 ET 的 UPM 包并随项目分发的前提之一。仓库中的 README_EN.md 提供了英文版介绍RELEASELOG.md 记录了版本迭代历史可作为后续升级与排查的参考。小结ET HybridCLR 热更新的完整链路将本文内容串联起来ET 项目使用 HybridCLR 的完整链路是配置在 HybridCLRSettings.asset 中声明四个热更程序集与patchAOTAssemblies列表编译通过HybridCLR/CompileDll菜单CompileDllCommand.cs编译出热更 dll构建BuildProcessors在 Unity 打包时完成 AOT 裁剪、AOT dll 提取、scriptingAssemblies.json补丁等处理运行时真机启动时 CodeLoader.cs 先调用LoadMetadataForAOTAssembly(..., SuperSet)补齐 AOT 元数据再Assembly.Load动态装载热更程序集最后反射调用ET.Entry.Start进入游戏逻辑热更线上发布新版本 dll 与补充元数据客户端下载后重复步骤 4 即可完成代码热更新。这套方案的价值在于热更代码与 AOT 代码同属原生 C#无需引入 Lua 等第二语言泛型、反射、多线程、Unity 生命周期等能力完整保留是 ET 这类以 C# 全栈著称的框架保持“客户端代码可热更”的关键底座。【免费下载链接】ETUnity3D Client And C# Server Framework项目地址: https://gitcode.com/GitHub_Trending/et/ET创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →