跳到主要内容
版本:v3

Hotfixers

重要 注意 提醒

Coding Style wiki​


Hotfixers 是 Hotfixer 模块的统一调用入口(Facade),整合 HybridCLR 代码热更新方案,涵盖热更新流程检查(下载与加载)、AOT 元数据补充、Hotfix DLL 加载与状态查询。

命名空间OxGFrame.Hotfixer
类型public static class
源码Hotfixers.cs
using OxGFrame.Hotfixer;

提醒 使用 HybridCLR 如有疑问,请前往官方文档进行熟悉;完整使用流程可参考 HotfixerDemo(从 Package Manager 导入)。

快速上手​

// 启动热更新流程(自动读取 StreamingAssets 中的 HotfixManifest.dat 配置文件)
Hotfixers.CheckHotfix("HotfixPackage");

// 等待热更新完成,再进入游戏主逻辑与资源更新
await UniTask.WaitUntil(() => Hotfixers.IsDone());

// 主程序集无法直接引用热更层,通过反射调用热更代码
var assembly = Hotfixers.GetHotfixAssembly("HotfixerDemo.Hotfix.Runtime.dll");
assembly?.GetType("Hello")?.GetMethod("Run")?.Invoke(null, null);

通用规则​

核心机制​

Hotfixers 主要与 HybridCLR 整合,负责在运行时:

  1. 补充 AOT 元数据:解决 AOT 泛型实例化等问题(通过 RuntimeApi.LoadMetadataForAOTAssembly,采用 HomologousImageMode.SuperSet 模式)。
  2. 加载热更新 DLL:以 Assembly.Load 将更新后的代码逻辑加载至执行环境。

重要 主程序集(AOT)无法直接引用热更新程序集。热更加载完成后,需通过反射调用热更层代码(可由 GetHotfixAssembly 获取程序集)。

提醒 AOT / Hotfix DLL 需先通过 Editor 工具 HotfixHelper 收集(.dll.bytes),再以 YooAsset 打包至 Hotfix Package 中,收集方式请参考收集示例。

热更流程​

调用 CheckHotfix 后,内部状态机将依序执行以下流程:

顺序流程状态说明
1FsmHotfixPrepare流程准备。
2FsmInitHotfixPackage初始化 Hotfix Package;失败时发送 HotfixInitFailed 事件。
3FsmUpdateHotfixPackage更新 Hotfix Package 版本;失败时发送 HotfixUpdateFailed 事件。
4FsmHotfixCreateDownloader创建下载器。有待下载文件时,发送 HotfixCreateDownloader 事件并等待用户确认;无则直接进入下载完成。
5FsmHotfixBeginDownload开始下载;过程中发送 HotfixDownloadProgression 进度事件,下载失败时发送 HotfixDownloadFailed 事件。
6FsmHotfixDownloadOver下载完成。
7FsmHotfixClearCache清理未使用的缓存文件。
8FsmLoadAOTAssemblies为 AOT 程序集补充元数据(HybridCLR RuntimeApi.LoadMetadataForAOTAssembly)。
9FsmLoadHotfixAssemblies加载热更新程序集(Assembly.Load)。
10FsmHotfixDone流程完成,IsDone 返回 true。
注意
  • 有文件待下载时,流程会停在步骤 4,需由用户发送 UserBeginDownload 事件确认后才会开始下载(参考流程事件)。
  • DLL 文件将以清单中的名称(含 .dll)作为资源名称,从 Hotfix Package 以 TextAsset 形式加载,加载完成后随即卸载。
  • 编辑器模拟模式(EditorSimulateMode)下会跳过 AOT 元数据补充;在 Editor 或热更禁用时,热更程序集改由当前 AppDomain 直接查找(不实际加载 DLL bytes)。

配置文件 HotfixManifest.dat​

自动配置模式的 CheckHotfix 重载,会向 StreamingAssets 请求热更新配置文件,并依配置内容启动流程:

  • 文件名默认为 HotfixManifest.dat,可通过 HotfixSettings 自定义名称与扩展名(参考全局配置)。
  • 内容包含 aotDlls 与 hotfixDlls 两组清单(名称皆含 .dll 扩展名),支持明文 JSON 与加密 BYTES 两种格式,读取时依文件头自动判别。
  • 可通过 HotfixHelper.ExportHotfixDllConfig 或编辑器菜单 OxGFrame → Hotfixer → Hotfix Config Generator (HotfixManifest.dat) 窗口工具生成。

明文 JSON 格式内容如下:

{
"aotDlls": [
"mscorlib.dll",
"UniTask.dll"
],
"hotfixDlls": [
"HotfixerDemo.Hotfix.Runtime.dll"
]
}

流程事件​

热更流程通过 UniEvent(UniFramework.Event)广播与接收事件,事件定义于命名空间 OxGFrame.Hotfixer.HotfixEvent。

框架发送(HotfixEvents)— 由用户监听

事件说明
HotfixFsmState流程状态切换通知,携带当前状态节点 stateNode。
HotfixInitFailedHotfix Package 初始化失败。
HotfixUpdateFailedHotfix Package 版本更新失败。
HotfixCreateDownloader下载器创建完成,携带待下载文件数 totalCount 与总大小 totalBytes。
HotfixDownloadProgression下载进度,携带 progress、下载数量、大小与速度等信息。
HotfixDownloadFailed文件下载失败,携带 fileName 与 error。

用户发送(HotfixUserEvents)— 驱动流程继续

事件说明
UserTryInitHotfix重新尝试初始化 Hotfix Package。
UserTryUpdateHotfix重新尝试更新 Hotfix Package。
UserTryCreateDownloader重新尝试创建下载器。
UserBeginDownload确认开始下载热更新文件。
using OxGFrame.Hotfixer.HotfixEvent;
using UniFramework.Event;

// 监听下载器创建完成事件,确认后开始下载
UniEvent.AddListener<HotfixEvents.HotfixCreateDownloader>((message) =>
{
var msgData = message as HotfixEvents.HotfixCreateDownloader;
Debug.Log($"待下载文件数:{msgData.totalCount},总大小:{msgData.totalBytes}");
HotfixUserEvents.UserBeginDownload.SendEventMessage();
});

禁用热更新​

重要 如果禁用 HybridCLR(HybridCLR Settings 取消勾选 Enable),必须搭配宏 OXGFRAME_HYBRIDCLR_DISABLED,才能有效剔除热更流程。

定义宏后 IsDisabled 将返回 true,流程将跳过 AOT 元数据补充,热更程序集改由当前 AppDomain 直接查找。

方法总览​

热更流程检查​

方法说明
CheckHotfix启动热更新流程,下载并加载所有热更新相关文件。

状态与重置​

方法说明
IsDone返回热更新流程是否已全部完成。
IsDisabled返回热更新功能是否已被禁用。
Reset重置热更新标记与缓存数据。

程序集信息​

方法说明
GetAOTAssemblyNames获取 AOT 程序集名称(含 .dll 扩展名)。
GetAotAssemblyNamesWithoutExtensions获取 AOT 程序集名称(不含扩展名)。
GetHotfixAssemblyNames获取热更新程序集名称(含 .dll 扩展名)。
GetHotfixAssemblyNamesWithoutExtensions获取热更新程序集名称(不含扩展名)。
GetHotfixAssembly依名称获取已加载的 Assembly 对象。

CheckHotfix​

public static void CheckHotfix(string packageName, Action errorAction = null)
public static void CheckHotfix(PackageInfoWithBuild packageInfoWithBuild, Action errorAction = null)
public static void CheckHotfix(string packageName, string[] aotAssemblies, string[] hotfixAssemblies)
public static void CheckHotfix(PackageInfoWithBuild packageInfoWithBuild, string[] aotAssemblies, string[] hotfixAssemblies)

参数

参数类型说明
packageNamestringHotfix 资源包名称。
packageInfoWithBuildPackageInfoWithBuild自定义的资源包信息(可自行指定构建模式等,命名空间 OxGFrame.AssetLoader.Bundle)。
errorActionAction配置文件请求失败(URL 无效、请求错误或超时)、内容为空或解析失败时触发的回调。
默认值:null
aotAssembliesstring[]需补充元数据的 AOT 程序集清单(名称含 .dll 扩展名)。
hotfixAssembliesstring[]热更新程序集清单(名称含 .dll 扩展名)。

说明

启动热更新流程,开始下载并加载所有热更新相关文件,完整流程参考热更流程。重载分为两种模式:

  • 自动配置模式(errorAction 重载):自动向 StreamingAssets 请求 HotfixManifest.dat 配置文件(参考配置文件),解析出 AOT 与 Hotfix 程序集清单后启动流程。
  • 手动指定模式(aotAssemblies 重载):直接传入需补充元数据的 AOT 程序集与热更新程序集清单。
注意
  • 此方法为非阻塞调用,完成与否需通过 IsDone 或流程事件判断。
  • 仅指定 packageName 的重载,将以 AppPackageInfoWithBuild(构建模式 ScriptableBuildPipeline)初始化 Package;如需自定义构建模式,请改用 PackageInfoWithBuild 重载。
  • 流程进行中重复调用将被忽略(输出警告)。
  • 流程已完成后再次调用将直接返回(输出警告),需先调用 Reset 才能重新执行。

示例

// 自动配置模式:读取 StreamingAssets 中的 HotfixManifest.dat
Hotfixers.CheckHotfix
(
"HotfixPackage",
() => Debug.LogWarning("配置文件请求失败,请先生成 HotfixManifest.dat")
);

// 手动指定模式:直接传入 AOT 与 Hotfix 程序集清单
Hotfixers.CheckHotfix
(
"HotfixPackage",
// 需补充元数据的 AOT 程序集
new string[] { "mscorlib.dll", "UniTask.dll" },
// 热更新程序集
new string[] { "HotfixerDemo.Hotfix.Runtime.dll" }
);

IsDone​

public static bool IsDone()

返回值

bool — 热更新流程是否已全部完成(下载与加载皆完成后为 true)。

说明

返回热更新完成状态。建议等待此状态为 true 后,再进入游戏主逻辑与资源更新。

示例

Hotfixers.CheckHotfix("HotfixPackage");

// 等待热更新完成
await UniTask.WaitUntil(() => Hotfixers.IsDone());

// 进入游戏主流程

IsDisabled​

public static bool IsDisabled()

返回值

bool — 是否已禁用热更新功能;项目定义 OXGFRAME_HYBRIDCLR_DISABLED 宏时返回 true。

说明

检查当前环境是否禁用了热更新功能(由编译期宏决定,通常用于开发者模式)。

重要 如果禁用 HybridCLR,必须搭配宏 OXGFRAME_HYBRIDCLR_DISABLED,才能有效剔除热更流程(参考禁用热更新)。


Reset​

public static void Reset()

说明

重置热更新的标记与缓存数据(包含完成标记、已记录的 AOT / Hotfix 程序集名称与已加载的 Assembly 缓存),使 CheckHotfix 能重新执行。

提醒 重置后重新加载热更 DLL 属于 HotReload 范畴,需 HybridCLR 商业版支持才可使用(社区版不支持)。


GetAOTAssemblyNames​

public static string[] GetAOTAssemblyNames()

返回值

string[] — AOT 程序集名称数组(含 .dll 扩展名);尚未执行过 CheckHotfix 时返回 null。

说明

获取需补充元数据的 AOT 程序集名称清单。此清单在调用 CheckHotfix 时设置。


GetAotAssemblyNamesWithoutExtensions​

public static string[] GetAotAssemblyNamesWithoutExtensions()

返回值

string[] — 去除 .dll 扩展名的 AOT 程序集名称数组;尚未执行过 CheckHotfix 时返回 null。

说明

同 GetAOTAssemblyNames,但名称不含 .dll 扩展名(首次调用时转换并缓存结果)。


GetHotfixAssemblyNames​

public static string[] GetHotfixAssemblyNames()

返回值

string[] — 热更新程序集名称数组(含 .dll 扩展名);尚未执行过 CheckHotfix 时返回 null。

说明

获取热更新程序集名称清单。此清单在调用 CheckHotfix 时设置。


GetHotfixAssemblyNamesWithoutExtensions​

public static string[] GetHotfixAssemblyNamesWithoutExtensions()

返回值

string[] — 去除 .dll 扩展名的热更新程序集名称数组;尚未执行过 CheckHotfix 时返回 null。

说明

同 GetHotfixAssemblyNames,但名称不含 .dll 扩展名(首次调用时转换并缓存结果)。


GetHotfixAssembly​

public static Assembly GetHotfixAssembly(string assemblyName)

参数

参数类型说明
assemblyNamestring热更新程序集名称(含 .dll 扩展名,如 HotfixerDemo.Hotfix.Runtime.dll)。

返回值

Assembly — 已加载的热更新程序集;未找到时返回 null。

说明

依名称获取已加载的 Assembly 对象。主程序集无法直接引用热更新程序集,可通过此方法获取程序集后,以反射调用热更层代码。

示例

// 热更完成后,通过反射进入热更层入口
var assembly = Hotfixers.GetHotfixAssembly("HotfixerDemo.Hotfix.Runtime.dll");
assembly?.GetType("Hello")?.GetMethod("Run")?.Invoke(null, null);