HybridCLR + YooAsset + UniTask 集成解决方案

April 25, 2026 · View on GitHub

Unity 2022.3 HybridCLR YooAsset UniTask License English


目录导航


项目简介

HybridCLR + YooAsset + UniTask是一个专为 Unity 开发者设计的高性能热更新与资源管理框架。

  • 热更新 DLL 编译与拷贝
  • AOT 元数据检查与补充流程
  • 资源打包与脚本打包联动
  • Sample 快照导入与路径规范化
  • 一体化编辑器构建窗口

基于 Unity 2022.3、HybridCLR 8.2.0、YooAsset 2.3.9、UniTask 2.5.10 版本整合。


核心概念

Assembly-CSharp.dll

Assembly-CSharp 为 Unity 自动整合的 DLL,在 Unity 工程中任何没有被单独编译的代码都会被整合进这个 Assembly-CSharp.dll 中。

Assembly Definition

Assembly Definition 是 Unity 2017.3 以后推出的功能,主要解决庞大程序集的编译时效问题。

在 Assets 目录下任意文件夹创建 Assembly Definition,会使该文件夹下所有代码单独编译成 DLL,修改该文件夹下代码时,只会重新编译该 DLL,而不会重新编译 Assembly-CSharp.dll

AOT 与热更新程序集

热更新程序集

热更新程序集理论上可以是 Assembly-CSharp 程序集,但为保证项目逻辑清晰、资源管理方便,当前框架使用 AssemblyDefinition 划分单独的 DLL 作为热更新程序集。热更新 Assembly 不应被 IL2CPP 处理并编译到最终包体中。

HybridCLR 处理了 IFilterBuildAssemblies 回调,将热更新 DLL 从 build assemblies 列表移除。

AOT 程序集

AOT 程序集是随包一起打出,不会被更新的代码。在当前框架定义下,Assembly-CSharp 为主 AOT 程序集,使用 AssemblyDefinition 划分其他 AOT 程序集。

Assembly-CSharp 作为 AOT 程序集时强烈建议关闭热更新程序集的 auto reference 选项,因为 Assembly-CSharp 是最顶层 Assembly,会自动引用剩余所有 Assembly,容易出现失误引用热更新程序集的情况。

UniTask

UniTask 是 GitHub 上的开源库,为 Unity 提供高性能异步解决方案,可以代替协程实现异步操作,同时兼容 Unity 生命周期,使得 Awake、Start、协程等方法都可以异步执行,但仍运行在主线程上。

热更新 DLL 的加载

HybridCLR 官方推荐将代码直接挂载在预制体上,通过 AssetBundle 加载预制体的方法进行热更新加载。也可以通过从加载的热更新 DLL 中直接反射出热更新类并使用 AddComponent 方法挂载到物体上实现热更新。无论哪种方式,都需要在加载预制体或加载类之前,提前加载好热更新的 DLL。

HybridCLR 首次构建前置链

首次在新工程通过 HybridBuilder 执行构建时,需要保证完整前置链:

  1. 编译热更新 DLL
  2. 生成 IL2CPP 定义
  3. 生成 link.xml
  4. 生成裁剪后的 AOT DLL

HybridBuilder 在必要时会触发 PrebuildCommand.GenerateAll() 自动补齐。


安装与依赖

系统要求

  • Unity 版本: 2022.3 LTS 或更高
  • 目标平台: Windows、Android、iOS
  • 开发环境: Visual Studio 2019+ 或 Rider

安装步骤

  1. 通过HybridCLR YooAsset UniTask安装第三方包
  2. 通过 Package Manager → Add Package From URL 添加:
https://github.com/YangLingCloud/HybridCLR_YooAsset_UniTask.git

包依赖

package.json 已声明以下依赖(自动安装):

  • com.code-philosophy.hybridclr — HybridCLR 热更新核心
  • com.tuyoogame.yooasset — YooAsset 资源管理
  • com.cysharp.unitask — UniTask 异步编程
  • com.unity.scriptablebuildpipeline — SBP 构建管线
  • com.unity.nuget.newtonsoft-json — JSON 序列化

快速开始

1. 安装包

通过 Package Manager 安装(见上方安装步骤)。

2. 导入 Samples

通过 Package Manager 找到 com.yanglingyun.hyu,点击 Samples 标签导入:

  • Hot Update Sample — 热更新示例
  • Build Pipeline Tests — 构建管线测试

导入后路径为:Assets/Samples/com.yanglingyun.hyu/<version>/Hot Update Sample/

3. 初始化 Sample 设置

执行菜单:

  1. HybridTool/Sample-HotUpdateSample/Restore HybridCLR Settings from Snapshot — 快速导入 HybridCLR 配置
  2. HybridTool/Sample-HotUpdateSample/Normalize Collector Paths — 快速设置 AssetBundleCollectorSetting

4. 配置运行时参数

打开 HybridRuntimeSettings 资产,填写 HostServerIP(CDN / 资源服务器地址)。

5. 执行构建

  1. 通过 HybridTool/ 菜单执行首次构建(自动触发 PrebuildCommand.GenerateAll() 生成 AOT 裁剪 DLL)
  2. 后续迭代仅需执行热更新 DLL 编译与资源打包

集成工具

HybridTool 整合工具

由于 YooAsset 和 HybridCLR 都是通过 Unity Package Manager 加载的,导致很多代码不够好用又无法修改,因此通过编辑器代码写了一套整合工具,使两个第三方库可以更好地配合工作。

主要功能

功能模块功能描述使用场景
验证元数据补充需求对比 AOT 与热更新 DLL打包前检查
APK 打包流程自动化打包与依赖分析完整构建流程
AOT 元数据生成自动生成补充文件解决裁剪问题
热更新 DLL 编译编译生成热更新代码开发阶段
预制体依赖补全自动补全 link.xml解决组件引用问题

HybridBuilderWindow

基于 UI Toolkit 的现代化打包工具窗口,重写了 YooAsset.AssetBundleBuilderWindow,并增加了代码打包相关设置项。

核心组件

  • HybridBuilderWindow — 窗口主控制器
  • HybridBuilderWindow.uxml — UI 布局定义文件
  • HybridBuilderWindow.uss — 现代化 UI 样式表
  • HybridBuildPipeViewerBase — 核心功能实现基类

使用 HybridBuilderWindow 打包

在 Unity 编辑器中,点击菜单栏:HybridTool/Hybrid Builder 打开窗口。

配置打包设置:

  1. 选择 HybridBuilderSetting:窗口中会列出项目中所有的 HybridBuilderSetting 文件,选择要使用的配置
  2. 选择 HybridRuntimeSetting:选择运行时设置文件,该文件定义了资源包和版本信息
  3. 选择打包选项:可以选择打包资产、脚本或全部

执行打包:

点击"构建"按钮开始打包。打包过程会自动处理以下步骤:

  • 验证元数据补充需求
  • 编译热更新 DLL
  • 生成 AOT 元数据
  • 打包 AssetBundle 资源

HybridScriptableBuildPipeline

主要打包逻辑在 HybridScriptableBuildPipelineViewer 中实现,仅在运行时对打包 Asset 或 Script 进行区分。

对 YooAsset 打包流程的修改

  1. 运行时区分打包类型 — Asset 或 Script 使用不同的构建管道
  2. 增强 RawFileBuildPipeline — 增加 TaskBuildScript_SBP 流程
  3. 批量打包支持 — 通过包名列表配置一次性打多个包
  4. APK 打包优化 — 优化构建流程与错误检查
  5. 裁剪检查 — 构建前检查热更新代码是否访问了被裁切代码

HybridBuilderSettings 配置

public class HybridBuilderSettings : ScriptableObject
{
    public HybridRuntimeSettings RuntimeSettings;  // 关联的运行时配置
    public List<string> AssetPackages;              // 资源包包名列表
    public string ScriptPackageName;                // 脚本包包名
    public DefaultAsset PatchedAOTDLLFolder;        // AOT 补充元数据 DLL 目录
    public DefaultAsset HotUpdateDLLFolder;         // 热更新 DLL 目录
    public int ReleaseBuildVersion;                 // 发行版本号
    public int AssetBuildVersion;                   // 资源构建版本号
    public int ScriptBuildVersion;                  // 脚本构建版本号
    public string buildOutputPath;                  // 构建输出路径(支持相对路径)
    public bool isClearBuildCache;                  // 是否清除构建缓存
    public bool isUseAssetDependDB;                 // 是否使用资源依赖数据库(加速构建)
    public bool isUseSelfIncrementingVersions;      // 是否使用自增版本号
    public ECompressOption assetCompressOption;     // AB 包压缩方式
    public EFileNameStyle assetFileNameStyle;       // AB 包命名方式
    public string assetEncryptionClassName;          // AB 包加密类名
    public EBuildinFileCopyOption assetBuildinFileCopyOption; // 首包 copy 选项
    public string assetBuildinFileCopyParams;       // copy 选项参数
    public HybridBuildOption hybridBuildOption;     // 混合构建选项
}

HybridRuntimeSettings 配置

[Serializable]
public class PackageVersion
{
    public string Name;
    public string Version;
}

public class HybridRuntimeSettings : ScriptableObject
{
    public string HostServerIP;
    public int ReleaseBuildVersion;
    public List<PackageVersion> Packages;
}

构建流程

HybridCLR + YooAsset + UniTask 的构建流程分为两个主要阶段:主包构建阶段热更新包构建阶段。通过分离式设计,实现高效的增量更新机制。

构建流程图

主包构建阶段(低频,首次或重大更新时)
├── 编译 AOT 程序集
├── 生成桥接函数
├── 生成裁剪后的 AOT DLL
├── 生成 AOT 补充元数据
└── 构建最终 APK 包

热更新包构建阶段(高频,日常更新)
├── 编译热更新程序集
├── 打包热更新 DLL
├── 打包资源文件
└── 生成版本信息

阶段一:主包构建

适用场景:首次发布、AOT 代码变更、桥接函数变化

  1. 环境准备

    • 执行 HybridCLR-Installer 安装 HybridCLR 环境
    • 执行 Generate-All 生成桥接函数和初始化文件
  2. AOT 元数据生成

    // 自动执行的流程
    Il2CppDefGeneratorCommand.GenerateIl2CppDef();
    LinkGeneratorCommand.GenerateLinkXml();
    StripAOTDllCommand.GenerateStripedAOTDlls();
    
  3. APK 构建

    • 构建包含 AOT 代码的 APK 包
    • 生成裁剪后的 AOT DLL 用于后续热更新

阶段二:热更新包构建

适用场景:热更新代码变更、资源文件更新

  1. 热更新 DLL 编译

    CompileDllCommand.CompileDllActiveBuildTarget();
    
  2. 资源包构建

    • 将热更新 DLL 作为 RawFile 打包
    • 打包美术资源、配置文件等
    • 生成版本控制信息
  3. 增量打包优化

    • 利用 YooAsset 的增量打包机制
    • 仅重新构建变更的资源包,避免全量构建
    • Clear Build Cache 选项控制是否清理构建缓存

构建决策机制

通过 BuildHelper.CheckAccessMissingMetadata() 方法判断:

  • 需要重新构建 APK 的情况

    • 热更新代码引用了被裁剪的类型
    • 桥接函数发生变化
    • AOT 代码有重大变更
  • 仅需更新热更新包的情况

    • 仅修改热更新逻辑代码
    • 更新资源文件
    • 修复热更新层 bug

桥接函数稳定性说明

根据桥接函数的原理,对于固定的 AOT 部分,桥接函数集是确定的。后续无论进行任何热更新,都不会需要新的额外桥接函数。因此不用担心热更上线后突然出现桥接函数缺失的问题。


编辑器菜单

Package 菜单(HybridTool/

  • Check AOT Metadata — 验证 AOT 元数据是否需要补充
  • Build APK — 构建 APK 包
  • Get Patched AOT Assembly List — 获取需要补充的 AOT 程序集列表
  • Generate AOT DLLs and Copy — 生成 AOT DLL 并拷贝到资源目录
  • Generate Hot-Update DLLs and Copy — 编译热更新 DLL 并拷贝到资源目录
  • Supplement Prefab Dependencies — 补全预制体依赖到 link.xml
  • Hybrid Builder — 打开 UI Toolkit 一体化构建窗口

Sample 菜单(HybridTool/Sample-HotUpdateSample/

  • Export HybridCLR Settings Snapshot — 导出当前 HybridCLR 配置快照
  • Restore HybridCLR Settings from Snapshot — 从快照恢复 HybridCLR 配置
  • Normalize Collector Paths — 规范化 YooAsset 收集器路径

项目结构

.
├── package.json                # UPM 包定义(依赖、示例)
├── CHANGELOG.md                # 变更日志
├── README.md / README_EN.md    # 双语文档(中文 / 英文)
├── LICENSE                     # MIT
├── README/                     # 文档附件(.png、.xmind、.pdf、.docx)

├── Editor/                     # 编辑器程序集:com.yanglingyun.hyu.Editor
│   ├── HybridEditor.asmdef     # 编辑器 asmdef
│   ├── BuildHelper.cs          # AOT 元数据检查、DLL 拷贝、APK 构建、link.xml 补全
│   ├── HybridBuilderWindow.cs  # UI Toolkit 打包窗口主控制器
│   ├── HybridBuilderWindow.uxml # 窗口 UI 布局
│   ├── HybridBuilderWindow.uss # 现代化 UI 样式表(卡片布局、配色方案、按钮样式)
│   ├── HybridBuilderSettings.cs # 构建配置 ScriptableObject + HybridBuildOption 枚举
│   ├── HybridBuildPipeViewerBase.cs  # 构建管线查看器基类
│   ├── HybridBuildPipeViewerBase.uxml # 查看器 UI 布局(卡片式设计)
│   ├── HybridScriptableBuildPipelineViewer.cs # SBP 构建管线查看器
│   ├── HybridPaths.cs          # 集中管理路径常量(AOT/热更 DLL 目录、link.xml、清单文件名)
│   ├── HybridRuntimeSettingsMigrator.cs # 旧版 Packages JSON 字段自动迁移
│   ├── SceneHelper.cs          # 场景工具
│   ├── BuildPipelineTask/      # 重写的打包流水线 Task
│   │   └── TaskBuildScript_SBP.cs  # SBP 自定义构建任务(脚本打包)
│   └── ScriptableBuildPipeline/ # 重写的打包流水线
│       ├── HybridScriptableBuildPipeline.cs     # SBP 管线实现
│       └── HybridScriptableBuildParameters.cs   # SBP 构建参数

├── Runtime/                    # 运行时程序集:com.yanglingyun.hyu.Runtime
│   ├── com.yanglingyun.hyu.Runtime.asmdef
│   └── HybridRuntimeSettings.cs # 运行时配置(CDN 地址、版本号、包名)

└── Samples~/                   # 可导入的示例(UPM 约定,不参与编译)
    ├── HotUpdateSample/        # 完整热更新示例
    │   ├── AOTScripts/         # AOT 运行时脚本(AOTPublic.asmdef)
    │   ├── Editor/             # 示例编辑器工具(快照导入、路径规范化)
    │   ├── EventDefine/        # UniEvent 事件定义(Battle/Patch/Scene/User)
    │   ├── HotUpdateAssets/    # 待打包资源(Prefabs/Scenes/Textures 等)
    │   ├── HotUpdateScripts/   # 热更新程序集(HotUpdate.asmdef)
    │   ├── PatchLogic/         # YooAsset 补丁下载状态机(8 个 FSM 节点)
    │   ├── Resources/          # 内置资源(PatchWindow 预制体等)
    │   ├── Scripts/            # 主场景 AOT 脚本(GameManager、HybridLauncher)
    │   ├── Settings/           # 预配置 ScriptableObject 资产
    │   └── ThirdParty/         # 轻量依赖(UniEvent/UniMachine/UniUtility)
    └── BuildTests/             # 构建管线测试
        └── Editor/
            ├── com.yanglingyun.hyu.Tests.Editor.asmdef
            └── HybridBuildPipelineTests.cs  # NUnit EditMode 测试

Sample 使用说明

本包提供两个可导入的 Sample:HotUpdateSample(热更新示例)和 BuildTests(构建测试)。

HotUpdateSample — 热更新完整示例

一个开箱即用的热更新演示工程,包含从资源下载到热更新代码执行的完整流程。

目录结构

HotUpdateSample/
├── AOTScripts/                # AOT 端运行时脚本(随主包发布,不可热更新)
│   ├── AOTPublic.asmdef
│   ├── HttpHelper.cs          # HTTP 工具类
│   └── SampleBundleEncryption.cs  # YooAsset 资源包加密示例
├── Editor/                    # 编辑器导入工具
│   ├── HybridCLRSettingsSnapshot.json  # HybridCLR 预置配置快照
│   └── HybridSettingsImporter.cs       # 自动/手动设置导入器
├── EventDefine/               # UniEvent 事件定义
│   ├── BattleEventDefine.cs
│   ├── PatchEventDefine.cs    # 热更新流程事件
│   ├── SceneEventDefine.cs
│   └── UserEventDefine.cs
├── HotUpdateAssets/           # 需要打入 AssetBundle 的资源
│   ├── HotUpdateDll/          # 编译后的热更新 DLL 存放目录
│   ├── PatchedAOTDLL/         # AOT 补充元数据 DLL(.bytes 格式)
│   ├── Prefabs/               # 预制体
│   ├── Scenes/                # 热更新场景
│   ├── Textures/ Materials/ UIPrefabs/ audios/
├── HotUpdateScripts/          # 热更新程序集(运行时由 HybridCLR 加载)
│   ├── HotUpdate.asmdef
│   ├── HotUpdateLauncher.cs   # 热更新入口脚本
│   ├── LoadImage.cs           # YooAsset 加载贴图示例
│   ├── ModelRotate.cs         # YooAsset 加载模型示例
│   └── animate/Rotating.cs    # 旋转动画组件
├── PatchLogic/                # YooAsset 热更新下载状态机
│   ├── FsmNode/               # 8 个 FSM 状态节点
│   ├── PatchOperation.cs      # 状态机调度器
│   └── PatchWindow.cs         # 下载进度 UI 控制器
├── Scripts/                   # 主场景 AOT 脚本
│   ├── GameManager.cs         # 游戏启动管理器
│   └── HybridLauncher.cs     # HybridCLR + YooAsset 启动器
├── Settings/                  # 配置文件
│   ├── AssetBundleCollectorSetting.asset
│   ├── HybridBuilderSettings.asset
│   └── HybridRuntimeSettings.asset
└── ThirdParty/                # 内置轻量工具库
    ├── UniEvent/              # 事件总线
    ├── UniMachine/            # 有限状态机
    └── UniUtility/            # 通用工具

使用步骤

第一步:导入示例

在 Package Manager 中找到 com.yanglingyun.hyu,点击 Samples 标签,导入 Hot Update Sample

第二步:自动初始化

导入后首次打开编辑器时,HybridSettingsImporter 会自动检测 HybridCLR 配置状态:

  • 若 HybridCLR Settings 中热更新程序集列表为空,弹窗询问是否从快照恢复
  • 点击 Restore from Snapshot 将自动配置:
    • hotUpdateAssemblyDefinitions[HotUpdate]
    • patchAOTAssemblies[UniTask, UnityEngine.CoreModule, YooAsset, mscorlib]
  • 同时自动创建 Settings 资产并规范化收集器路径

第三步:手动初始化(可选)

如果自动初始化未触发,可手动执行菜单:

  1. HybridTool/Sample-HotUpdateSample/Restore HybridCLR Settings from Snapshot
  2. HybridTool/Sample-HotUpdateSample/Normalize Collector Paths

第四步:配置并构建

  1. HybridRuntimeSettings 中填写 HostServerIP
  2. 通过 HybridTool/ 菜单执行构建

运行时流程

HybridLauncher → GameManager → PatchOperation(8 步状态机)
    → 初始化 YooAsset 包
    → 请求远端版本号
    → 更新资源清单
    → 下载资源包
    → 加载 AOT 元数据(为热更新泛型函数提供支持)
    → 加载热更新 DLL(HybridCLR)
    → 实例化 HotUpdateLauncher,进入热更新逻辑

BuildTests — 构建管线测试

用于验证构建配置与管线正确性的 NUnit EditMode 测试集。

使用步骤

  1. 在 Package Manager 中导入 Build Pipeline Tests 示例
  2. 打开 Unity Test Runner(Window > General > Test Runner
  3. 测试程序集 com.yanglingyun.hyu.Tests.Editor 仅在 UNITY_INCLUDE_TESTS 定义时编译

测试覆盖范围

测试类别说明
PathResolutionResolveBuildOutputPath 相对/绝对路径解析、GetBuildOutputPath 追加版本号子目录
VersionStringGetCurrentVersion 构建格式(三段整数下划线连接)与展示格式(含标签)
CopyDllEdgeCasesCopyPatchedAOTDll / CopyHotUpdateDll 空路径防御、CopyDllFileToByte 源目录不存在时返回空列表
PipelineTypeValidationHybridScriptableBuildPipeline 传入非法参数类型时抛出异常
EndToEndGenerateAll 端到端首次构建产物验证、CopyHotUpdateDll 端到端 .bytes 与清单生成

标记 [Category("SlowTest")] 的测试会实际执行构建命令,耗时较长;当活跃平台不匹配时会自动跳过。

测试边界说明

测试仅验证本包自身功能(环境配置、Editor 方法、版本逻辑、DLL 编译拷贝等)的正确性。YooAsset 资源打包(ScriptableBuildPipeline.Run())、APK 构建(BuildHelper.BuildAPK())等属于第三方框架或 Unity 构建管线的职责,由各自的测试保证,不在本测试范围内。


常见问题

Q1: 热更新代码无法访问 AOT 代码中的泛型方法怎么办?

这是因为泛型方法需要额外的元数据支持。解决方案:

  1. 显式调用 — 在热更新代码中显式调用该泛型方法
  2. 手动配置 — 在 link.xml 中添加相关类型的保留设置
  3. 工具辅助 — 使用 HybridTool/Supplement Prefab Dependencies 功能

Q2: 打包时提示"缺少 AOT 元数据"错误怎么办?

  1. 使用 HybridTool/Check AOT Metadata 验证元数据是否需要补充
  2. 执行 HybridTool/Generate AOT DLLs and Copy 生成 AOT 补充文件
  3. 重新构建 APK

Q3: 热更新代码运行时出现"方法未找到"错误怎么办?

可能原因及解决方案:

  • 版本不匹配 — 确保热更新 DLL 和 AOT 元数据版本一致
  • 配置问题 — 检查 link.xml 配置是否正确
  • 重新构建 — 重新构建 APK 以更新元数据

Q4: 首次构建时 MetadataCheck 失败怎么办?

先执行 Sample 菜单中的 Snapshot 恢复和 Collector 规范化,然后触发 GenerateAll 前置链,再进行热更新构建。

Q5: Sample 导入后 Collector 路径不对?

执行:HybridTool/Sample-HotUpdateSample/Normalize Collector Paths


最佳实践

程序集划分建议

AOT 程序集(稳定不变)

  • 核心业务逻辑
  • 第三方库封装
  • Unity API 抽象层
  • 接口定义与数据结构
  • 事件系统

热更新程序集(频繁更新)

  • 游戏玩法逻辑
  • UI 界面实现
  • 配置数据解析

构建优化建议

  • 利用 YooAsset 增量打包机制,不勾选 Clear Build Cache 可大幅提升构建速度
  • AOT 部分稳定后,日常迭代仅需执行热更新包构建
  • 桥接函数对于固定 AOT 部分是确定的,热更不会引入新的桥接函数需求

License

MIT


如有问题,请提交 Issue

Happy Coding!