ET 框架 HybridCLR 热更新集成包:包结构、运行时加载链路与编辑器工具链详解
2026/9/16 15:02:25 网站建设 项目流程

ET 框架 HybridCLR 热更新集成包:包结构、运行时加载链路与编辑器工具链详解

【免费下载链接】ETUnity3D Client And C# Server Framework项目地址: https://gitcode.com/GitHub_Trending/et/ET

导读

cn.etetet.hybridclr是 ET 框架中集成 HybridCLR 的官方包,为 Unity 客户端提供基于 il2cpp 改造的原生 C# 热更新能力。本文以 AGENTS.md 为核心骨架,结合仓库源码深入讲解该包的目录约定、运行时加载链路(补充元数据装载 → 程序集加载 → 入口启动)、运行时 API 配置项以及编辑器生成工具链,并给出代码规范(et-code)与构建验证(et-build)的使用约定,帮助读者理解并正确接入 ET + HybridCLR 热更新体系。

一、包概览:cn.etetet.hybridclr 在 ET 中的定位

按照 AGENTS.md 的概述,该包是HybridCLR 集成包,包含热更新相关的运行时插件编辑器工具三大部分。从 package.json 可以看到包的元信息:

字段说明
namecn.etetet.hybridclr包唯一标识,遵循 ET 包命名规范
version8.5.1当前仓库集成的 HybridCLR 版本
displayNameET.HybridCLRUnity 编辑器中的显示名
categoryRuntime归类为运行时包
keywordsHybridCLR / hotupdate / hotfix / focus-creative-games / code-philosophy检索关键词

HybridCLR 本身是对 il2cpp 运行时的扩充:它将纯 AOT(预编译)runtime 改造成"AOT + Interpreter"混合 runtime,从而原生支持动态加载 assembly,从底层实现 C# 热更新。ET 通过这个包把 HybridCLR 的运行时(Runtime/)、原生插件(Plugins/)、编辑器生成与打包工具(Scripts/Editor/)以及安装器(Editor/Installer等)统一收纳为一个可随包分发的 Unity Package。

仓库中该包的完整演进记录见 RELEASELOG.md,最新条目为 8.5.1(2025-08-25),修复了值类型上System.Activator.CreateInstance<T>()的 instinct 变换栈计算缺陷,并修复了 PInvokeAnalyzer 对 PInvoke 函数调用约定的计算问题;8.4.0 起支持自定义 image 格式,8.1.0 用std::unordered_set优化了Assembly.Load的耗时(降为原来的约 33%)。这些条目也印证了该包是"运行时 + 编辑器"双线并进维护的。

二、HybridCLR 技术原理:从纯 AOT 到 AOT + Interpreter 混合运行时

理解本包的目录结构与工具链,需要先掌握 HybridCLR 的核心原理。根据 README.md 的说明,HybridCLR 受 mono 的 mixed mode execution 技术启发,为 il2cpp 这类 AOT runtime 额外提供 interpreter 模块,使其从纯 AOT 变为"AOT + Interpreter"混合运行方式。具体做了五方面工作:

  1. 实现高效的元数据(dll)解析库
  2. 改造元数据管理模块,实现元数据的动态注册(补充元数据机制);
  3. 实现IL 指令集到自定义寄存器指令集的 compiler(即 IL 转换器);
  4. 实现高效的寄存器解释器(interpreter 执行引擎);
  5. 提供大量instinct 函数,提升解释器性能。

从使用者视角看,这些机制带来的直接能力包括:热更新代码与 AOT 代码无缝协作、支持继承/泛型/反射/多线程(volatile、ThreadStatic、async Task 等)、支持热更新 MonoBehaviour 与 ScriptableObject、支持MonoPInvokeCallback/PInvoke与原生代码交互、支持 DHE 差分混合执行与热重载等。版本支持方面,仓库 README 声明支持 2019.4.x、2020.3.x、2021.3.x、2022.3.x、2023.2.x、6000.x.y 等 LTS 版本以及所有 il2cpp 支持的平台(含团结引擎与鸿蒙平台)——具体以仓库实际集成的 8.5.1 为准。

在 ET 中,这套原理最终落到一个关键 API:HybridCLR.RuntimeApi.LoadMetadataForAOTAssembly(详见第四节)。

三、目录约定详解:编辑器代码、运行时与原生插件的组织方式

AGENTS.md 的「目录约定」是理解本包结构的关键,仓库实际目录如下:

Packages/cn.etetet.hybridclr/ ├── AGENTS.md / README.md / README_EN.md / RELEASELOG.md # 包文档与版本日志 ├── Data~/ # 编辑器工具使用的原生数据(.dll/.tpl/.json 等) ├── Editor/ # 原生工具与历史编辑器资源(UnityHook/7zip/UnityFS 等) ├── HybridCLR/ │ └── AssemblyReferenceToLoader.asmref # 程序集引用:汇入 ET.Loader ├── Plugins/ # dnlib.dll、LZ4.dll 等托管依赖 ├── Runtime/ # 运行时 API 与 ET.HybridCLR.asmdef └── Scripts/ ├── Editor/ # 编辑器 C# 代码(Commands/BuildProcessors/Settings 等) └── Model/ # 共享模型(如 PackageType.cs)

3.1Scripts/Editor:编辑器代码统一落点

按 AGENTS.md 约定,编辑器代码放在Scripts/Editor下,并通过AssemblyReference.asmref汇入ET.Editor;同时明确"不再使用包根Editor目录承载编辑器 C# 代码"。对照仓库实际布局,包根Editor/目录保留的是非 C# 的原生资源与工具(如3rds/UnityHook下的Utils.cpplibMonoHookUtils_OSX.dylib及构建脚本,3rds/7zip3rds/UnityFS等第三方组件),而全部编辑器 C# 源码都集中在 Scripts/Editor/Share 目录树中:

  • Settings/HybridCLRSettings.cs(配置项定义)、HybridCLRSettingProvider.cs(Project Settings 面板)、MenuProvider.cs(菜单项);
  • Commands/PrebuildCommandCompileDllCommandStripAOTDllCommandAOTReferenceGeneratorCommandLinkGeneratorCommandMethodBridgeGeneratorCommandIl2CppDefGeneratorCommand
  • BuildProcessors/CheckSettingsFilterHotFixAssembliesPatchScriptingAssemblyListCopyStrippedAOTAssembliesScriptingAssembliesJsonPatcherAddLil2cppSourceCodeToXcodeproj*(按 Unity 2019/2020-2021/2022/2023+ 分版本实现);
  • AOT/AOTAssemblyMetadataStripper(裁剪 AOT dll)、AnalyzerGenericReferenceWriter
  • Link/MethodBridge/Il2CppDef/Meta/ABI/Installer/HotUpdate/MissingMetadataChecker)、Template/等模块目录。

这种"包根只放原生资源、C# 编辑器代码全部收进Scripts/Editor并由 asmref 汇入ET.Editor"的组织方式,是为了让包内的编辑器代码真正进入 ET 的主编辑器程序集,从而能调用 ET.Editor 提供的构建管线与工具函数。

3.2HybridCLR/AssemblyReferenceToLoader.asmref:运行时汇入 ET.Loader

包根下还有一个关键程序集引用文件 AssemblyReferenceToLoader.asmref,它把本包的运行时程序集(ET.HybridCLR.asmdef)汇入ET.Loader。这正是 CodeLoader.cs 中可以直接调用HybridCLR.RuntimeApi.LoadMetadataForAOTAssembly(...)的编译期前提——运行时加载逻辑与 HybridCLR API 在同一程序集内(详见第四节)。

3.3Runtime:运行时 API 与程序集定义

Runtime 目录包含运行所需的全部 API 文件:

文件职责
ET.HybridCLR.asmdef运行时程序集定义
RuntimeApi.cs热更新入口 API(补充元数据装载、预编译、运行参数读写)
RuntimeOptionId.cs解释器运行参数枚举(栈大小、方法体缓存、内联深度等)
HomologousImageMode.cs补充元数据装载模式
LoadImageErrorCode.cs装载返回的错误码
ReversePInvokeWrapperGenerationAttribute.cs反向 P/Invoke 包装生成标记

3.4Plugins:托管第三方依赖

Plugins 目录提供编辑器阶段的托管依赖:dnlib.dll(.NET 元数据处理库,供Meta/MethodBridge/Link/等编辑器模块解析程序集)与LZ4.dll(LZ4 压缩,供3rds/UnityFS处理 AssetBundle 相关格式)。

四、运行时加载链路:CodeLoader 与补充元数据装载

AGENTS.md 概述中提到的"运行时"能力,在 ET 中由 CodeLoader.cs 承担具体落地。其Start()方法是热更新加载的完整链路,可拆分为四个阶段:

阶段一:下载热更新资源。await DownloadAsync()获取 dll/pdb 等热更资源(见 CodeLoader.cs)。

阶段二:装载 AOT 补充元数据(核心热更步骤)。在非编辑器环境(#if !UNITY_EDITOR)下,遍历this.aotDlls中的每个 TextAsset,调用:

HybridCLR.RuntimeApi.LoadMetadataForAOTAssembly(textAsset.bytes, HybridCLR.HomologousImageMode.SuperSet);

见 CodeLoader.cs。这一步的作用是把AOT 程序集的补充元数据动态注册进 il2cpp 元数据系统,使热更新代码可以正常使用泛型实例化、反射等需要完整元数据的特性。装载模式使用HomologousImageMode.SuperSet(超集模式),即补充元数据 dll 为原始 AOT dll 的超集;LoadImageErrorCode枚举则定义了装载失败时的错误码(如 OK/错误码,见 LoadImageErrorCode.cs)。

阶段三:动态加载热更新程序集。依次Assembly.Load(modelAssBytes, modelPdbBytes)加载ET.Model/ET.ModelView,并通过LoadHotfix()加载ET.Hotfix/ET.HotfixView(pdb 同时加载以保留栈调试行号信息),见 CodeLoader.cs 与 CodeLoader.cs。

阶段四:装配并启动入口。将加载出的程序集列表交给CodeTypes单例注册类型,然后通过反射调用热更新程序集中的ET.Entry.Start启动游戏逻辑(见 CodeLoader.cs)。

需要特别注意的是,仓库代码注释提醒:编辑器调试时可改用File.ReadAllBytes(Path.Combine(Define.CodeDir, "ET.Model.dll.bytes"))直接读取本地生成的热更 dll(见 CodeLoader.cs),但真正打包发布时必须使用下载/内置的热更资源路径

五、运行时 API 与解释器运行参数

RuntimeApi.cs 是热更新运行时的主要编程接口,按功能分组如下:

补充元数据装载。LoadMetadataForAOTAssembly(byte[] dllBytes, HomologousImageMode mode)返回LoadImageErrorCode。注意它在编辑器下是空实现(return LoadImageErrorCode.OK),仅在真机/发布环境通过[MethodImpl(MethodImplOptions.InternalCall)]桥接到 native 层。

预编译(Prejit)。PreJitMethod(MethodInfo method)PreJitClass(Type type)用于在游戏启动时提前 JIT 解释器方法,规避首次调用时的解释开销;返回true表示成功预编译,false表示无法预编译。编辑器下同样为空实现。

运行参数读写。通过GetRuntimeOption(RuntimeOptionId)/SetRuntimeOption(RuntimeOptionId, int)读写解释器参数,并封装了如GetInterpreterThreadObjectStackSize()等便捷方法。RuntimeOptionId.cs 定义了全部参数:

枚举值数值含义
InterpreterThreadObjectStackSize1解释器线程对象栈的 StackObject 数量上限(实际内存约 size×8 字节)
InterpreterThreadFrameStackSize2解释器线程帧栈大小
ThreadExceptionFlowSize3线程异常流转栈大小
MaxMethodBodyCacheSize4方法体缓存上限
MaxMethodInlineDepth5方法内联最大深度
MaxInlineableMethodBodySize6可内联方法体的最大体积

这些参数与 RELEASELOG 中 7.0.0(新增方法内联)与 7.1.0(默认MaxInlineableMethodBodySize由 16 调整为 32)的演进一一对应,可以在游戏启动早期按项目负载特征调优。

反向 P/Invoke。ReversePInvokeWrapperGenerationAttribute用于标记需要生成反向 P/Invoke 包装的委托,配合编辑器端MethodBridge生成器支持从 native(如 Lua/JS)回调热更新 C# 方法。

六、编辑器工具链:生成命令、打包处理器与配置项

6.1 命令菜单(Commands)

编辑器菜单HybridCLR/Generate/*对应 Commands 下的各生成命令,典型工作流为:

  1. PrebuildCommand—— 生成前的预处理(如检查 HybridCLR 是否已安装);
  2. CompileDllCommand—— 把热更新程序集编译为目标平台的 dll;
  3. StripAOTDllCommand—— 裁剪 AOT 程序集,产出补充元数据所需的精简 dll(配合AOTAssemblyMetadataStripper去除非泛型函数元数据);
  4. AOTReferenceGeneratorCommand—— 分析热更新程序集对 AOT 泛型类型/方法的引用,生成补充元数据清单(AOTGenericReferences.cs);
  5. LinkGeneratorCommand—— 扫描热更新程序集自动生成link.xml,防止 AOT 链接裁剪掉运行所需的元数据;
  6. MethodBridgeGeneratorCommand—— 生成托管/native 双向调用的桥接函数(MethodBridge);
  7. Il2CppDefGeneratorCommand—— 生成 il2cpp 定义相关代码(UnityVersion.h.tplAssemblyManifest.cpp.tplMethodBridge.cpp.tpl等模板来自Data~目录)。

6.2 打包处理器(BuildProcessors)

BuildProcessors 通过 UnityIPreprocessBuildWithReport等回调在打包阶段自动工作:CheckSettings校验 Scripting Backend 必须为 il2cpp 及 API 兼容级别;FilterHotFixAssemblies从构建中过滤热更程序集;PatchScriptingAssemblyList/ScriptingAssembliesJsonPatcher修正scriptingassemblies.json,把热更程序集从 AOT 编译列表剔除;CopyStrippedAOTAssemblies拷贝裁剪后的 AOT dll 供运行时装载补充元数据;AddLil2cppSourceCodeToXcodeproj*负责在 iOS/macOS 导出 Xcode 工程时把 HybridCLR 的 native 源码(libil2cpp 扩展)注入工程。

6.3 配置项(HybridCLRSettings)

编辑器配置定义在 HybridCLRSettings.cs,序列化存储于 Unity 工程根目录ProjectSettings/HybridCLRSettings.asset(见该文件GetFilePath()实现,L71-L74),并通过HybridCLRSettingProvider在 Project Settings 面板中展示。核心字段及默认值:

字段默认值说明
enabletrue是否启用 HybridCLR
useGlobalIl2cppfalse是否使用 Unity 安装目录中的全局 il2cpp
hybridclrRepoURL/il2cppPlusRepoURLgitee 仓库地址安装器拉取 hybridclr / il2cpp_plus 源码的仓库 URL
hotUpdateAssemblyDefinitions热更新程序集的 asmdef 资源列表
hotUpdateAssemblies热更新程序集名列表(不带 .dll 后缀)
preserveHotUpdateAssemblies需保留的热更新程序集名
hotUpdateDllCompileOutputRootDirHybridCLRData/HotUpdateDlls热更 dll 编译输出目录
externalHotUpdateAssembliyDirs外部热更程序集搜索路径
strippedAOTDllOutputRootDirHybridCLRData/AssembliesPostIl2CppStrip裁剪后 AOT dll 输出目录
patchAOTAssemblies补充元数据程序集名列表
outputLinkFileHybridCLRGenerate/link.xml自动生成的 link.xml 输出路径
outputAOTGenericReferenceFileHybridCLRGenerate/AOTGenericReferences.cs自动生成的泛型引用清单输出路径
maxGenericReferenceIteration10热更程序集中泛型方法搜索的最大迭代次数
maxMethodBridgeGenericIteration10AOT 程序集中方法桥接泛型搜索的最大迭代次数

6.4 安装器与体检工具

Installer(InstallerWindow/InstallerController/BashUtil)提供图形化安装入口,负责把 HybridCLR 的 libil2cpp 扩展源码下载并接入 Unity 安装目录;HotUpdate/MissingMetadataChecker则用于在开发期检测"热更新代码引用了 AOT 泛型但缺少补充元数据"等典型配置遗漏,避免发布后才暴露运行时错误。

七、代码规范与构建验证:AGENTS.md 引用的两个 skill

AGENTS.md 的「详细文档」部分将本包的开发工作流锚定到 harness 的两个 skill,这两者共同构成 HybridCLR 包的维护规范:

7.1 代码规范:/et-code

et-code SKILL.md 覆盖 ET 框架 C# 代码编写与审查流程,对本包(以及依赖它的热更新模块)的约束要点包括:

  • 新建或修改Entity/Component/System/Helper、消息 Handler、程序集与包依赖时启用;纯测试、配置导出或 Unity 编辑器操作场景不加载该 skill;
  • 改动前先确认代码所在 package、程序集层级和包内AGENTS.md规则;判断是否影响 Entity/System 分离、HandlerRun规范、包依赖单向与 Module analyzer;
  • 涉及async/await/ETTask/EntityRef时叠加 et-async skill;
  • 默认"一类一文件";严禁 AI 手工生成.meta或手工修改.csproj,移动 C# 文件必须同步移动.meta以保留 GUID——这与本包"目录约定"中 asmref/asmdef 的组织方式直接相关;
  • 输出要求:说明代码落点、包依赖、程序集层次是否正确,是否影响.meta/.csproj/ Unity 刷新或工程文件生成,是否引入新的 analyzer 风险、静态状态风险或模块边界问题。

7.2 构建验证:/et-build

et-build SKILL.md 提供编译、Proto 导出、服务器启动与发布的唯一标准入口:

  • 编译与分析器验证统一使用dotnet build ET.sln不单独编译包或 IDE 私有方案
  • Proto 导出:dotnet ./Bin/ET.Proto2CS.dll
  • 启动服务器:dotnet ./Bin/ET.App.dll --Console=1(必须在 Unity 项目根目录启动,不在Bin/目录启动,运行前先清理旧Logs/);
  • 发布:pwsh -ExecutionPolicy Bypass -File ./Scripts/Publish.ps1
  • 特别提醒:Model / Hotfix 程序集不能用 IDE 编译,必须走项目规定的 Unity / ET 编译入口——这正是 HybridCLR 热更 dll 由编辑器CompileDllCommand生成的原因。

八、实践小结与接入注意事项

综合以上分析,在 ET 项目中接入cn.etetet.hybridclr时应把握以下要点:

  1. 结构认知:编辑器 C# 代码统一在 Scripts/Editor,通过 asmref 汇入ET.Editor;运行时通过 AssemblyReferenceToLoader.asmref 汇入ET.Loader;包根Editor/只保留原生工具资源。
  2. 加载顺序不可颠倒:真机加载必须"先装载 AOT 补充元数据(HomologousImageMode.SuperSet)→ 再Assembly.Load热更程序集 → 最后反射调用ET.Entry.Start",参见 CodeLoader.cs。
  3. 配置与生成配套HybridCLRSettings中的热更程序集列表、补充元数据列表、link.xml 与 AOTGenericReferences 输出路径必须与Generate/*命令的执行结果保持一致,否则会出现 MissingMetadata / 链接裁剪类问题。
  4. 发布约束:以仓库实际集成的 8.5.1 版本为准,关注 RELEASELOG.md 中的关键修复(如打包时Texture Compression设置被改动、WebGL 平台scriptingassemblies.json路径等问题),升级包后需重新执行安装器并重新生成。
  5. 开发纪律:遵循et-code的代码规范(.meta 同步、一类一文件、包依赖单向)与et-build的构建入口(dotnet build ET.sln、Publish.ps1),避免绕过既定管线导致热更链路不一致。

【免费下载链接】ETUnity3D Client And C# Server Framework项目地址: https://gitcode.com/GitHub_Trending/et/ET

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询