HybridCLR¶
核心机制¶
HybridCLR 不是“在 IL2CPP 上开一个 JIT”,而是把 IL2CPP 从纯 AOT 运行时扩展为 AOT + Interpreter 的混合运行时:1
这样既保留了 iOS、主机等平台对 JIT 的限制,又能在运行时加载新的 C# 程序集。
基础配置¶
Scripting Backend切换为IL2CPP;Api Compatibility Level使用.NET 4.x或.NET Framework;- 按项目版本安装 HybridCLR 包与生成器;
- 热更程序集与 AOT 主工程使用兼容的 Unity / .NET API 基线;
- 在目标平台上验证 GC、线程和热更程序集加载顺序。
配置只是起点
真正决定上线稳定性的是程序集划分、AOT 泛型补充、裁剪保护、构建产物校验与回滚策略,而不是几个 Inspector 选项。
补充元数据¶
AOT 泛型与某些类型实例在编译期未出现时,IL2CPP 不会生成对应实现。HybridCLR 通过补充元数据(Supplementary Metadata)让解释器能够构造这些类型。
构建时通常需要:
- 收集热更程序集引用到的 AOT 泛型与类型;
- 生成补充元数据 DLL;
- 随包或随热更内容分发;
- 加载热更程序集前调用运行时 API 加载元数据;
- 对缺失元数据做启动期校验,而不是等玩家进入玩法后崩溃。
// 结构示意:实际 API 名称与调用顺序以项目使用的 HybridCLR 版本为准
RuntimeApi.LoadMetadataForAOTAssembly(
metadataDllBytes,
HomologousImageMode.SuperSet);
程序集切分¶
适合放进热更程序集的内容:
- 活动玩法与业务逻辑;
- UI 流程与配置解析;
- 低风险的战斗规则;
- 需要快速修复的模块。
更适合留在 AOT 主工程的内容:
- 引擎底层封装;
- 高频数学与物理热点;
- 启动引导与热更加载器;
- 平台 SDK 桥接;
- 安全与签名校验。
切分原则不是“能热更的都热更”,而是把高频性能路径与低稳定性依赖留在 AOT 侧。
裁剪与链接保护¶
IL2CPP 的 Managed Stripping 会删除未被静态引用的代码。热更程序集在构建期不可见,反射与序列化使用的类型尤其容易被裁剪。
需要:
- 使用
link.xml保护类型与成员; - 用生成的 AOT 引用代码显式引用泛型实例;
- 在构建后检查裁剪日志;
- 在真机 Development Build 上跑完整热更加载流程;
- 对缺失类型记录清晰错误,而不是静默回退。
加载与回滚¶
更完整的下载、裁剪、回滚和真机测试问题,整理在热更新常见问题与排查。
热更清单至少包含:
- 程序集 ID、版本、哈希;
- 对应客户端版本范围;
- 补充元数据版本;
- 依赖项与加载顺序;
- 失败回退策略。
性能与兼容性边界¶
| 关注点 | 说明 |
|---|---|
| 解释执行开销 | 热更代码通常慢于 AOT,不应承担极端热点 |
| 跨程序集调用 | 频繁反射与动态调用会增加开销 |
| 泛型组合 | 缺失元数据会在运行时暴露 |
| 内存 | 程序集、元数据与解释器状态会占用额外内存 |
| 平台 | 必须逐平台验证裁剪、启动与商店审核要求 |
| 调试 | 真机日志、符号与异常栈需要保留 |
选择建议¶
HybridCLR 适合希望统一使用 C#、又需要接近原生 IL2CPP 运行方式的项目;ILRuntime 更偏向独立解释器与跨域绑定模型;xLua 等 Lua 方案则把热更边界放在脚本层。最终选择应基于团队语言能力、性能热点、包体、平台限制与发布节奏,而不是只看“谁更快”的单一指标。