diff --git a/docs/business/ultimate/build.md b/docs/business/ultimate/build.md
new file mode 100644
index 00000000..48278808
--- /dev/null
+++ b/docs/business/ultimate/build.md
@@ -0,0 +1,26 @@
+# 构建和热更新
+
+DHE技术中与构建相关的文件为dhe dll文件和对应的dhao文件。
+
+## 构建游戏
+
+由于首包中所有DHE程序集中代码没有发生改变,因为在构建游戏工作流中并不需要任何DHE相关的dll或者dhao文件。
+
+- 运行`HybridCLR/Generate/All`
+- 构建游戏
+- 备份`HybridCLRData\AssembliesPostIl2CppStrip\{buildTarget}`目录下的所有程序集,加入版本管理系统。将来热更新生成dhao文件时需要用到这些原始的dll文件
+
+
+## 热更新
+
+- 使用 `HybridCLR/CompileDll/ActivedBuildTarget` 生成热更新dll。
+- 使用`HybridCLR.Editor.DHE.BuildUtils.GenerateDHAODatas`生成最新的热更新dll的dhao文件。如果需要加密dhe程序集,则使用`HybridCLR.Editor.DHE.BuildUtils.EncryptDllAndGenerateDHAODatas`生成加密dll及相应的dhao文件
+- 将最新的热更新dll(或者加密后的dll)和dhao文件加入热更新资源管理系统。注意,运行时不需要原始dll文件,请不要将备份的原始dll加入热更新资源管理系统。
+
+:::caution
+
+如果构建游戏使用 **development build 选项**,请一定要对应使用`HybridCLR/CompileDll/ActivedBuildTarget_Development`编译Development模式的热更新dll。
+否则由于developemnt与非development编译的dll差异较大,会导致几乎所有函数都被计算为变化。
+
+:::
+
diff --git a/docs/business/ultimate/dhao.md b/docs/business/ultimate/dhao.md
new file mode 100644
index 00000000..44888065
--- /dev/null
+++ b/docs/business/ultimate/dhao.md
@@ -0,0 +1,52 @@
+# DHAO 文件
+
+
+dhao文件是DHE技术的核心概念。dhao文件中包含了离线计算好的最新的热更新dll中变化的类型和函数的信息,运行时直接根据dhao文件中信息决定执行某个热更新函数时,应该使用最新的解释版本还是直接调用原始的AOT函数。
+离线计算好的dhao文件对于DHE技术极为关键,如果没有dhao文件,需要额外携带原始AOT dll,并且计算函数变化的代价极其高昂。
+
+通过对比最新的热更新dll与打包时生成的AOT dll,离线计算出变化的类型与函数,保存成dhao文件。因此DHE机制要正常工作,必须依赖于dhao文件的正确性,而dhao文件的正确性
+则依赖精确提供最新的热更新dll和打包时生成的AOT dll。
+
+
+`HybridCLR.Editor.DHE.BuildUtils`提供了多个生成dhao文件相关的函数。
+
+|函数名|描述|
+|-|-|
+|GenerateDHAODatas|生成热更新包(即有代码发生改变时)的dhao文件|
+|EncryptDllAndGenerateDHAODatas|当开启初级代码加固时,生成热更新包(即有代码发生改变时)加密后的dll和dhao文件|
+
+
+## 标记变化的函数信息
+
+目前已经可以自动通过对比最新的热更新dll和打包时生成的aot dll,计算出变化的函数,绝大多数情况下不需要手动操作。但事实上并不存在完美的能够判断逻辑等价性的代码,
+工具只是简单地一一对比IL来判断等价性。有时候可能发生函数是等价的但IL发生变化的情况(如调换了两行不相关代码的顺序),则会被判定为函数发生变换而切到解释执行。
+如果发生了这种情况,**并且对该函数有极其严苛的性能要求**,开发者可以手动使用UnchangedAttribute特性标注函数的变化性。
+`[Unchanged]`和`[Unchanged(true)]`表示未变化,`[Unchanged(false)]`表示变化,未标记特性则由工具自动计算。
+
+错误地将未变化函数标记为已变化,不会影响运行的正确性,只会影响性能。就算将所有热更新函数都标记为变化,也能正常运行。但错误地将变化函数标记为未变化,不仅会导致运行逻辑出错,
+严重情况下还会导致崩溃!
+
+:::caution
+除非特殊情况以及你是有经验的专家,不要手动标记。因为编译器经常生成一些隐藏类或字段,这些类名并不是稳定的。表面看起来一样的C#代码,实际生成的代码未必一样,强行标注为`[Unchanged]`会导致不正确的运行逻辑,甚至崩溃。
+:::
+
+
+## 合并dhao文件
+
+基于相同或者相似源码发布的游戏包,它们的原始dhe程序集在不同平台之间仅有微小区分,热更新时生成的dhao文件也只有微小区别。
+导致需要为每个平台都计算单独的dhao文件(即使是相同平台,由于代码编译的不稳定性,生成的原始dll也可能有微小区别),这导致维护dhao工作变得复杂易错。当多个新旧游戏包同时存在时,这个问题尤为严重。
+可以考虑将同一个dhe程序集对应的多个平台的dhao文件合并,不影响运行正确性的同时对性能的影响也很小。
+
+我们提供了`HybridCLR.Editor.DHE.BuildUtil::MergeDHAOFiles`函数实现合并dhao文件目标。
+
+注意,带校验的工作流无法使用合并dhao文件的方式,因为带校验的工作流会检查原始dll的md5码,这个肯定是不匹配的。
+
+
+## 注意事项
+
+### 外部dll引发的计算dhao的结果有巨量差异
+
+如果有外部dll被标记为DHE程序集,由于外部dll打包时会被裁剪,而计算dhao文件时,取的是原始的外部dll,导致产生巨量的差异,这不是所期望的。解决办法有几个:
+
+1. 在link.xml里`` 完全保留外部dll
+2. 不用最新的热更新dll去计算差异,而是使用最新代码重新打包时生成的aot dll去计算差异
diff --git a/docs/business/ultimate/freetrial.md b/docs/business/ultimate/freetrial.md
index d4a5e86b..3ad2a12c 100644
--- a/docs/business/ultimate/freetrial.md
+++ b/docs/business/ultimate/freetrial.md
@@ -54,4 +54,4 @@
## 使用
-除了安装与设置如上面文档说明有少许调整外,剩余完全参照[快速上手](./quickstartchecked)即可。
+除了安装与设置如上面文档说明有少许调整外,剩余完全参照[快速上手](./quickstartunchecked)即可。
diff --git a/docs/business/ultimate/manual.md b/docs/business/ultimate/manual.md
index db9de7d9..d38097b2 100644
--- a/docs/business/ultimate/manual.md
+++ b/docs/business/ultimate/manual.md
@@ -57,113 +57,6 @@
在`Assets/link.xml`(或者其他自定义的link.xml)中为你的所有dhe程序集添加类似配置``。
-## dhao文件
-
-dhao文件是DHE技术的核心概念。dhao文件中包含了离线计算好的最新的热更新dll中变化的类型和函数的信息,运行时直接根据dhao文件中信息决定执行某个热更新函数时,应该使用最新的解释版本还是直接调用原始的AOT函数。
-离线计算好的dhao文件对于DHE技术极为关键,如果没有dhao文件,需要额外携带原始AOT dll,并且计算函数变化的代价极其高昂。
-
-通过对比最新的热更新dll与打包时生成的AOT dll,离线计算出变化的类型与函数,保存成dhao文件。因此DHE机制要正常工作,必须依赖于dhao文件的正确性,而dhao文件的正确性
-则依赖精确提供最新的热更新dll和打包时生成的AOT dll。
-
-
-`HybridCLR.Editor.DHE.BuildUtils`提供了多个生成dhao文件相关的函数。
-
-|函数名|描述|
-|-|-|
-|GenerateUnchangedDHAODatas|生成首包(即没有发生任何改变时)的dhao文件|
-|GenerateDHAODatas|生成热更新包(即有代码发生改变时)的dhao文件|
-|EncryptDllAndGenerateUnchangedDHAODatas|当开启初级代码加固时,生成首包(即没有发生任何改变时)加密后的dll和dhao文件|
-|EncryptDllAndGenerateDHAODatas|当开启初级代码加固时,生成热更新包(即有代码发生改变时)加密后的dll和dhao文件|
-
-
-## 标记变化的函数信息
-
-目前已经可以自动通过对比最新的热更新dll和打包时生成的aot dll,计算出变化的函数,绝大多数情况下不需要手动操作。但事实上并不存在完美的能够判断逻辑等价性的代码,
-工具只是简单地一一对比IL来判断等价性。有时候可能发生函数是等价的但IL发生变化的情况(如调换了两行不相关代码的顺序),则会被判定为函数发生变换而切到解释执行。
-如果发生了这种情况,**并且对该函数有极其严苛的性能要求**,开发者可以手动使用UnchangedAttribute特性标注函数的变化性。
-`[Unchanged]`和`[Unchanged(true)]`表示未变化,`[Unchanged(false)]`表示变化,未标记特性则由工具自动计算。
-
-错误地将未变化函数标记为已变化,不会影响运行的正确性,只会影响性能。就算将所有热更新函数都标记为变化,也能正常运行。但错误地将变化函数标记为未变化,不仅会导致运行逻辑出错,
-严重情况下还会导致崩溃!
-
-:::caution
-除非特殊情况以及你是有经验的专家,不要手动标记。因为编译器经常生成一些隐藏类或字段,这些类名并不是稳定的。表面看起来一样的C#代码,实际生成的代码未必一样,强行标注为`[Unchanged]`会导致不正确的运行逻辑,甚至崩溃。
-:::
-
-## 代码中使用
-
-运行时,完成热更新后,对于每个dhe程序集,调用 `RuntimeApi::LoadDifferentialHybridAssembly`或`RuntimeApi::LoadDifferentialHybridAssemblyUnchecked` 加载热更新assembly。
-
-注意事项:
-
-- 要按照assembly的依赖顺序加载 差分混合执行 assembly。
-- 如果某个程序集未发生改变,dhao字段可以传null,但此时一定要使用打包时生成的AOT dll,而不能使用通过`HybridCLR/CompileDll/xxx`命令生成的热更新dll。
-- DHE程序集本身已经包含了元数据,即使未开启完全泛型共享时也**不要对DHE程序集进行补充元数据**,补充了也会失败,其他非DHE的AOT程序集可以照常补充元数据。
-
-
-`RuntimeApi::LoadDifferentialHybridAssembly`为带校验的工作流,需要传入原始dhe dll的md5及当前dhe dll的md5,与dhao文件中保存的md5进行对比。
-为了originalDllMd5和currentDllMd5参数,极大增加了工作流的复杂度。
-
-:::tip
-
-推荐初学者在demo项目中使用带校验的工作流,熟悉工作流后在正式项目中使用不带校验的工作流。
-:::
-
-### 带校验的 `RuntimeApi::LoadDifferentialHybridAssembly`
-
-```csharp title="加载DHE程序集"
-
-public static string CreateMD5Hash(byte[] bytes)
-{
- return BitConverter.ToString(new MD5CryptoServiceProvider().ComputeHash(bytes)).Replace("-", "").ToUpperInvariant();
-}
-
-///
-/// originalDllMd5 从构建时生成的`{manifest}`清单文件中获得,此清单文件由开发者自己生成
-///
-void LoadDifferentialHybridAssembly(string assemblyName, string originalDllMd5)
-{
- // currentDllMd5 既可以运行时生成,也可以发布热更新包时离线提前生成
- string currentDllMd5 = CreateMD5Hash(dllBytes);
- LoadImageErrorCode err = RuntimeApi.LoadDifferentialHybridAssembly(dllBytes, dhaoBytes, originalDllMd5, currentDllMd5);
- if (err == LoadImageErrorCode.OK)
- {
- Debug.Log($"LoadDifferentialHybridAssembly {assName} OK");
- }
- else
- {
- Debug.LogError($"LoadDifferentialHybridAssembly {assName} failed, err={err}");
- }
-}
-```
-
-### 不带校验的 `RuntimeApi::LoadDifferentialHybridAssemblyUnchecked`
-
-:::warning
-
-使用不带校验的工作流,请务必保证原始dhe dll、当前dhe dll和dhao文件的一致性。如果不一致,轻则运行出错,重则进程崩溃。
-
-:::
-
-```csharp title="加载DHE程序集"
-
-///
-/// originalDllMd5 从构建时生成的`{manifest}`清单文件中获得,此清单文件由开发者自己生成
-///
-void LoadDifferentialHybridAssembly(string assemblyName)
-{
- LoadImageErrorCode err = RuntimeApi.LoadDifferentialHybridAssemblyUnchecked(dllBytes, dhaoBytes);
- if (err == LoadImageErrorCode.OK)
- {
- Debug.Log($"LoadDifferentialHybridAssembly {assName} OK");
- }
- else
- {
- Debug.LogError($"LoadDifferentialHybridAssembly {assName} failed, err={err}");
- }
-}
-```
-
## 配置函数注入策略
@@ -181,73 +74,9 @@ void LoadDifferentialHybridAssembly(string assemblyName)
在 `HybridCLR Settings`中`InjectRuleFiles`字段中填写注入策略文件路径,文件的相对路径为项目根目录(如`Assets/InjectRules/DefaultInjectRules.xml`)。
-## 打包
-
-DHE技术中与构建相关的文件为dhe dll文件和对应的dhao文件。
-
-### 非加密工作流
-
-#### 构建主包
-
-- 将构建后生成的裁剪AOT dll作为 首包(没有任何改动)的dhe dll
-- 使用`HybridCLR.Editor.DHE.BuildUtils.GenerateUnchangedDHAODatas`生成首包的dhao文件
-
-如果使用带校验的工作流,则执行以下操作:
-
-- 为dhe dll生成一个至少包含 assemblyName,md5的`{manifest}`清单文件(由开发者自由决定怎么实现),因为`RuntimeApi.LoadDifferentialHybridAssembly`需要提供dhe dll的原始md5
-- 将 dhe dll、dhao文件及`{manifest}`文件加入热更新资源管理系统
-
-如果使用不带校验的工作流,则执行以下操作:
-
-- 将 dhe dll、dhao文件加入热更新资源管理系统
-
-如果想随包携带首包的dhe dll和dhao文件,请先导出工程,再按照上面的步骤生成dhe dll和dhao文件,再将它们加入到导出工程中。
-
-
-#### 热更新
-
-- 使用 `HybridCLR/CompileDll/ActivedBuildTarget` 生成热更新dll。
-- 使用`HybridCLR.Editor.DHE.BuildUtils.GenerateDHAODatas`生成最新的热更新dll的dhao文件
-- 将最新的热更新dll和dhao文件加入热更新资源管理系统
-
-:::caution
-
-如果打包使用 **development build 选项**,请一定要对应使用`HybridCLR/CompileDll/ActivedBuildTarget_Development`编译Development模式的热更新dll,否则对比结果为几乎所有函数都被判定为发生变化。
-
-:::
-
-### 加密工作流
-
-#### 构建主包
-
-- 将构建后生成的裁剪AOT dll作为 原始dhe dll
-- 使用`HybridCLR.Editor.DHE.BuildUtils.EncryptDllAndGenerateUnchangedDHAODatas`生成首包的dhao文件及加密后的dhe dll文件
-
-如果使用带校验的工作流,则执行以下操作:
-
-- 为dhe dll生成一个至少包含 assemblyName,md5的`{manifest}`清单文件(由开发者自由决定怎么实现),因为`RuntimeApi.LoadDifferentialHybridAssembly`需要提供dhe dll的原始md5
-- 将 加密后的dhe dll、dhao文件及`{manifest}`文件加入热更新资源管理系统
-
-如果使用不带校验的工作流,则执行以下操作:
-
-- 将 加密后的dhe dll、dhao文件加入热更新资源管理系统
-
-
-#### 热更新
-
-- 使用 `HybridCLR/CompileDll/ActivedBuildTarget` 生成热更新dll。
-- 使用`HybridCLR.Editor.DHE.BuildUtils.EncryptDllAndGenerateDHAODatas`生成最新的dhe dll的加密后的文件及对应的dhao文件
-- 将加密后的dhe dll和dhao文件加入热更新资源管理系统
## 不支持特性
- 不支持开启 `script debugging` 构建选项
-## 注意事项
-
-### 外部dll引发的计算dhao的结果有巨量差异
-
-如果有外部dll被标记为DHE程序集,由于外部dll打包时会被裁剪,而计算dhao文件时,取的是原始的外部dll,导致产生巨量的差异,这不是所期望的。解决办法有几个:
-1. 在link.xml里`` 完全保留外部dll
-2. 不用最新的热更新dll去计算差异,而是使用最新代码重新打包时生成的aot dll去计算差异
diff --git a/docs/business/ultimate/quickstartchecked.md b/docs/business/ultimate/quickstartchecked.md
deleted file mode 100644
index 27b507f9..00000000
--- a/docs/business/ultimate/quickstartchecked.md
+++ /dev/null
@@ -1,482 +0,0 @@
-# 快速上手(带校验的工作流)
-
-本教程引导从空项目开始体验HybridCLR热更新。出于简化起见,只演示BuildTarget为**Windows**或**MacOS** Standalone平台的情况。
-请在Standalone平台上正确跑通热更新流程后再自行尝试Android、iOS平台的热更新,它们的流程非常相似。
-
-旗舰版本使用难度跟社区版本相似,大多数原理相同,建议先熟悉社区版本后再尝试旗舰版本。
-
-自v5.0.0版本起,同时支持带校验的`RuntimeApi.LoadDifferentialHybridAssembly`工作流和不带校验的`RuntimeApi.LoadDifferentialHybridAssemblyUnchecked`工作流。
-本文档介绍带校验的工作流。
-
-:::tip
-
-实践中不带校验的工作流会简单很多,不必传递originalDllMd5和currentDllMd5参数,所以省去了工作流中保存或者计算dll md5的过程。
-但要求开发者确保aot dll、hot update dll、dhao文件的一致性。
-推荐初学者在demo项目中使用带校验的工作流,熟悉工作流后在正式项目中使用不带校验的工作流。
-
-:::
-
-## 体验目标
-
-- 创建热更新程序集
-- 加载热更新程序集,并执行其中热更新代码,打印 `Hello, HybridCLR`
-- 修改热更新代码,打印 `Hello, World`
-
-## 准备环境
-
-### 安装Unity
-
-- 安装 2019.4.x、2020.3.x、2021.3.x、2022.3.x 中任一版本。某些版本有特殊的安装要求,参见[安装hybridclr](../../basic/install.md)
-- 根据你所用的操作系统,安装过程中选择模块时,必须选中 `Windows Build Support(IL2CPP)`或`Mac Build Support(IL2CPP)`
-
-![select il2cpp modules](/img/hybridclr/select_il2cpp_modules.jpg)
-
-### 安装IDE及相关编译环境
-
-- Windows
- - Win下需要安装`visual studio 2019`或更高版本。安装时至少要包含 `使用Unity的游戏开发` 和 `使用c++的游戏开发` 组件
- - 安装git
-- Mac
- - 要求MacOS版本 >= 12,xcode版本 >= 13,例如`xcode 13.4.1, macos 12.4`
- - 安装 git
-
-## 初始化Unity热更新项目
-
-从零开始构造热更新项目的过程较冗长,以下步骤中涉及的代码可参考dhe_demo项目,其仓库地址为 [github](https://github.com/focus-creative-games/dhe_demo) 。
-
-### 创建项目
-
-创建空的Unity项目。
-
-### 创建`ConsoleToScreen.cs`脚本
-
-这个脚本对于演示热更新没有直接作用。它可以打印日志到屏幕上,方便定位错误。
-
-创建 `Assets/ConsoleToScreen.cs` 脚本类,代码如下:
-
-```csharp
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using UnityEngine;
-
-public class ConsoleToScreen : MonoBehaviour
-{
- const int maxLines = 50;
- const int maxLineLength = 120;
- private string _logStr = "";
-
- private readonly List _lines = new List();
-
- public int fontSize = 15;
-
- void OnEnable() { Application.logMessageReceived += Log; }
- void OnDisable() { Application.logMessageReceived -= Log; }
-
- public void Log(string logString, string stackTrace, LogType type)
- {
- foreach (var line in logString.Split('\n'))
- {
- if (line.Length <= maxLineLength)
- {
- _lines.Add(line);
- continue;
- }
- var lineCount = line.Length / maxLineLength + 1;
- for (int i = 0; i < lineCount; i++)
- {
- if ((i + 1) * maxLineLength <= line.Length)
- {
- _lines.Add(line.Substring(i * maxLineLength, maxLineLength));
- }
- else
- {
- _lines.Add(line.Substring(i * maxLineLength, line.Length - i * maxLineLength));
- }
- }
- }
- if (_lines.Count > maxLines)
- {
- _lines.RemoveRange(0, _lines.Count - maxLines);
- }
- _logStr = string.Join("\n", _lines);
- }
-
- void OnGUI()
- {
- GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity,
- new Vector3(Screen.width / 1200.0f, Screen.height / 800.0f, 1.0f));
- GUI.Label(new Rect(10, 10, 800, 370), _logStr, new GUIStyle() { fontSize = Math.Max(10, fontSize) });
- }
-}
-
-
-```
-
-### 创建主场景
-
-- 创建默认初始场景 main.scene
-- 场景中创建一个空GameObject,将ConsoleToScreen挂到上面
-- 在`Build Settings`中添加main场景到打包场景列表
-
-### 创建 HotUpdate 热更新模块
-
-- 创建 `Assets/HotUpdate` 目录
-- 在目录下 右键 `Create/Assembly Definition`,创建一个名为`HotUpdate`的程序集模块
-
-## 安装和配置HybridCLR
-
-### 安装
-
-- 将hybridclr_unity.zip解压后,放到项目Packages目录下,改名为com.code-philosophy.hybridclr
-- 根据你的unity版本解压对应的`il2cpp_plus-{version}.zip`
-- 解压 `hybridclr.zip`
-- 将`hybridclr.zip`解压后的hybridclr目录放到`il2cpp-{version}.zip`解压后的libil2cpp目录下
-- 打开 `HybridCLR/Installer`,启用`从本地复制libil2cpp`选项,选中刚才解压的libil2cpp目录,进行安装
-- 根据你的Unity版本:
- - 如果版本 >= 2020,将 `ModifiedDlls\{verions}\Unity.IL2CPP.dll` 文件替换 `{proj}\HybridCLRData\LocalIl2CppData-WindowsEditor\il2cpp\build\deploy\netcoreapp3.1\Unity.IL2CPP.dll`(Unity 2020)或`{proj}\HybridCLRData\LocalIl2CppData-WindowsEditor\il2cpp\build\deploy\Unity.IL2CPP.dll`(Unity 2021+)。如果没有你的版本对应的文件,联系我们制作一个
- - 如果版本 为 2019,不需要任何操作,因为Install过程中已经自动复制
-
-![installer](/img/hybridclr/ultimate-installer.jpg)
-
-### 配置HybridCLR
-
-- 打开菜单 `HybridCLR/Settings`
-- 在`differentialHybridAssemblies`列表中添加`HotUpdate`程序集
-
-![settings](/img/hybridclr/ultimate-hybridclr-settings.jpg)
-
-### 配置PlayerSettings
-
-- `Scripting Backend` 切换为 `IL2CPP`
-- `Api Compatability Level` 切换为 `.Net 4.x`(Unity 2019-2020) 或 `.Net Framework`(Unity 2021+)
-
-![player settings](/img/hybridclr/ultimate-project-settings.jpg)
-
-## 创建Editor脚本
-
-在`Assets/Editor`目录下创建 BuildTools.cs 文件,内容如下:
-
-```csharp
-
-using HybridCLR.Editor;
-using HybridCLR.Editor.DHE;
-using HybridCLR.Runtime;
-using System.Collections;
-using System.Collections.Generic;
-using System.IO;
-using UnityEditor;
-using UnityEngine;
-
-public static class BuildTools
-{
- public const string BackupAOTDllDir = "HybridCLRData/BackupAOT";
-
- public const string EncrypedDllDir = "HybridCLRData/EncryptedDll";
-
- public const string DhaoDir = "HybridCLRData/Dhao";
-
- public const string ManifestFile = "manifest.txt";
-
-
- ///
- /// 备份构建主包时生成的裁剪AOT dll
- ///
- [MenuItem("BuildTools/BackupAOTDll")]
- public static void BackupAOTDllFromAssemblyPostStrippedDir()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- var backupDir = $"{BackupAOTDllDir}/{target}";
- System.IO.Directory.CreateDirectory(backupDir);
- var dlls = System.IO.Directory.GetFiles(SettingsUtil.GetAssembliesPostIl2CppStripDir(target));
- foreach (var dll in dlls)
- {
- var fileName = System.IO.Path.GetFileName(dll);
- string dstFile = $"{BackupAOTDllDir}/{target}/{fileName}";
- System.IO.File.Copy(dll, dstFile, true);
- Debug.Log($"BackupAOTDllFromAssemblyPostStrippedDir: {dll} -> {dstFile}");
- }
- }
-
- ///
- /// 创建dhe manifest文件,格式为每行一个 'dll名,原始dll的md5'
- ///
- ///
- [MenuItem("BuildTools/CreateManifestAtBackupDir")]
- public static void CreateManifest()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string backupDir = $"{BackupAOTDllDir}/{target}";
- CreateManifest(backupDir);
- }
-
- public static void CreateManifest(string outputDir)
- {
- Directory.CreateDirectory(outputDir);
- var lines = new List();
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string backupDir = $"{BackupAOTDllDir}/{target}";
- foreach (string dheDll in SettingsUtil.DifferentialHybridAssemblyNames)
- {
- string originalDll = $"{backupDir}/{dheDll}.dll";
- string originalDllMd5 = AssemblyOptionDataGenerator.CreateMD5Hash(File.ReadAllBytes(originalDll));
- lines.Add($"{dheDll},{originalDllMd5}");
- }
- string manifestFile = $"{outputDir}/{ManifestFile}";
- File.WriteAllBytes(manifestFile, System.Text.Encoding.UTF8.GetBytes(string.Join("\n", lines)));
- Debug.Log($"CreateManifest: {manifestFile}");
- }
-
- ///
- /// 生成首包的没有任何代码改动对应的dhao数据
- ///
- [MenuItem("BuildTools/GenerateUnchangedDHAODatas")]
- public static void GenerateUnchangedDHAODatas()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string backupDir = $"{BackupAOTDllDir}/{target}";
- string dhaoDir = $"{DhaoDir}/{target}";
- BuildUtils.GenerateUnchangedDHAODatas(SettingsUtil.DifferentialHybridAssemblyNames, backupDir, dhaoDir);
- }
-
- ///
- /// 生成热更包的dhao数据
- ///
- [MenuItem("BuildTools/GenerateDHAODatas")]
- public static void GenerateDHAODatas()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string backupDir = $"{BackupAOTDllDir}/{target}";
- string dhaoDir = $"{DhaoDir}/{target}";
- string currentDllDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
- BuildUtils.GenerateDHAODatas(SettingsUtil.DifferentialHybridAssemblyNames, backupDir, currentDllDir, null, null, dhaoDir);
- }
-
- ///
- /// 生成首包的加密dll和没有任何代码改动对应的dhao数据
- ///
- [MenuItem("BuildTools/GenerateUnchangedEncryptedDllAndDhaoDatas")]
- public static void GenerateUnchangedEncryptedDllAndDhaoDatas()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string backupDir = $"{BackupAOTDllDir}/{target}";
- string dhaoDir = $"{DhaoDir}/{target}";
- string encryptedDllDir = $"{EncrypedDllDir}/{target}";
- BuildUtils.EncryptDllAndGenerateUnchangedDHAODatas(SettingsUtil.DifferentialHybridAssemblyNames, backupDir, encryptedDllDir, dhaoDir);
- }
-
-
- ///
- /// 生成热更包的加密dll和dhao数据
- ///
- [MenuItem("BuildTools/GenerateEncryptedDllAndDhaoDatas")]
- public static void GenerateEncryptedDllAndDhaoDatas()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string backupDir = $"{BackupAOTDllDir}/{target}";
- string dhaoDir = $"{DhaoDir}/{target}";
- string currentDllDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
- string encryptedDllDir = $"{EncrypedDllDir}/{target}";
- BuildUtils.EncryptDllAndGenerateDHAODatas(SettingsUtil.DifferentialHybridAssemblyNames, backupDir, currentDllDir, null, null, encryptedDllDir, dhaoDir);
- }
-
- ///
- /// 复制没有改动的首包dll和dhao文件到StreamingAssets
- ///
- [MenuItem("BuildTools/CopyUnchangedDllAndDhaoFileAndManifestToStreamingAssets")]
- public static void CopyUnchangedDllAndDhaoFileToStreamingAssets()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string streamingAssetsDir = Application.streamingAssetsPath;
- Directory.CreateDirectory(streamingAssetsDir);
-
- string manifestFile = $"{BackupAOTDllDir}/{target}/{ManifestFile}";
- string dstManifestFile = $"{streamingAssetsDir}/{ManifestFile}";
- System.IO.File.Copy(manifestFile, dstManifestFile, true);
- Debug.Log($"CopyUnchangedDllAndDhaoFileToStreamingAssets: {manifestFile} -> {dstManifestFile}");
-
- string dllDir = $"{BackupAOTDllDir}/{target}";
- string dhaoDir = $"{DhaoDir}/{target}";
- foreach (var dll in SettingsUtil.DifferentialHybridAssemblyNames)
- {
- string srcFile = $"{dllDir}/{dll}.dll";
- string dstFile = $"{streamingAssetsDir}/{dll}.dll.bytes";
- System.IO.File.Copy(srcFile, dstFile, true);
- Debug.Log($"CopyUnchangedDllAndDhaoFileToStreamingAssets: {srcFile} -> {dstFile}");
- string dhaoFile = $"{dhaoDir}/{dll}.dhao.bytes";
- dstFile = $"{streamingAssetsDir}/{dll}.dhao.bytes";
- System.IO.File.Copy(dhaoFile, dstFile, true);
- Debug.Log($"CopyUnchangedDllAndDhaoFileToStreamingAssets: {dhaoFile} -> {dstFile}");
- }
- }
-
- ///
- /// 复制热更新dll和dhao文件到StreamingAssets
- ///
- [MenuItem("BuildTools/CopyDllAndDhaoFileToStreamingAssets")]
- public static void CopyDllAndDhaoFileToStreamingAssets()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string streamingAssetsDir = Application.streamingAssetsPath;
- Directory.CreateDirectory(streamingAssetsDir);
-
- string dllDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
- string dhaoDir = $"{DhaoDir}/{target}";
- foreach (var dll in SettingsUtil.DifferentialHybridAssemblyNames)
- {
- string srcFile = $"{dllDir}/{dll}.dll";
- string dstFile = $"{streamingAssetsDir}/{dll}.dll.bytes";
- System.IO.File.Copy(srcFile, dstFile, true);
- Debug.Log($"CopyUnchangedDllAndDhaoFileToStreamingAssets: {srcFile} -> {dstFile}");
- string dhaoFile = $"{dhaoDir}/{dll}.dhao.bytes";
- dstFile = $"{streamingAssetsDir}/{dll}.dhao.bytes";
- System.IO.File.Copy(dhaoFile, dstFile, true);
- Debug.Log($"CopyUnchangedDllAndDhaoFileToStreamingAssets: {dhaoFile} -> {dstFile}");
- }
- }
-
-}
-
-
-```
-
-## 创建热更新脚本
-
-创建 `Assets/HotUpdate/Hello.cs` 文件,代码内容如下
-
-```csharp
-using System.Collections;
-using UnityEngine;
-
-public class Hello
-{
- public static void Run()
- {
- Debug.Log("Hello, HybridCLR");
- }
-}
-```
-
-## 加载热更新程序集
-
-为了简化演示,我们不通过http服务器下载HotUpdate.dll,而是直接将HotUpdate.dll放到StreamingAssets目录下。
-
-创建`Assets/LoadDll.cs`脚本,然后**在main场景中创建一个GameObject对象,挂载LoadDll脚本**。
-
-
-```csharp
-using HybridCLR;
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Security.Cryptography;
-using System.Text;
-using System.Threading.Tasks;
-using UnityEngine;
-using UnityEngine.Networking;
-
-public class LoadDll : MonoBehaviour
-{
-
- void Start()
- {
- // Editor环境下,HotUpdate.dll.bytes已经被自动加载,不需要加载,重复加载反而会出问题。
-#if !UNITY_EDITOR
- var manifests = LoadManifest($"{Application.streamingAssetsPath}/manifest.txt");
- Assembly hotUpdateAss = LoadDifferentialHybridAssembly(manifests["HotUpdate"], "HotUpdate");
-#else
- // Editor下无需加载,直接查找获得HotUpdate程序集
- Assembly hotUpdateAss = System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "HotUpdate");
-#endif
- Type helloType = hotUpdateAss.GetType("Hello");
- MethodInfo runMethod = helloType.GetMethod("Run");
- runMethod.Invoke(null, null);
- }
-
- class Manifest
- {
- public string AssemblyName { get; set; }
-
- public string OriginalDllMd5 { get; set; }
- }
-
- private Dictionary LoadManifest(string manifestFile)
- {
- var manifest = new Dictionary();
- var lines = File.ReadAllLines(manifestFile, Encoding.UTF8);
- foreach (var line in lines)
- {
- string[] args = line.Split(",");
- if (args.Length != 2)
- {
- Debug.LogError($"manifest file format error, line={line}");
- return null;
- }
- manifest.Add(args[0], new Manifest()
- {
- AssemblyName = args[0],
- OriginalDllMd5 = args[1],
- });
- }
- return manifest;
- }
-
-
- public static string CreateMD5Hash(byte[] bytes)
- {
- return BitConverter.ToString(new MD5CryptoServiceProvider().ComputeHash(bytes)).Replace("-", "").ToUpperInvariant();
- }
-
- private Assembly LoadDifferentialHybridAssembly(Manifest manifest, string assName)
- {
- byte[] dllBytes = File.ReadAllBytes($"{Application.streamingAssetsPath}/{assName}.dll.bytes");
- byte[] dhaoBytes = File.ReadAllBytes($"{Application.streamingAssetsPath}/{assName}.dhao.bytes");
- string currentDllMd5 = CreateMD5Hash(dllBytes);
- LoadImageErrorCode err = RuntimeApi.LoadDifferentialHybridAssembly(dllBytes, dhaoBytes, manifest.OriginalDllMd5, currentDllMd5);
- if (err == LoadImageErrorCode.OK)
- {
- Debug.Log($"LoadDifferentialHybridAssembly {assName} OK");
- return System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == assName);
- }
- else
- {
- Debug.LogError($"LoadDifferentialHybridAssembly {assName} failed, err={err}");
- return null;
- }
- }
-}
-
-```
-
-
-至此,完成整个热更新工程的创建工作!!!
-
-## Editor中试运行
-
-运行main场景,屏幕上会显示 'Hello,HybridCLR',表示代码工作正常。
-
-## 打包运行
-
-- 运行菜单 `HybridCLR/Generate/All` 进行必要的生成操作。**这一步不可遗漏**!!!
-- 打开 `Build Settings` 对话框,点击`Build`,选择输出目录`{build}`,执行构建
-- 运行 `BuildTools/BackupAOTDll` 备份裁剪后的dhe dll。 实践中这些dll应该加入版本管理,用于后面生成dhao文件,这些文件不会再被修改
-- 运行 `BuildTools/CreateManifestAtBackupDir`生成原始dhe dll的清单文件。实践中这个清单文件应该加入版本管理,而且不会再被修改
-- 运行 `BuildTools/GenerateUnchangedDHAODatas` 生成首包的dhao文件
-- 运行 `BuildTools/CopyUnchangedDllAndDhaoFileAndManifestToStreamingAssets` 复制首包 dhe程序集、dhao文件、清单文件到 StreamingAssets
-- 将 `Assets/StreamingAssets`目录复制到`{build}\dhe_demo2_Data\StreamingAssets`
-- 运行`{build}/Xxx.exe`,屏幕显示 `Hello,HybridCLR`,表示热更新代码被顺利执行!
-
-## 测试热更新
-
-- 修改`Assets/HotUpdate/Hello.cs`的Run函数中`Debug.Log("Hello, HybridCLR");`代码,改成`Debug.Log("Hello, World");`。
-- 运行`HybridCLR/CompileDll/ActiveBulidTarget`生成热更新dll
-- 运行`BuildTools/GenerateDHAODatas` 生成dhao文件
-- 运行`BuildTools/CopyDllAndDhaoFileToStreamingAssets`复制热更新dll和dhao文件到StreamingAssets目录
-- 将 `Assets/StreamingAssets`目录复制到`{build}\dhe_demo2_Data\StreamingAssets`
-- 重新运行程序,会发现屏幕中显示`Hello, World`,表示热更新代码生效了!
-
-
-至此完成热更新体验!!!
diff --git a/docs/business/ultimate/quickstartunchecked.md b/docs/business/ultimate/quickstartunchecked.md
index 9b686248..42ce6276 100644
--- a/docs/business/ultimate/quickstartunchecked.md
+++ b/docs/business/ultimate/quickstartunchecked.md
@@ -1,20 +1,10 @@
-# 快速上手(不带校验的工作流)
+# 快速上手
本教程引导从空项目开始体验HybridCLR热更新。出于简化起见,只演示BuildTarget为**Windows**或**MacOS** Standalone平台的情况。
请在Standalone平台上正确跑通热更新流程后再自行尝试Android、iOS平台的热更新,它们的流程非常相似。
旗舰版本使用难度跟社区版本相似,大多数原理相同,建议先熟悉社区版本后再尝试旗舰版本。
-自v5.0.0版本起,同时支持带校验的`RuntimeApi.LoadDifferentialHybridAssembly`工作流和不带校验的`RuntimeApi.LoadDifferentialHybridAssemblyUnchecked`工作流。
-本文档介绍不带校验的工作流。
-
-:::tip
-
-实践中不带校验的工作流会简单很多,不必传递originalDllMd5和currentDllMd5参数,所以省去了工作流中保存或者计算dll md5的过程。
-但要求开发者确保aot dll、hot update dll、dhao文件的一致性。
-推荐初学者在demo项目中使用带校验的工作流,熟悉工作流后在正式项目中使用不带校验的工作流。
-
-:::
## 体验目标
@@ -170,7 +160,9 @@ using UnityEngine;
public static class BuildTools
{
- public const string BackupAOTDllDir = "HybridCLRData/BackupAOT";
+ public const string BackupAOTDllDir = "HybridCLRData/BackupAOT";
+
+ public const string EncrypedDllDir = "HybridCLRData/EncryptedDll";
public const string DhaoDir = "HybridCLRData/Dhao";
@@ -193,19 +185,7 @@ public static class BuildTools
Debug.Log($"BackupAOTDllFromAssemblyPostStrippedDir: {dll} -> {dstFile}");
}
}
-
- ///
- /// 生成首包的没有任何代码改动对应的dhao数据
- ///
- [MenuItem("BuildTools/GenerateUnchangedDHAODatas")]
- public static void GenerateUnchangedDHAODatas()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string backupDir = $"{BackupAOTDllDir}/{target}";
- string dhaoDir = $"{DhaoDir}/{target}";
- BuildUtils.GenerateUnchangedDHAODatas(SettingsUtil.DifferentialHybridAssemblyNames, backupDir, dhaoDir);
- }
-
+
///
/// 生成热更包的dhao数据
///
@@ -216,56 +196,46 @@ public static class BuildTools
string backupDir = $"{BackupAOTDllDir}/{target}";
string dhaoDir = $"{DhaoDir}/{target}";
string currentDllDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
- BuildUtils.GenerateDHAODatas(SettingsUtil.DifferentialHybridAssemblyNames, backupDir, currentDllDir, null, null, dhaoDir);
+ BuildUtils.GenerateDHAODatas(SettingsUtil.DifferentialHybridAssemblyNames, backupDir, currentDllDir, null, HybridCLRSettings.Instance.injectRuleFiles, dhaoDir);
}
- ///
- /// 复制没有改动的首包dll和dhao文件到StreamingAssets
- ///
- [MenuItem("BuildTools/CopyUnchangedDllAndDhaoFileToStreamingAssets")]
- public static void CopyUnchangedDllAndDhaoFileToStreamingAssets()
+ [MenuItem("BuildTools/CompileHotUpdateDlls")]
+ public static void CompileHotUpdateDlls()
{
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string streamingAssetsDir = Application.streamingAssetsPath;
- Directory.CreateDirectory(streamingAssetsDir);
+ CompileDllCommand.CompileDll(target);
+ }
- string dllDir = $"{BackupAOTDllDir}/{target}";
- string dhaoDir = $"{DhaoDir}/{target}";
- foreach (var dll in SettingsUtil.DifferentialHybridAssemblyNames)
- {
- string srcFile = $"{dllDir}/{dll}.dll";
- string dstFile = $"{streamingAssetsDir}/{dll}.dll.bytes";
- System.IO.File.Copy(srcFile, dstFile, true);
- Debug.Log($"CopyUnchangedDllAndDhaoFileToStreamingAssets: {srcFile} -> {dstFile}");
- string dhaoFile = $"{dhaoDir}/{dll}.dhao.bytes";
- dstFile = $"{streamingAssetsDir}/{dll}.dhao.bytes";
- System.IO.File.Copy(dhaoFile, dstFile, true);
- Debug.Log($"CopyUnchangedDllAndDhaoFileToStreamingAssets: {dhaoFile} -> {dstFile}");
- }
+
+ [MenuItem("BuildTools/CompileHotUpdateDllsAndGenerateDHAODatas")]
+ public static void CompileHotUpdateDllsAndGenerateDHAODatas()
+ {
+ CompileHotUpdateDlls();
+ GenerateDHAODatas();
}
///
- /// 复制热更新dll和dhao文件到StreamingAssets
+ /// 复制热更新dll和dhao文件到HotUpdateDatas
///
- [MenuItem("BuildTools/CopyDllAndDhaoFileToStreamingAssets")]
- public static void CopyDllAndDhaoFileToStreamingAssets()
+ [MenuItem("BuildTools/CopyDllAndDhaoFileToHotUpdateDataDir")]
+ public static void CopyDllAndDhaoFileToHotUpdateDataDir()
{
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string streamingAssetsDir = Application.streamingAssetsPath;
- Directory.CreateDirectory(streamingAssetsDir);
+ string hotUpdateDatasDir = $"{Application.dataPath}/../HotUpdateDatas";
+ Directory.CreateDirectory(hotUpdateDatasDir);
string dllDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
string dhaoDir = $"{DhaoDir}/{target}";
foreach (var dll in SettingsUtil.DifferentialHybridAssemblyNames)
{
string srcFile = $"{dllDir}/{dll}.dll";
- string dstFile = $"{streamingAssetsDir}/{dll}.dll.bytes";
+ string dstFile = $"{hotUpdateDatasDir}/{dll}.dll.bytes";
System.IO.File.Copy(srcFile, dstFile, true);
- Debug.Log($"CopyUnchangedDllAndDhaoFileToStreamingAssets: {srcFile} -> {dstFile}");
+ Debug.Log($"Copy: {srcFile} -> {dstFile}");
string dhaoFile = $"{dhaoDir}/{dll}.dhao.bytes";
- dstFile = $"{streamingAssetsDir}/{dll}.dhao.bytes";
+ dstFile = $"{hotUpdateDatasDir}/{dll}.dhao.bytes";
System.IO.File.Copy(dhaoFile, dstFile, true);
- Debug.Log($"CopyUnchangedDllAndDhaoFileToStreamingAssets: {dhaoFile} -> {dstFile}");
+ Debug.Log($"Copy: {dhaoFile} -> {dstFile}");
}
}
}
@@ -285,7 +255,10 @@ public class Hello
{
public static void Run()
{
- Debug.Log("Hello, HybridCLR");
+ // 原始代码
+ Debug.Log("Hello, World");
+ // 热更新后改为
+ // Debug.Log("Hello, HybridCLR");
}
}
```
@@ -318,34 +291,54 @@ public class LoadDll : MonoBehaviour
{
// Editor环境下,HotUpdate.dll.bytes已经被自动加载,不需要加载,重复加载反而会出问题。
#if !UNITY_EDITOR
- Assembly hotUpdateAss = LoadDifferentialHybridAssembly("HotUpdate");
-#else
- // Editor下无需加载,直接查找获得HotUpdate程序集
- Assembly hotUpdateAss = System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "HotUpdate");
+ LoadDifferentialHybridAssembly("HotUpdate");
#endif
+ Assembly hotUpdateAss = System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "HotUpdate");
Type helloType = hotUpdateAss.GetType("Hello");
MethodInfo runMethod = helloType.GetMethod("Run");
runMethod.Invoke(null, null);
}
- private Assembly LoadDifferentialHybridAssembly(string assName)
+
+ ///
+ ///
+ ///
+ /// 不含文件名后缀的程序集名,如HotUpdate
+ ///
+ private void LoadDifferentialHybridAssembly(string assName)
{
- byte[] dllBytes = File.ReadAllBytes($"{Application.streamingAssetsPath}/{assName}.dll.bytes");
- byte[] dhaoBytes = File.ReadAllBytes($"{Application.streamingAssetsPath}/{assName}.dhao.bytes");
- LoadImageErrorCode err = RuntimeApi.LoadDifferentialHybridAssemblyUnchecked(dllBytes, dhaoBytes);
- if (err == LoadImageErrorCode.OK)
+ string assFile = $"{Application.streamingAssetsPath}/{assName}.dll.bytes";
+ // 如果不存在,则使用原始AOT程序集
+ if (!File.Exists(assFile))
{
- Debug.Log($"LoadDifferentialHybridAssembly {assName} OK");
- return System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == assName);
+ LoadImageErrorCode err = RuntimeApi.LoadOriginalDifferentialHybridAssembly(assName);
+ if (err == LoadImageErrorCode.OK)
+ {
+ Debug.Log($"LoadOriginalDifferentialHybridAssembly {assName} OK");
+ }
+ else
+ {
+ Debug.LogError($"LoadOriginalDifferentialHybridAssembly {assName} failed, err={err}");
+ }
}
else
{
- Debug.LogError($"LoadDifferentialHybridAssembly {assName} failed, err={err}");
- return null;
+ byte[] dllBytes = File.ReadAllBytes($"{Application.streamingAssetsPath}/{assName}.dll.bytes");
+ byte[] dhaoBytes = File.ReadAllBytes($"{Application.streamingAssetsPath}/{assName}.dhao.bytes");
+ LoadImageErrorCode err = RuntimeApi.LoadDifferentialHybridAssemblyUnchecked(dllBytes, dhaoBytes);
+ if (err == LoadImageErrorCode.OK)
+ {
+ Debug.Log($"LoadDifferentialHybridAssembly {assName} OK");
+ }
+ else
+ {
+ Debug.LogError($"LoadDifferentialHybridAssembly {assName} failed, err={err}");
+ }
}
}
}
+
```
@@ -353,26 +346,32 @@ public class LoadDll : MonoBehaviour
## Editor中试运行
-运行main场景,屏幕上会显示 'Hello,HybridCLR',表示代码工作正常。
+运行main场景,屏幕上会显示 'Hello, World',表示代码工作正常。
-## 打包运行
+## 构建游戏
- 运行菜单 `HybridCLR/Generate/All` 进行必要的生成操作。**这一步不可遗漏**!!!
- 打开 `Build Settings` 对话框,点击`Build`,选择输出目录`{build}`,执行构建
-- 运行 `BuildTools/BackupAOTDll` 备份裁剪后的dhe dll。 实践中这些dll应该加入版本管理,用于后面生成dhao文件,这些文件不会再被修改
-- 运行 `BuildTools/GenerateUnchangedDHAODatas` 生成首包的dhao文件
-- 运行 `BuildTools/CopyUnchangedDllAndDhaoFileToStreamingAssets` 复制首包 dhe程序集、dhao文件到 StreamingAssets
-- 将 `Assets/StreamingAssets`目录复制到`{build}\dhe_demo2_Data\StreamingAssets`
-- 运行`{build}/Xxx.exe`,屏幕显示 `Hello,HybridCLR`,表示热更新代码被顺利执行!
+- 运行 `BuildTools/BackupAOTDll` 备份构建时生成的dhe dll。 **这一步必须在`Build`之后**,因为原始AOT dll必须是构建时生成的dll,而不是`HybridCLR/Generate/all`时生成
+
+:::tip
+
+`BuildTools/BackupAOTDll`备份的dll应该加入版本管理,用于将来热更新时生成dhao文件。
+
+:::
+
+## 首包测试
+
+- 运行`{build}/Xxx.exe`,屏幕显示 `Hello, World`,表示执行了原始代码!
## 测试热更新
-- 修改`Assets/HotUpdate/Hello.cs`的Run函数中`Debug.Log("Hello, HybridCLR");`代码,改成`Debug.Log("Hello, World");`。
-- 运行`HybridCLR/CompileDll/ActiveBulidTarget`生成热更新dll
-- 运行`BuildTools/GenerateDHAODatas` 生成dhao文件
-- 运行`BuildTools/CopyDllAndDhaoFileToStreamingAssets`复制热更新dll和dhao文件到StreamingAssets目录
-- 将 `Assets/StreamingAssets`目录复制到`{build}\dhe_demo2_Data\StreamingAssets`
-- 重新运行程序,会发现屏幕中显示`Hello, World`,表示热更新代码生效了!
+- 请确保`构建游戏`这一步已经执行了`BuildTools/BackupAOTDll`,运行一次即可,不要多次运行
+- 修改`Hello::Run`函数中`Debug.Log("Hello, World")`为`Debug.Log("Hello, HybridCLR")`
+- 运行`BuildTools/CompileHotUpdateDllsAndGenerateDHAODatas` 生成热更新dll及对应的dhao文件
+- 运行`BuildTools/CopyDllAndDhaoFileToHotUpdateDataDir`复制HotUpdate.dll.bytes和HotUpdate.dhao.bytes到`HotUpdateDatas`目录
+- 手动复制`HotUpdateDatas`目录下HotUpdate.dll.bytes和HotUpdate.dhao.bytes到`{build}\StreamingAssets`目录下
+- 再次运行,屏幕上会打印`Hello, HybridCLR`
至此完成热更新体验!!!
diff --git a/docs/business/ultimate/useIncodes.md b/docs/business/ultimate/useIncodes.md
new file mode 100644
index 00000000..e85334d7
--- /dev/null
+++ b/docs/business/ultimate/useIncodes.md
@@ -0,0 +1,72 @@
+# 代码中使用
+
+
+## RuntimeApi::LoadOriginalDifferentialHybridAssembly
+
+:::tip
+
+自v6.6.0版本支持接口。
+
+:::
+
+在初次构建App未发生任何代码更新,或者说虽然有代码更新,但该DHE程序集的代码没有更新时,可以调用此接口,表示完全使用原始AOT实现。
+
+
+示例代码:
+
+```csharp
+ string assFile = $"{Application.streamingAssetsPath}/{assName}.dll.bytes";
+ // 如果不存在,则使用原始AOT程序集
+ if (!File.Exists(assFile))
+ {
+ LoadImageErrorCode err = RuntimeApi.LoadOriginalDifferentialHybridAssembly(assName);
+ if (err == LoadImageErrorCode.OK)
+ {
+ Debug.Log($"LoadOriginalDifferentialHybridAssembly {assName} OK");
+ }
+ else
+ {
+ Debug.LogError($"LoadOriginalDifferentialHybridAssembly {assName} failed, err={err}");
+ }
+ }
+```
+
+
+## RuntimeApi::LoadDifferentialHybridAssemblyUnchecked
+
+当某个DHE程序集代码发生变化时,需要用此接口加载DHE程序集。注意,不能使用Assembly.Load加载DHE程序集,会出错。
+
+该接口有两个参数: currentDllBytes和optionBytes。
+
+- currentDllBytes为最新的DHE程序集文件的字节
+- optionBytes 为dhao文件的字节。[dhao文件](./dhao)包含了DHE的变化信息,用于指示哪些函数以aot模式运行,哪些以解释方式执行。
+
+```csharp
+
+ string assFile = $"{Application.streamingAssetsPath}/{assName}.dll.bytes";
+ // 如果不存在,则使用原始AOT程序集
+ if (File.Exists(assFile))
+ {
+ byte[] dllBytes = File.ReadAllBytes($"{Application.streamingAssetsPath}/{assName}.dll.bytes");
+ byte[] dhaoBytes = File.ReadAllBytes($"{Application.streamingAssetsPath}/{assName}.dhao.bytes");
+ LoadImageErrorCode err = RuntimeApi.LoadDifferentialHybridAssemblyUnchecked(dllBytes, dhaoBytes);
+ if (err == LoadImageErrorCode.OK)
+ {
+ Debug.Log($"LoadDifferentialHybridAssembly {assName} OK");
+ }
+ else
+ {
+ Debug.LogError($"LoadDifferentialHybridAssembly {assName} failed, err={err}");
+ }
+ }
+
+```
+
+
+## 注意事项:
+
+- 即使DHE程序集没有发生改变,在运行DHE程序集中任何代码前,仍然要显式执行RuntimeApi::LoadOriginalDifferentialHybridAssembly
+- 要按照assembly的依赖顺序LoadOriginalDifferentialHybridAssembly或LoadDifferentialHybridAssemblyUnchecked加载 DHE程序集
+- RuntimeApi::LoadOriginalDifferentialHybridAssembly 加载的DHE程序集为普通AOT程序集,如果其他热更新程序集中引用了该DHE程序集中的泛型,并且没有开启完全泛型共享,则会与普通AOT程序集一样出现AOT泛型问题,可以使用完全泛型共享或者补充元数据机制解决
+- RuntimeApi::LoadDifferentialHybridAssemblyUnchecked 加载的DHE程序集本身已经包含了元数据,即使未开启完全泛型共享时也**不要对DHE程序集进行补充元数据**,补充了也会失败,其他非DHE的AOT程序集可以照常补充元数据。
+
diff --git a/docs/business/ultimate/workflow.md b/docs/business/ultimate/workflow.md
deleted file mode 100644
index 784db216..00000000
--- a/docs/business/ultimate/workflow.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# 简化dhao工作流
-
-基于同一版本的原始工程,在发布不同平台时原始dll会有微小区别,导致需要为每个平台都计算单独的dhao文件(即使是相同平台,由于代码编译的不稳定性,
-生成的原始dll也可能有微小区别),这导致维护dhao工作变得复杂易错。当多个新旧游戏包同时存在时,这个问题尤为严重。
-
-解决这个问题主要靠`合并dhao文件`。
-
-## 合并dhao文件
-
-基于相同或者相似源码发布的游戏包,它们的原始dhe程序集在不同平台之间仅有微小区分,热更新时生成的dhao文件也只有微小区别。
-可以考虑将同一个dhe程序集对应的多个平台的dhao文件合并,不影响运行正确性的同时对性能的影响也很小。
-
-我们提供了`HybridCLR.Editor.DHE.BuildUtil::MergeDHAOFiles`函数实现合并dhao文件目标。
-
-注意,带校验的工作流无法使用合并dhao文件的方式,因为带校验的工作流会检查原始dll的md5码,这个肯定是不匹配的。
-
diff --git a/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/build.md b/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/build.md
new file mode 100644
index 00000000..47efc433
--- /dev/null
+++ b/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/build.md
@@ -0,0 +1,24 @@
+# Build and hot update
+
+The files related to the build in DHE technology are dhe dll files and corresponding dhao files.
+
+## Build the game
+
+Since the code in all DHE assemblies in the first package has not changed, no DHE-related dll or dhao files are needed in the game building workflow.
+
+- Run `HybridCLR/Generate/All`
+- Build the game
+- Back up all assemblies in the `HybridCLRData\AssembliesPostIl2CppStrip\{buildTarget}` directory and add them to the version management system. These original dll files will be needed when hot updating to generate dhao files in the future
+
+## Hot Update
+
+- Use `HybridCLR/CompileDll/ActivedBuildTarget` to generate hot update dlls.
+- Use `HybridCLR.Editor.DHE.BuildUtils.GenerateDHAODatas` to generate the latest hot update dll dhao files. If you need to encrypt the DHE assembly, use `HybridCLR.Editor.DHE.BuildUtils.EncryptDllAndGenerateDHAODatas` to generate the encrypted DLL and the corresponding DHA file.
+- Add the latest hot update DLL (or encrypted DLL) and DHA file to the hot update resource management system. Note that the original DLL file is not needed at runtime, so please do not add the backed-up original DLL to the hot update resource management system.
+
+:::caution
+
+If you use the **development build option** to build the game, please be sure to use `HybridCLR/CompileDll/ActivedBuildTarget_Development` to compile the hot update DLL in Development mode.
+Otherwise, due to the large difference between the developmentemnt and non-development compiled DLLs, almost all functions will be calculated as changes.
+
+:::
diff --git a/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/dhao.md b/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/dhao.md
new file mode 100644
index 00000000..8eb816c3
--- /dev/null
+++ b/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/dhao.md
@@ -0,0 +1,47 @@
+# DHAO file
+
+The dhao file is the core concept of DHE technology. The dhao file contains the information of the types and functions changed in the latest hot update dll calculated offline. When executing a hot update function, the runtime directly determines whether to use the latest interpreted version or directly call the original AOT function based on the information in the dhao file.
+The dhao file calculated offline is extremely critical for DHE technology. If there is no dhao file, the original AOT dll needs to be carried additionally, and the cost of calculating function changes is extremely high.
+
+By comparing the latest hot update dll with the AOT dll generated during packaging, the changed types and functions are calculated offline and saved as dhao files. Therefore, for the DHE mechanism to work properly, it must rely on the correctness of the dhao file, and the correctness of the dhao file
+depends on accurately providing the latest hot update dll and the AOT dll generated during packaging.
+
+`HybridCLR.Editor.DHE.BuildUtils` provides multiple functions related to generating dhao files.
+
+|Function name|Description|
+|-|-|
+|GenerateDHAODatas|Generate dhao file for hot update package (i.e. when code changes)|
+|EncryptDllAndGenerateDHAODatas|When primary code reinforcement is enabled, generate encrypted dll and dhao file for hot update package (i.e. when code changes)|
+
+## Mark changed function information
+
+Currently, it is possible to automatically calculate the changed functions by comparing the latest hot update dll with the aot dll generated during packaging, and manual operation is not required in most cases. But in fact, there is no perfect code that can determine logical equivalence.
+The tool simply compares IL one by one to determine equivalence. Sometimes, the function may be equivalent but the IL has changed (such as swapping the order of two unrelated lines of code), which will be judged as a function transformation and switched to interpreted execution.
+If this happens, **and there are extremely strict performance requirements for the function**, developers can manually use the UnchangedAttribute feature to mark the function's variability.
+`[Unchanged]` and `[Unchanged(true)]` indicate unchanged, `[Unchanged(false)]` indicates changed, and unmarked features are automatically calculated by the tool.
+
+Incorrectly marking unchanged functions as changed will not affect the correctness of the operation, but only the performance. Even if all hot update functions are marked as changed, they can still run normally. However, incorrectly marking changed functions as unchanged will not only cause errors in the operation logic,
+but also cause crashes in serious cases!
+
+:::caution
+Unless there are special circumstances and you are an experienced expert, do not mark manually. Because the compiler often generates some hidden classes or fields, these class names are not stable. The C# code that looks the same on the surface may not be the same as the actual generated code. Forcibly marking it as `[Unchanged]` will lead to incorrect operation logic or even crashes.
+:::
+
+## Merge dhao files
+
+Game packages released based on the same or similar source code have only slight differences in their original dhe assemblies on different platforms, and the dhao files generated during hot updates also have only slight differences.
+This results in the need to calculate a separate dhao file for each platform (even for the same platform, the generated original dll may have slight differences due to the instability of code compilation), which makes the maintenance of dhao complicated and error-prone. This problem is particularly serious when multiple new and old game packages exist at the same time.
+You can consider merging the dhao files of multiple platforms corresponding to the same dhe assembly, which does not affect the correctness of the operation and has little impact on performance.
+
+We provide the `HybridCLR.Editor.DHE.BuildUtil::MergeDHAOFiles` function to achieve the goal of merging dhao files.
+
+Note that the workflow with verification cannot use the method of merging dhao files, because the workflow with verification will check the md5 code of the original dll, which is definitely not a match.
+
+## Notes
+
+### The results of calculating dhao caused by external dlls have huge differences
+
+If an external dll is marked as a DHE assembly, the external dll will be trimmed when it is packaged, and when calculating the dhao file, the original external dll is taken, resulting in huge differences, which is not expected. There are several solutions:
+
+1. In link.xml, `` completely retain the external dll
+2. Instead of using the latest hot update dll to calculate the difference, use the aot dll generated when the latest code is repackaged to calculate the difference
diff --git a/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/freetrial.md b/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/freetrial.md
index f7d8f24b..cb7b2ff3 100644
--- a/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/freetrial.md
+++ b/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/freetrial.md
@@ -52,4 +52,4 @@ In the trial version, the source code of some modules is removed and replaced wi
## Usage
-Apart from minor adjustments in installation and configuration as described above, the rest remains entirely according to the [Quick Start](./quickstartchecked) documentation.
+Apart from minor adjustments in installation and configuration as described above, the rest remains entirely according to the [Quick Start](./quickstartunchecked) documentation.
diff --git a/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/manual.md b/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/manual.md
index 64ce6765..b8c1e91d 100644
--- a/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/manual.md
+++ b/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/manual.md
@@ -1,253 +1,71 @@
-# Manual
+# User Manual
-## Install
+## Installation
-- Unzip hybridclr_unity.zip, place it in the project Packages directory, and rename it com.code-philosophy.hybridclr
-- Unzip the corresponding `il2cpp_plus-{version}.zip` according to your unity version
+- Unzip hybridclr_unity.zip and put it in the project Packages directory, rename it to com.code-philosophy.hybridclr
+- Unzip the corresponding `il2cpp_plus-{version}.zip` according to your Unity version
- Unzip `hybridclr.zip`
-- Place the hybridclr directory after decompression of `hybridclr.zip` into the libil2cpp directory after decompression of `il2cpp-{version}.zip`
-- Open `HybridCLR/Installer`, enable the `Copy libil2cpp from local` option, select the libil2cpp directory you just decompressed, and install it.
-- Depending on your Unity version:
- - If version >= 2020, replace the `ModifiedDlls\{verions}\Unity.IL2CPP.dll` file with `{proj}\HybridCLRData\LocalIl2CppData-WindowsEditor\il2cpp\build\deploy\netcoreapp3.1\Unity.IL2CPP.dll` (Unity 2020) or `{proj}\HybridCLRData\LocalIl2CppData-WindowsEditor\il2cpp\build\deploy\Unity.IL2CPP.dll` (Unity 2021+). If there is no file corresponding to your version, contact us to make one.
- - If the version is 2019, no operation is required because it has been automatically copied during the Install process
+- Put the hybridclr directory after unzipping `hybridclr.zip` into the libil2cpp directory after unzipping `il2cpp-{version}.zip`
+- Open `HybridCLR/Installer`, enable the `Copy libil2cpp from local` option, select the libil2cpp directory just unzipped, and install it
+- According to your Unity version:
+- If the version is >= 2020, replace the `ModifiedDlls\{verions}\Unity.IL2CPP.dll` file `{proj}\HybridCLRData\LocalIl2CppData-WindowsEditor\il2cpp\build\deploy\netcoreapp3.1\Unity.IL2CPP.dll`(Unity 2020) or `{proj}\HybridCLRData\LocalIl2CppData-WindowsEditor\il2cpp\build\deploy\Unity.IL2CPP.dll`(Unity 202 1+). If there is no file corresponding to your version, please contact us to make one
+- If the version is 2019, no operation is required, because it has been automatically copied during the installation process
![installer](/img/hybridclr/ultimate-installer.jpg)
-
## Configuration
### Configure PlayerSettings
-- `Scripting Backend` switched to `IL2CPP`
-- `Api Compatability Level` switched to `.Net 4.x` (Unity 2019-2020) or `.Net Framework` (Unity 2021+)
+- Switch `Scripting Backend` to `IL2CPP`
+- Switch `Api Compatibility Level` to `.Net 4.x`(Unity 2019-2020) or `.Net Framework` (Unity 2021+)
![player settings](/img/hybridclr/ultimate-project-settings.jpg)
-
### Enable incremental GC
-Just enable the `use incremental GC` option in `Player Settings`, and there is no need to make any settings for HybridCLR.
+Enable the `use incremental GC` option in `Player Settings`, no settings are required for HybridCLR.
### Enable full generic sharing
-- The 2020 version does not support full generic sharing
-- The 2021 version requires setting the IL2CPP Code Generation option to `faster(smaller)`
-- The 2022 version enables full generic sharing by default and cannot be turned off. If you set the IL2CPP Code Generation option to `faster(smaller)`, you can further reduce the package body.
-
+- 2020 version does not support full generic sharing
+- 2021 version needs to set IL2CPP Code Generation option to `faster(smaller)`
+- 2022 version enables full generic sharing by default and cannot be turned off. If you set IL2CPP Code Generation option to `faster(smaller)`, you can further reduce the package size.
-## Turn on and off standard command optimization
+## Enable and disable standard instruction optimization
-Standard optimization is enabled by default. This feature can be actively controlled to be turned on or off through the `RuntimeApi.EnableTransformOptimization` function.
+Standard optimization is enabled by default. You can actively control to enable or disable this feature through the `RuntimeApi.EnableTransformOptimization` function.
-Standard instruction optimization and advanced instruction optimization are two completely independent and mutually exclusive features. For each interpreted function, you can only choose to use one of the two or not use them at all.
+Standard instruction optimization and advanced instruction optimization are two completely independent and mutually exclusive features. For each interpreted function, you can only choose to use one of them or not use them at all.
### Configure HybridCLR
-As with the community version, click the `HybridCLR/Settings` menu to open the configuration dialog.
+As with the community version, click the `HybridCLR/Settings` menu to open the configuration dialog box.
-| Field | Description |
+| Field | Description|
|-|-|-|
-|differentialHybridAssemblies|DHE assembly list. Add the assembly name that requires differential hybrid execution to this list, such as HotUpdate. The same assembly cannot be added to the differentialHybridAssemblies and hotUpdateAssemlies lists at the same time. |
-
+|differentialHybridAssemblies|DHE assembly list. Add the assembly names that need differential hybrid execution to this list, such as HotUpdate. The same assembly cannot be added to both the differentialHybridAssemblies and hotUpdateAssemblies lists. |
### Reserve all DHE assemblies in link.xml
-For user-owned code such as Assembly-CSharp, il2cpp generally does not cut it. However, for third-party assemblies that are directly added to Unity in the form of dlls, if all are not reserved, these dlls will be cut during packaging.
-Then there are huge changes when generating dhao files, which is obviously not what we expect.
-
-Add similar configuration `` in `Assets/link.xml` (or other custom link.xml) for all your dhe assemblies.
-
-## dhao file
-
-The dhao file is the core concept of DHE technology. The dhao file contains information about the changed types and functions in the latest hot update dll calculated offline. The runtime determines whether to use the latest interpreted version or directly call the original function when executing a hot update function based on the information in the dhao file. AOT function.
-Offline calculated dhao files are extremely critical for DHE technology. If there is no dhao file, the original AOT dll needs to be carried additionally, and the cost of calculating function changes is extremely high.
-
-By comparing the latest hot update dll with the AOT dll generated during packaging, the changed types and functions are calculated offline and saved as a dhao file. Therefore, for the DHE mechanism to work properly, it must rely on the correctness of the dhao file, and the correctness of the dhao file
-It relies on accurately providing the latest hot update dll and the AOT dll generated during packaging.
-
-
-`HybridCLR.Editor.DHE.BuildUtils` provides multiple functions related to generating dhao files.
-
-|function name|description|
-|-|-|
-|GenerateUnchangedDHAODatas|Generate the dhao file of the first package (that is, when no changes have occurred)|
-|GenerateDHAODatas|Generate dhao files for hot update packages (that is, when code changes)|
-|EncryptDllAndGenerateUnchangedDHAODatas|When the primary code reinforcement is turned on, the encrypted dll and dhao files are generated in the first package (that is, when no changes have occurred)|
-|EncryptDllAndGenerateDHAODatas|When the primary code reinforcement is turned on, the encrypted dll and dhao files are generated in the hot update package (that is, when the code changes)|
-
-
-## Mark changed function information
-
-At present, it is possible to automatically calculate the changed function by comparing the latest hot update dll with the aot dll generated during packaging. In most cases, manual operation is not required. But in fact, there is no perfect code that can judge logical equivalence.
-The tool simply compares IL one by one to determine equivalence. Sometimes it may happen that the functions are equivalent but the IL changes (such as changing the order of two lines of unrelated code), it will be judged as a function change and the execution will be switched to interpretation.
-If this happens, and there are extremely stringent performance requirements for the function, the developer can manually use the UnchangedAttribute attribute to mark the change of the function.
-`[Unchanged]` and `[Unchanged(true)]` represent unchanged, `[Unchanged(false)]` represents change, and unmarked features are automatically calculated by the tool.
-
-Incorrectly marking an unchanged function as changed will not affect the correctness of the run, only performance. Even if all hot update functions are marked as changes, they can still run normally. However, incorrectly marking the changed function as unchanged will not only cause errors in the running logic, but
-In severe cases, it can even cause a crash!
-
-:::caution
-Unless there are special circumstances and you are an experienced expert, do not mark manually. Because the compiler often generates some hidden classes or fields, these class names are not stable. C# code that looks the same on the surface may not actually generate the same code. Forcibly marking it as `[Unchanged]` will lead to incorrect running logic or even crash.
-:::
-
-## Used in code
-
-At runtime, after hot update is completed, for each dhe assembly, call `RuntimeApi::LoadDifferentialHybridAssembly` or `RuntimeApi::LoadDifferentialHybridAssemblyUnchecked` to load the hot update assembly.
-
-Precautions:
-
-- Differential hybrid execution assembly should be loaded according to assembly dependency order.
-- If an assembly has not changed, the dhao field can be passed as null, but in this case the AOT dll generated during packaging must be used, and the hot update dll generated through the `HybridCLR/CompileDll/xxx` command cannot be used.
-- The DHE assembly itself already contains metadata. Even if full generic sharing is not enabled, **Do not add metadata** to the DHE assembly. If you add it, it will fail. Other non-DHE AOT assemblies can be added as usual. metadata.
-
-
-`RuntimeApi::LoadDifferentialHybridAssembly` is a checked workflow. It needs to pass in the md5 of the original dhe dll and the md5 of the current dhe dll, and compare them with the md5 saved in the dhao file.
-For the originalDllMd5 and currentDllMd5 parameters, the complexity of the workflow is greatly increased.
-
-:::tip
-
-It is recommended that beginners use the checked workflow in demo projects. After becoming familiar with the workflow, they can use the unchecked workflow in formal projects.
-:::
-
-### use unchecked `RuntimeApi::LoadDifferentialHybridAssembly`
-
-```csharp title="Loading DHE assembly"
-
-public static string CreateMD5Hash(byte[] bytes)
-{
- return BitConverter.ToString(new MD5CryptoServiceProvider().ComputeHash(bytes)).Replace("-", "").ToUpperInvariant();
-}
-
-///
-/// originalDllMd5 is obtained from the `{manifest}` manifest file generated during the build. This manifest file is generated by the developer himself
-///
-void LoadDifferentialHybridAssembly(string assemblyName, string originalDllMd5)
-{
- // currentDllMd5 can be generated at runtime or offline and in advance when a hot update package is released.
- string currentDllMd5 = CreateMD5Hash(dllBytes);
- LoadImageErrorCode err = RuntimeApi.LoadDifferentialHybridAssembly(dllBytes, dhaoBytes, originalDllMd5, currentDllMd5);
- if (err == LoadImageErrorCode.OK)
- {
- Debug.Log($"LoadDifferentialHybridAssembly {assName} OK");
- }
- else
- {
- Debug.LogError($"LoadDifferentialHybridAssembly {assName} failed, err={err}");
- }
-}
-```
-
-### use checked `RuntimeApi::LoadDifferentialHybridAssemblyUnchecked`
-
-:::warning
-
-When using a unchecked workflow, be sure to ensure the consistency of the original dhe dll, current dhe dll, and dhao files. If they are inconsistent, an operation error may occur, or the process may crash.
-
-:::
-
-```csharp title="Loading DHE assembly"
-
-///
-/// originalDllMd5 is obtained from the `{manifest}` manifest file generated during the build. This manifest file is generated by the developer himself
-///
-void LoadDifferentialHybridAssembly(string assemblyName)
-{
- LoadImageErrorCode err = RuntimeApi.LoadDifferentialHybridAssemblyUnchecked(dllBytes, dhaoBytes);
- if (err == LoadImageErrorCode.OK)
- {
- Debug.Log($"LoadDifferentialHybridAssembly {assName} OK");
- }
- else
- {
- Debug.LogError($"LoadDifferentialHybridAssembly {assName} failed, err={err}");
- }
-}
-```
+For user-owned code such as Assembly-CSharp, il2cpp generally does not trim. However, for third-party assemblies that are directly added to Unity in the form of dll, if all are not reserved, these dlls will be trimmed during packaging, and there will be huge changes when generating dhao files, which is obviously not what we expect.
+Add similar configurations `` to all your dhe assemblies in `Assets/link.xml` (or other custom link.xml).
## Configure function injection strategy
:::tip
-In the vast majority of projects, the default full injection strategy has minimal impact on performance. As long as there are no performance issues, you do not need and should not care about this configuration.
-
-:::
-
- In order to avoid indirect dirty function contagion (that is, function A calls function B, if B changes, A will also be marked as changed), a small piece of check jump code is injected into the header of all functions by default. Although it is
- Very simple `if (method->isInterpterImpl)` statement, but for short functions like `int Age {get; set;}`, this insertion may produce an observable performance degradation (even up to 10%).
-
-The function injection strategy is used to optimize this situation. For short functions that do not change, configuring not to inject can improve performance. See the [InjectRules](./injectrules) document for details.
-
-Fill in the injection policy file path in the `InjectRuleFiles` field in `HybridCLR Settings`. The relative path of the file is the project root directory (such as `Assets/InjectRules/DefaultInjectRules.xml`).
-
-
-## Pack
-
-The files related to construction in DHE technology are dhe dll files and corresponding dhao files.
-
-### Non-encrypted workflow
-
-#### Build the main package
-
-- Use the trimmed AOT dll generated after building as the dhe dll of the first package (without any changes)
-- Use `HybridCLR.Editor.DHE.BuildUtils.GenerateUnchangedDHAODatas` to generate the dhao file of the first package
-
-If using a checked workflow, do the following:
-
-- Generate a `{manifest}` manifest file for dhe dll that contains at least assemblyName, md5 (it is up to the developer to decide how to implement it), because `RuntimeApi.LoadDifferentialHybridAssembly` needs to provide the original md5 of dhe dll
-- Add dhe dll, dhao files and `{manifest}` files to the hot update resource management system
-
-If you use a workflow without validation, do the following:
-
-- Add dhe dll and dhao files to the hot update resource management system
-
-If you want to carry the dhe dll and dhao files of the first package with the package, please export the project first, then follow the above steps to generate the dhe dll and dhao files, and then add them to the exported project.
-
-
-#### Hot update
-
-- Use `HybridCLR/CompileDll/ActivedBuildTarget` to generate hot update dll.
-- Use `HybridCLR.Editor.DHE.BuildUtils.GenerateDHAODatas` to generate the latest hot update dll dhao file
-- Add the latest hot update dll and dhao files to the hot update resource management system
-
-:::caution
-
-If you package using the **development build option**, be sure to use `HybridCLR/CompileDll/ActivedBuildTarget_Development` to compile the hot update dll in Development mode. Otherwise, the comparison result is that almost all functions are judged to have changed.
+In most projects, the default full injection strategy has little impact on performance. As long as there is no performance problem, you don't need to care about this configuration.
:::
-### Encryption workflow
-
-#### Build the main package
-
-- Use the cropped AOT dll generated after the build as the original dhe dll
-- Use `HybridCLR.Editor.DHE.BuildUtils.EncryptDllAndGenerateUnchangedDHAODatas` to generate the dhao file of the first package and the encrypted dhe dll file
-
-If using a checked workflow, do the following:
-
-- Generate a `{manifest}` manifest file for dhe dll that contains at least assemblyName, md5 (it is up to the developer to decide how to implement it), because `RuntimeApi.LoadDifferentialHybridAssembly` needs to provide the original md5 of dhe dll
-- Add the encrypted dhe dll, dhao files and `{manifest}` files to the hot update resource management system
-
-If you use a workflow without validation, do the following:
-
-- Add the encrypted dhe dll and dhao files to the hot update resource management system
-
-
-#### Hot update
-
-- Use `HybridCLR/CompileDll/ActivedBuildTarget` to generate hot update dll.
-- Use `HybridCLR.Editor.DHE.BuildUtils.EncryptDllAndGenerateDHAODatas` to generate the latest dhe dll encrypted file and the corresponding dhao file
-- Add the encrypted dhe dll and dhao files to the hot update resource management system
-
-## Feature not supported
-
-- Does not support turning on the `script debugging` build option
+In order to avoid indirect dirty function contagion (i.e. function A calls function B, if B changes, A will also be marked as changed), a small check jump code is injected into all function headers by default. Although it is a very simple `if (method->isInterpterImpl)` statement, for short functions such as `int Age {get; set;}`, this insertion may cause observable performance degradation (even up to 10%).
-## Precautions
+Function injection strategy is used to optimize this situation. For short functions that do not change, configuring it to not inject can improve performance. For details, please see the [InjectRules](./injectrules) document.
-### There are huge differences in the results of calculating dhao caused by external dll
+In `HybridCLR Settings`, fill in the injection policy file path in the `InjectRuleFiles` field. The relative path of the file is the project root directory (such as `Assets/InjectRules/DefaultInjectRules.xml`).
-If there is an external dll marked as a DHE assembly, the external dll will be trimmed when packaged, and when calculating the dhao file, the original external dll will be taken, resulting in a huge difference, which is not expected. There are several solutions:
+## Unsupported features
-1. In link.xml `` completely retains the external dll
-2. Instead of using the latest hot update dll to calculate the difference, use the aot dll generated when the latest code is repackaged to calculate the difference.
+- Unsupported `script debugging` build option
diff --git a/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/quickstartchecked.md b/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/quickstartchecked.md
deleted file mode 100644
index 9c5d5354..00000000
--- a/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/quickstartchecked.md
+++ /dev/null
@@ -1,480 +0,0 @@
-# Get Started Quickly (checked workflow)
-
-This tutorial guides you to experience HybridCLR hot update from an empty project. For the sake of simplicity, only the case where the BuildTarget is the **Windows** or **MacOS** Standalone platform is demonstrated.
-Please run the hot update process correctly on the Standalone platform before trying the hot update on the Android and iOS platforms. Their processes are very similar.
-
-The difficulty of using the flagship version is similar to that of the community version, and most of the principles are the same. It is recommended to familiarize yourself with the community version before trying the flagship version.
-
-Since version v5.0.0, both the `RuntimeApi.LoadDifferentialHybridAssembly` workflow with verification and the `RuntimeApi.LoadDifferentialHybridAssemblyUnchecked` workflow without verification are supported.
-This document introduces the workflow with validation.
-
-:::tip
-
-In practice, the workflow without verification will be much simpler. There is no need to pass the originalDllMd5 and currentDllMd5 parameters, so the process of saving or calculating dll md5 in the workflow is omitted.
-However, developers are required to ensure the consistency of aot dll, hot update dll, and dhao files.
-It is recommended that beginners use the workflow with verification in demo projects. After becoming familiar with the workflow, they can use the workflow without verification in formal projects.
-
-:::
-
-## Experience goals
-
-- Create hot update assembly
-- Load the hot update assembly, execute the hot update code in it, and print `Hello, HybridCLR`
-- Modify the hot update code to print `Hello, World`
-
-## Prepare environment
-
-### Install Unity
-
-- Install any version 2019.4.x, 2020.3.x, 2021.3.x, 2022.3.x. Some versions have special installation requirements, see [Install hybridclr](../../basic/install.md)
-- Depending on the operating system you are using, when selecting modules during the installation process, you must select `Windows Build Support(IL2CPP)` or `Mac Build Support(IL2CPP)`
-
-![select il2cpp modules](/img/hybridclr/select_il2cpp_modules.jpg)
-
-### Install IDE and related compilation environment
-
-- Windows
- - `visual studio 2019` or higher version needs to be installed under Win. The installation must include at least the `Game development using Unity` and `Game development using C++` components.
- - install git
--Mac
- - Requires MacOS version >= 12, xcode version >= 13, for example `xcode 13.4.1, macos 12.4`
- - install git
-
-## Initialize Unity hot update project
-
-The process of constructing a hot update project from scratch is lengthy. The code involved in the following steps can refer to the dhe_demo project, whose warehouse address is [github](https://github.com/focus-creative-games/dhe_demo).
-
-### Create project
-
-Create an empty Unity project.
-
-### Create `ConsoleToScreen.cs` script
-
-This script has no direct effect on demonstrating hot updates. It can print logs to the screen to facilitate locating errors.
-
-Create the `Assets/ConsoleToScreen.cs` script class with the following code:
-
-```csharp
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using UnityEngine;
-
-public class ConsoleToScreen : MonoBehaviour
-{
- const int maxLines = 50;
- const int maxLineLength = 120;
- private string _logStr = "";
-
- private readonly List _lines = new List();
-
- public int fontSize = 15;
-
- void OnEnable() { Application.logMessageReceived += Log; }
- void OnDisable() { Application.logMessageReceived -= Log; }
-
- public void Log(string logString, string stackTrace, LogType type)
- {
- foreach (var line in logString.Split('\n'))
- {
- if (line.Length <= maxLineLength)
- {
- _lines.Add(line);
- continue;
- }
- var lineCount = line.Length / maxLineLength + 1;
- for (int i = 0; i < lineCount; i++)
- {
- if ((i + 1) * maxLineLength <= line.Length)
- {
- _lines.Add(line.Substring(i * maxLineLength, maxLineLength));
- }
- else
- {
- _lines.Add(line.Substring(i * maxLineLength, line.Length - i * maxLineLength));
- }
- }
- }
- if (_lines.Count > maxLines)
- {
- _lines.RemoveRange(0, _lines.Count - maxLines);
- }
- _logStr = string.Join("\n", _lines);
- }
-
- voidOnGUI()
- {
- GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity,
- new Vector3(Screen.width / 1200.0f, Screen.height / 800.0f, 1.0f));
- GUI.Label(new Rect(10, 10, 800, 370), _logStr, new GUIStyle() { fontSize = Math.Max(10, fontSize) });
- }
-}
-
-
-```
-
-### Create the main scene
-
-- Create default initial scene main.scene
-- Create an empty GameObject in the scene and hang ConsoleToScreen on it
-- Add the main scene to the packaged scene list in `Build Settings`
-
-### Create HotUpdate hot update module
-
-- Create `Assets/HotUpdate` directory
-- Right-click `Create/Assembly Definition` in the directory and create an assembly module named `HotUpdate`
-
-## Install and configure HybridCLR
-
-### Install
-
-- Unzip hybridclr_unity.zip, place it in the project Packages directory, and rename it com.code-philosophy.hybridclr
-- Unzip the corresponding `il2cpp_plus-{version}.zip` according to your unity version
-- Unzip `hybridclr.zip`
-- Place the hybridclr directory after decompression of `hybridclr.zip` into the libil2cpp directory after decompression of `il2cpp-{version}.zip`
-- Open `HybridCLR/Installer`, enable the `Copy libil2cpp from local` option, select the libil2cpp directory you just decompressed, and install it.
-- Depending on your Unity version:
- - If version >= 2020, replace the `ModifiedDlls\{verions}\Unity.IL2CPP.dll` file with `{proj}\HybridCLRData\LocalIl2CppData-WindowsEditor\il2cpp\build\deploy\netcoreapp3.1\Unity.IL2CPP.dll` (Unity 2020) or `{proj}\HybridCLRData\LocalIl2CppData-WindowsEditor\il2cpp\build\deploy\Unity.IL2CPP.dll` (Unity 2021+). If there is no file corresponding to your version, contact us to make one.
- - If the version is 2019, no operation is required because it has been automatically copied during the Install process
-
-![installer](/img/hybridclr/ultimate-installer.jpg)
-
-### Configure HybridCLR
-
-- Open menu `HybridCLR/Settings`
-- Add `HotUpdate` assembly to `differentialHybridAssemblies` list
-
-![settings](/img/hybridclr/ultimate-hybridclr-settings.jpg)
-
-### Configure PlayerSettings
-
-- `Scripting Backend` switched to `IL2CPP`
-- `Api Compatability Level` switched to `.Net 4.x` (Unity 2019-2020) or `.Net Framework` (Unity 2021+)
-
-![player settings](/img/hybridclr/ultimate-project-settings.jpg)
-
-## Create Editor script
-
-Create the BuildTools.cs file in the `Assets/Editor` directory with the following content:
-
-```csharp
-
-using HybridCLR.Editor;
-using HybridCLR.Editor.DHE;
-using HybridCLR.Runtime;
-using System.Collections;
-using System.Collections.Generic;
-using System.IO;
-using UnityEditor;
-using UnityEngine;
-
-public static class BuildTools
-{
- public const string BackupAOTDllDir = "HybridCLRData/BackupAOT";
-
- public const string EncryptedDllDir = "HybridCLRData/EncryptedDll";
-
- public const string DhaoDir = "HybridCLRData/Dhao";
-
- public const string ManifestFile = "manifest.txt";
-
-
- ///
- /// Back up the cropped AOT dll generated when building the main package
- ///
- [MenuItem("BuildTools/BackupAOTDll")]
- public static void BackupAOTDllFromAssemblyPostStrippedDir()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- var backupDir = $"{BackupAOTDllDir}/{target}";
- System.IO.Directory.CreateDirectory(backupDir);
- var dlls = System.IO.Directory.GetFiles(SettingsUtil.GetAssembliesPostIl2CppStripDir(target));
- foreach (var dll in dlls)
- {
- var fileName = System.IO.Path.GetFileName(dll);
- string dstFile = $"{BackupAOTDllDir}/{target}/{fileName}";
- System.IO.File.Copy(dll, dstFile, true);
- Debug.Log($"BackupAOTDllFromAssemblyPostStrippedDir: {dll} -> {dstFile}");
- }
- }
-
- ///
- /// Create a dhe manifest file, the format is one 'dll name, md5 of the original dll' per line
- ///
- ///
- [MenuItem("BuildTools/CreateManifestAtBackupDir")]
- public static void CreateManifest()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string backupDir = $"{BackupAOTDllDir}/{target}";
- CreateManifest(backupDir);
- }
-
- public static void CreateManifest(string outputDir)
- {
- Directory.CreateDirectory(outputDir);
- var lines = new List();
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string backupDir = $"{BackupAOTDllDir}/{target}";
- foreach (string dheDll in SettingsUtil.DifferentialHybridAssemblyNames)
- {
- string originalDll = $"{backupDir}/{dheDll}.dll";
- string originalDllMd5 = AssemblyOptionDataGenerator.CreateMD5Hash(File.ReadAllBytes(originalDll));
- lines.Add($"{dheDll},{originalDllMd5}");
- }
- string manifestFile = $"{outputDir}/{ManifestFile}";
- File.WriteAllBytes(manifestFile, System.Text.Encoding.UTF8.GetBytes(string.Join("\n", lines)));
- Debug.Log($"CreateManifest: {manifestFile}");
- }
-
- ///
- /// Generate the dhao data corresponding to the first package without any code changes
- ///
- [MenuItem("BuildTools/GenerateUnchangedDHAODatas")]
- public static void GenerateUnchangedDHAODatas()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string backupDir = $"{BackupAOTDllDir}/{target}";
- string dhaoDir = $"{DhaoDir}/{target}";
- BuildUtils.GenerateUnchangedDHAODatas(SettingsUtil.DifferentialHybridAssemblyNames, backupDir, dhaoDir);
- }
-
- ///
- /// Generate dhao data of hot update package
- ///
- [MenuItem("BuildTools/GenerateDHAODatas")]
- public static void GenerateDHAODatas()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string backupDir = $"{BackupAOTDllDir}/{target}";
- string dhaoDir = $"{DhaoDir}/{target}";
- string currentDllDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
- BuildUtils.GenerateDHAODatas(SettingsUtil.DifferentialHybridAssemblyNames, backupDir, currentDllDir, null, null, dhaoDir);
- }
-
- ///
- /// Generate the encrypted dll of the first package and the corresponding dhao data without any code changes
- ///
- [MenuItem("BuildTools/GenerateUnchangedEncryptedDllAndDhaoDatas")]
- public static void GenerateUnchangedEncryptedDllAndDhaoDatas()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string backupDir = $"{BackupAOTDllDir}/{target}";
- string dhaoDir = $"{DhaoDir}/{target}";
- string encryptedDllDir = $"{EncryptedDllDir}/{target}";
- BuildUtils.EncryptDllAndGenerateUnchangedDHAODatas(SettingsUtil.DifferentialHybridAssemblyNames, backupDir, encryptedDllDir, dhaoDir);
- }
-
-
- ///
- /// Generate the encrypted dll and dhao data of the hot update package
- ///
- [MenuItem("BuildTools/GenerateEncryptedDllAndDhaoDatas")]
- public static void GenerateEncryptedDllAndDhaoDatas()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string backupDir = $"{BackupAOTDllDir}/{target}";
- string dhaoDir = $"{DhaoDir}/{target}";
- string currentDllDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
- string encryptedDllDir = $"{EncryptedDllDir}/{target}";
- BuildUtils.EncryptDllAndGenerateDHAODatas(SettingsUtil.DifferentialHybridAssemblyNames, backupDir, currentDllDir, null, null, encryptedDllDir, dhaoDir);
- }
-
- ///
- /// Copy the unmodified first package dll and dhao files to StreamingAssets
- ///
- [MenuItem("BuildTools/CopyUnchangedDllAndDhaoFileAndManifestToStreamingAssets")]
- public static void CopyUnchangedDllAndDhaoFileToStreamingAssets()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string streamingAssetsDir = Application.streamingAssetsPath;
- Directory.CreateDirectory(streamingAssetsDir);
-
- string manifestFile = $"{BackupAOTDllDir}/{target}/{ManifestFile}";
- string dstManifestFile = $"{streamingAssetsDir}/{ManifestFile}";
- System.IO.File.Copy(manifestFile, dstManifestFile, true);
- Debug.Log($"CopyUnchangedDllAndDhaoFileToStreamingAssets: {manifestFile} -> {dstManifestFile}");
-
- string dllDir = $"{BackupAOTDllDir}/{target}";
- string dhaoDir = $"{DhaoDir}/{target}";
- foreach (var dll in SettingsUtil.DifferentialHybridAssemblyNames)
- {
- string srcFile = $"{dllDir}/{dll}.dll";
- string dstFile = $"{streamingAssetsDir}/{dll}.dll.bytes";
- System.IO.File.Copy(srcFile, dstFile, true);
- Debug.Log($"CopyUnchangedDllAndDhaoFileToStreamingAssets: {srcFile} -> {dstFile}");
- string dhaoFile = $"{dhaoDir}/{dll}.dhao.bytes";
- dstFile = $"{streamingAssetsDir}/{dll}.dhao.bytes";
- System.IO.File.Copy(dhaoFile, dstFile, true);
- Debug.Log($"CopyUnchangedDllAndDhaoFileToStreamingAssets: {dhaoFile} -> {dstFile}");
- }
- }
-
- ///
- /// Copy hot update dll and dhao files to StreamingAssets
- ///
- [MenuItem("BuildTools/CopyDllAndDhaoFileToStreamingAssets")]
- public static void CopyDllAndDhaoFileToStreamingAssets()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string streamingAssetsDir = Application.streamingAssetsPath;
- Directory.CreateDirectory(streamingAssetsDir);
-
- string dllDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
- string dhaoDir = $"{DhaoDir}/{target}";
- foreach (var dll in SettingsUtil.DifferentialHybridAssemblyNames)
- {
- string srcFile = $"{dllDir}/{dll}.dll";
- string dstFile = $"{streamingAssetsDir}/{dll}.dll.bytes";
- System.IO.File.Copy(srcFile, dstFile, true);
- Debug.Log($"CopyUnchangedDllAndDhaoFileToStreamingAssets: {srcFile} -> {dstFile}");
- string dhaoFile = $"{dhaoDir}/{dll}.dhao.bytes";
- dstFile = $"{streamingAssetsDir}/{dll}.dhao.bytes";
- System.IO.File.Copy(dhaoFile, dstFile, true);
- Debug.Log($"CopyUnchangedDllAndDhaoFileToStreamingAssets: {dhaoFile} -> {dstFile}");
- }
- }
-}
-
-
-```
-
-## Create hot update script
-
-Create the `Assets/HotUpdate/Hello.cs` file with the following code content
-
-```csharp
-using System.Collections;
-using UnityEngine;
-
-public class Hello
-{
- public static void Run()
- {
- Debug.Log("Hello, HybridCLR");
- }
-}
-```
-
-## Load hot update assembly
-
-To simplify the demonstration, we do not download HotUpdate.dll through the http server, but directly place HotUpdate.dll in the StreamingAssets directory.
-
-Create the `Assets/LoadDll.cs` script, then **create a GameObject object in the main scene and mount the LoadDll script**.
-
-
-```csharp
-using HybridCLR;
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Security.Cryptography;
-using System.Text;
-using System.Threading.Tasks;
-using UnityEngine;
-using UnityEngine.Networking;
-
-public class LoadDll : MonoBehaviour
-{
-
- void Start()
- {
- // In the Editor environment, HotUpdate.dll.bytes has been automatically loaded and does not need to be loaded. Repeated loading will cause problems.
-#if !UNITY_EDITOR
- var manifests = LoadManifest($"{Application.streamingAssetsPath}/manifest.txt");
- Assembly hotUpdateAss = LoadDifferentialHybridAssembly(manifests["HotUpdate"], "HotUpdate");
-#else
- // No need to load under Editor, directly find the HotUpdate assembly
- Assembly hotUpdateAss = System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "HotUpdate");
-#endif
- Type helloType = hotUpdateAss.GetType("Hello");
- MethodInfo runMethod = helloType.GetMethod("Run");
- runMethod.Invoke(null, null);
- }
-
- class Manifest
- {
- public string AssemblyName { get; set; }
-
- public string OriginalDllMd5 { get; set; }
- }
-
- private Dictionary LoadManifest(string manifestFile)
- {
- var manifest = new Dictionary();
- var lines = File.ReadAllLines(manifestFile, Encoding.UTF8);
- foreach (var line in lines)
- {
- string[] args = line.Split(",");
- if (args.Length != 2)
- {
- Debug.LogError($"manifest file format error, line={line}");
- return null;
- }
- manifest.Add(args[0], new Manifest()
- {
- AssemblyName = args[0],
- OriginalDllMd5 = args[1],
- });
- }
- return manifest;
- }
-
-
- public static string CreateMD5Hash(byte[] bytes)
- {
- return BitConverter.ToString(new MD5CryptoServiceProvider().ComputeHash(bytes)).Replace("-", "").ToUpperInvariant();
- }
-
- private Assembly LoadDifferentialHybridAssembly(Manifest manifest, string assName)
- {
- byte[] dllBytes = File.ReadAllBytes($"{Application.streamingAssetsPath}/{assName}.dll.bytes");
- byte[] dhaoBytes = File.ReadAllBytes($"{Application.streamingAssetsPath}/{assName}.dhao.bytes");
- string currentDllMd5 = CreateMD5Hash(dllBytes);
- LoadImageErrorCode err = RuntimeApi.LoadDifferentialHybridAssembly(dllBytes, dhaoBytes, manifest.OriginalDllMd5, currentDllMd5);
- if (err == LoadImageErrorCode.OK)
- {
- Debug.Log($"LoadDifferentialHybridAssembly {assName} OK");
- return System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == assName);
- }else
- {
- Debug.LogError($"LoadDifferentialHybridAssembly {assName} failed, err={err}");
- return null;
- }
- }
-}
-
-```
-
-
-At this point, the creation of the entire hot update project is completed! ! !
-
-## Trial run in Editor
-
-Run the main scene and 'Hello,HybridCLR' will be displayed on the screen, indicating that the code is working properly.
-
-## Package and run
-
-- Run menu `HybridCLR/Generate/All` to perform necessary generation operations. **This step cannot be missed**!!!
-- Open the `Build Settings` dialog box, click `Build`, select the output directory `{build}`, and execute the build
-- Run `BuildTools/BackupAOTDll` to back up the trimmed dhe dll. In practice, these dlls should be added to version management for later generation of dhao files. These files will not be modified again.
-- Run `BuildTools/CreateManifestAtBackupDir` to generate the manifest file of the original dhe dll. In practice, this manifest file should be added to version management and will not be modified again.
-- Run `BuildTools/GenerateUnchangedDHAODatas` to generate the dhao file of the first package
-- Run `BuildTools/CopyUnchangedDllAndDhaoFileAndManifestToStreamingAssets` to copy the first package dhe assembly, dhao file, and manifest file to StreamingAssets
-- Copy the `Assets/StreamingAssets` directory to `{build}\dhe_demo2_Data\StreamingAssets`
-- Run `{build}/Xxx.exe`, and the screen will display `Hello,HybridCLR`, indicating that the hot update code has been successfully executed!
-
-## Test hot update
-
-- Modify the `Debug.Log("Hello, HybridCLR");` code in the Run function of `Assets/HotUpdate/Hello.cs` to `Debug.Log("Hello, World");`.
-- Run `HybridCLR/CompileDll/ActiveBulidTarget` to generate hot update dll
-- Run `BuildTools/GenerateDHAODatas` to generate dhao files
-- Run `BuildTools/CopyDllAndDhaoFileToStreamingAssets` to copy the hot update dll and dhao files to the StreamingAssets directory
-- Copy the `Assets/StreamingAssets` directory to `{build}\dhe_demo2_Data\StreamingAssets`
-- Rerun the program and you will find `Hello, World` displayed on the screen, indicating that the hot update code has taken effect!
-
-
-This completes the hot update experience.
diff --git a/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/quickstartunchecked.md b/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/quickstartunchecked.md
index 6bfc3439..a79018ff 100644
--- a/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/quickstartunchecked.md
+++ b/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/quickstartunchecked.md
@@ -1,58 +1,47 @@
-# Get Started Quickly (unchecked workflow)
+# Get started quickly
-This tutorial guides you to experience HybridCLR hot update from an empty project. For the sake of simplicity, only the case where the BuildTarget is the **Windows** or **MacOS** Standalone platform is demonstrated.
-Please run the hot update process correctly on the Standalone platform before trying the hot update on the Android and iOS platforms. Their processes are very similar.
+This tutorial guides you to experience the hot update of HybridCLR from an empty project. For the sake of simplicity, only the case where BuildTarget is **Windows** or **MacOS** Standalone platform is demonstrated.
+Please run the hot update process correctly on the Standalone platform before trying the hot update of Android and iOS platforms by yourself. Their processes are very similar.
-The difficulty of using the flagship version is similar to that of the community version, and most of the principles are the same. It is recommended to familiarize yourself with the community version before trying the flagship version.
+The difficulty of using the Ultimate version is similar to that of the Community version. Most of the principles are the same. It is recommended to familiarize yourself with the Community version before trying the Ultimate version.
-Since version v5.0.0, both the `RuntimeApi.LoadDifferentialHybridAssembly` workflow with verification and the `RuntimeApi.LoadDifferentialHybridAssemblyUnchecked` workflow without verification are supported.
-This document describes the workflow without validation.
+## Experience target
-:::tip
-
-In practice, the workflow without verification will be much simpler. There is no need to pass the originalDllMd5 and currentDllMd5 parameters, so the process of saving or calculating dll md5 in the workflow is omitted.
-However, developers are required to ensure the consistency of aot dll, hot update dll, and dhao files.
-It is recommended that beginners use the workflow with verification in demo projects. After becoming familiar with the workflow, they can use the workflow without verification in formal projects.
-
-:::
-
-## Experience goals
+- Create a hot update assembly
+- Load the hot update assembly and execute the hot update code in it, print `Hello, HybridCLR`
+- Modify the hot update code and print `Hello, World`
-- Create hot update assembly
-- Load the hot update assembly, execute the hot update code in it, and print `Hello, HybridCLR`
-- Modify the hot update code to print `Hello, World`
-
-## Prepare environment
+## Prepare the environment
### Install Unity
-- Install any version 2019.4.x, 2020.3.x, 2021.3.x, 2022.3.x. Some versions have special installation requirements, see [Install hybridclr](../../basic/install.md)
-- Depending on the operating system you are using, when selecting modules during the installation process, you must select `Windows Build Support(IL2CPP)` or `Mac Build Support(IL2CPP)`
+- Install any version of 2019.4.x, 2020.3.x, 2021.3.x, 2022.3.x. Some versions have special installation requirements, see [Install hybridclr](../../basic/install.md)
+- Depending on your operating system, you must select `Windows Build Support (IL2CPP)` or `Mac Build Support (IL2CPP)` when selecting modules during installation
![select il2cpp modules](/img/hybridclr/select_il2cpp_modules.jpg)
### Install IDE and related compilation environment
- Windows
- - `visual studio 2019` or higher version needs to be installed under Win. The installation must include at least the `Game development using Unity` and `Game development using C++` components.
- - install git
+- Under Win, you need to install `visual studio 2019` or higher. The installation should at least include the `Game Development with Unity` and `Game Development with C++` components
+- Install git
- Mac
- - Requires MacOS version >= 12, xcode version >= 13, for example `xcode 13.4.1, macos 12.4`
- - install git
+- Requires MacOS version >= 12, Xcode version >= 13, for example `Xcode 13.4.1, macos 12.4`
+- Install git
## Initialize Unity hot update project
-The process of constructing a hot update project from scratch is lengthy. The code involved in the following steps can refer to the dhe_demo project, whose warehouse address is [github](https://github.com/focus-creative-games/dhe_demo).
+The process of constructing a hot update project from scratch is relatively lengthy. The code involved in the following steps can refer to the dhe_demo project, whose repository address is [github](https://github.com/focus-creative-games/dhe_demo).
-### Create project
+### Create a project
Create an empty Unity project.
-### Create `ConsoleToScreen.cs` script
+### Create the `ConsoleToScreen.cs` script
-This script has no direct effect on demonstrating hot updates. It can print logs to the screen to facilitate locating errors.
+This script has no direct effect on demonstrating hot updates. It can print logs to the screen to facilitate error location.
-Create the `Assets/ConsoleToScreen.cs` script class with the following code:
+Create the `Assets/ConsoleToScreen.cs` script class, the code is as follows:
```csharp
using System;
@@ -62,100 +51,97 @@ using UnityEngine;
public class ConsoleToScreen : MonoBehaviour
{
- const int maxLines = 50;
- const int maxLineLength = 120;
- private string _logStr = "";
-
- private readonly List _lines = new List();
-
- public int fontSize = 15;
-
- void OnEnable() { Application.logMessageReceived += Log; }
- void OnDisable() { Application.logMessageReceived -= Log; }
-
- public void Log(string logString, string stackTrace, LogType type)
- {
- foreach (var line in logString.Split('\n'))
- {
- if (line.Length <= maxLineLength)
- {
- _lines.Add(line);
- continue;
- }
- var lineCount = line.Length / maxLineLength + 1;
- for (int i = 0; i < lineCount; i++)
- {
- if ((i + 1) * maxLineLength <= line.Length)
- {
- _lines.Add(line.Substring(i * maxLineLength, maxLineLength));
- }
- else
- {
- _lines.Add(line.Substring(i * maxLineLength, line.Length - i * maxLineLength));
- }
- }
- }
- if (_lines.Count > maxLines)
- {
- _lines.RemoveRange(0, _lines.Count - maxLines);
- }
- _logStr = string.Join("\n", _lines);
- }
-
- voidOnGUI()
- {
- GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity,
- new Vector3(Screen.width / 1200.0f, Screen.height / 800.0f, 1.0f));
- GUI.Label(new Rect(10, 10, 800, 370), _logStr, new GUIStyle() { fontSize = Math.Max(10, fontSize) });
- }
+ const int maxLines = 50;
+ const int maxLineLength = 120;
+ private string _logStr = "";
+
+ private readonly List _lines = new List();
+
+ public int fontSize = 15;
+
+ void OnEnable() { Application.logMessageReceived += Log; }
+ void OnDisable() { Application.logMessageReceived -= Log; }
+
+ public void Log(string logString, string stackTrace, LogType type)
+ {
+ foreach (var line in logString.Split('\n'))
+ {
+ if (line.Length <= maxLineLength)
+ {
+ _lines.Add(line);
+ continue;
+ }
+ var lineCount = line.Length / maxLineLength + 1;
+ for (int i = 0; i < lineCount; i++)
+ {
+ if ((i + 1) * maxLineLength <= line.Length)
+ {
+ _lines.Add(line.Substring(i * maxLineLength, maxLineLength));
+ }
+ else
+ {
+ _lines.Add(line.Substring(i * maxLineLength, line.Length - i * maxLineLength));
+ }
+ }
+ }
+ if (_lines.Count > maxLines)
+ {
+ _lines.RemoveRange(0, _lines.Count - maxLines);
+ }
+ _logStr = string.Join("\n", _lines);
+ }
+
+ void OnGUI()
+ {
+ GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity,
+ new Vector3(Screen.width / 1200.0f, Screen.height / 800.0f, 1.0f));
+ GUI.Label(new Rect(10, 10, 800, 370), _logStr, new GUIStyle() { fontSize = Math.Max(10, fontSize) });
+ }
}
-
-```
-
### Create the main scene
-- Create default initial scene main.scene
-- Create an empty GameObject in the scene and hang ConsoleToScreen on it
+- Create the default initial scene main.scene
+- Create an empty GameObject in the scene and attach ConsoleToScreen to it
- Add the main scene to the packaged scene list in `Build Settings`
-### Create HotUpdate hot update module
+### Create the HotUpdate hot update module
-- Create `Assets/HotUpdate` directory
+- Create the `Assets/HotUpdate` directory
- Right-click `Create/Assembly Definition` in the directory and create an assembly module named `HotUpdate`
## Install and configure HybridCLR
-### Install
+### Installation
-- Unzip hybridclr_unity.zip, place it in the project Packages directory, and rename it com.code-philosophy.hybridclr
+- Unzip hybridclr_unity.zip and put it in the project Packages directory, renaming it to com.code-philosophy.hybridclr
- Unzip the corresponding `il2cpp_plus-{version}.zip` according to your unity version
- Unzip `hybridclr.zip`
-- Place the hybridclr directory after decompression of `hybridclr.zip` into the libil2cpp directory after decompression of `il2cpp-{version}.zip`
-- Open `HybridCLR/Installer`, enable the `Copy libil2cpp from local` option, select the libil2cpp directory you just decompressed, and install it.
-- Depending on your Unity version:
- - If version >= 2020, replace the `ModifiedDlls\{verions}\Unity.IL2CPP.dll` file with `{proj}\HybridCLRData\LocalIl2CppData-WindowsEditor\il2cpp\build\deploy\netcoreapp3.1\Unity.IL2CPP.dll` (Unity 2020) or `{proj}\HybridCLRData\LocalIl2CppData-WindowsEditor\il2cpp\build\deploy\Unity.IL2CPP.dll` (Unity 2021+). If there is no file corresponding to your version, contact us to make one.
- - If the version is 2019, no operation is required because it has been automatically copied during the Install process
+- Put the hybridclr directory after decompressing `hybridclr.zip` into the libil2cpp directory after decompressing `il2cpp-{version}.zip`
+- Open `HybridCLR/Installer`, enable the option `Copy libil2cpp from local`, select the libil2cpp directory just decompressed, and install it
+- According to your Unity version:
+- If the version is >= 2020, replace the file `ModifiedDlls\{verions}\Unity.IL2CPP.dll` with `{proj}\HybridCLRData\LocalIl2CppData-WindowsEditor\il2cpp\build\deploy\netcoreapp3.1\Unity.IL2CPP.dll` (Unity 2020) or `{proj}\HybridCLRData\LocalIl2CppData-WindowsEditor\il2cpp\build\deploy\Unity.IL2CPP.dll` (Unity 2021+). If there is no file corresponding to your version, please contact us to make one
+- If the version is 2019, no operation is required, because it has been automatically copied during the installation process
![installer](/img/hybridclr/ultimate-installer.jpg)
### Configure HybridCLR
-- Open menu `HybridCLR/Settings`
-- Add `HotUpdate` assembly to `differentialHybridAssemblies` list
+- Open the menu `HybridCLR/Settings`
+- Add the `HotUpdate` assembly to the `differentialHybridAssemblies` list
![settings](/img/hybridclr/ultimate-hybridclr-settings.jpg)
### Configure PlayerSettings
-- `Scripting Backend` switched to `IL2CPP`
-- `Api Compatability Level` switched to `.Net 4.x` (Unity 2019-2020) or `.Net Framework` (Unity 2021+)
+- Switch `Scripting Backend` to `IL2CPP`
+- Switch `Api Compatibility Level` to `.Net 4.x`(Unity 2019-2020) or `.Net Framework` (Unity 2021+)
![player settings](/img/hybridclr/ultimate-project-settings.jpg)
## Create Editor script
-Create the BuildTools.cs file in the `Assets/Editor` directory with the following content:
+Create BuildTools.cs file in the `Assets/Editor` directory with the following content:
```csharp
@@ -172,110 +158,90 @@ public static class BuildTools
{
public const string BackupAOTDllDir = "HybridCLRData/BackupAOT";
- public const string DhaoDir = "HybridCLRData/Dhao";
-
-
- ///
- /// Back up the cropped AOT dll generated when building the main package
- ///
- [MenuItem("BuildTools/BackupAOTDll")]
- public static void BackupAOTDllFromAssemblyPostStrippedDir()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- var backupDir = $"{BackupAOTDllDir}/{target}";
- System.IO.Directory.CreateDirectory(backupDir);
- var dlls = System.IO.Directory.GetFiles(SettingsUtil.GetAssembliesPostIl2CppStripDir(target));
- foreach (var dll in dlls)
- {
- var fileName = System.IO.Path.GetFileName(dll);
- string dstFile = $"{BackupAOTDllDir}/{target}/{fileName}";
- System.IO.File.Copy(dll, dstFile, true);
- Debug.Log($"BackupAOTDllFromAssemblyPostStrippedDir: {dll} -> {dstFile}");
- }
- }
-
- ///
- /// Generate the dhao data corresponding to the first package without any code changes
- ///
- [MenuItem("BuildTools/GenerateUnchangedDHAODatas")]
- public static void GenerateUnchangedDHAODatas()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string backupDir = $"{BackupAOTDllDir}/{target}";
- string dhaoDir = $"{DhaoDir}/{target}";
- BuildUtils.GenerateUnchangedDHAODatas(SettingsUtil.DifferentialHybridAssemblyNames, backupDir, dhaoDir);
- }
-
- ///
- /// Generate dhao data of hot update package
- ///
- [MenuItem("BuildTools/GenerateDHAODatas")]
- public static void GenerateDHAODatas()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string backupDir = $"{BackupAOTDllDir}/{target}";
- string dhaoDir = $"{DhaoDir}/{target}";
- string currentDllDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
- BuildUtils.GenerateDHAODatas(SettingsUtil.DifferentialHybridAssemblyNames, backupDir, currentDllDir, null, null, dhaoDir);
- }
-
- ///
- /// Copy the unmodified first package dll and dhao files to StreamingAssets
- ///
- [MenuItem("BuildTools/CopyUnchangedDllAndDhaoFileToStreamingAssets")]
- public static void CopyUnchangedDllAndDhaoFileToStreamingAssets()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string streamingAssetsDir = Application.streamingAssetsPath;
- Directory.CreateDirectory(streamingAssetsDir);
-
- string dllDir = $"{BackupAOTDllDir}/{target}";
- string dhaoDir = $"{DhaoDir}/{target}";
- foreach (var dll in SettingsUtil.DifferentialHybridAssemblyNames)
- {
- string srcFile = $"{dllDir}/{dll}.dll";
- string dstFile = $"{streamingAssetsDir}/{dll}.dll.bytes";
- System.IO.File.Copy(srcFile, dstFile, true);
- Debug.Log($"CopyUnchangedDllAndDhaoFileToStreamingAssets: {srcFile} -> {dstFile}");
- string dhaoFile = $"{dhaoDir}/{dll}.dhao.bytes";
- dstFile = $"{streamingAssetsDir}/{dll}.dhao.bytes";
- System.IO.File.Copy(dhaoFile, dstFile, true);
- Debug.Log($"CopyUnchangedDllAndDhaoFileToStreamingAssets: {dhaoFile} -> {dstFile}");
- }
- }
-
- ///
- /// Copy hot update dll and dhao files to StreamingAssets
- ///
- [MenuItem("BuildTools/CopyDllAndDhaoFileToStreamingAssets")]
- public static void CopyDllAndDhaoFileToStreamingAssets()
- {
- BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
- string streamingAssetsDir = Application.streamingAssetsPath;
- Directory.CreateDirectory(streamingAssetsDir);
-
- string dllDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
- string dhaoDir = $"{DhaoDir}/{target}";
- foreach (var dll in SettingsUtil.DifferentialHybridAssemblyNames)
- {
- string srcFile = $"{dllDir}/{dll}.dll";
- string dstFile = $"{streamingAssetsDir}/{dll}.dll.bytes";
- System.IO.File.Copy(srcFile, dstFile, true);
- Debug.Log($"CopyUnchangedDllAndDhaoFileToStreamingAssets: {srcFile} -> {dstFile}");
- string dhaoFile = $"{dhaoDir}/{dll}.dhao.bytes";
- dstFile = $"{streamingAssetsDir}/{dll}.dhao.bytes";
- System.IO.File.Copy(dhaoFile, dstFile, true);
- Debug.Log($"CopyUnchangedDllAndDhaoFileToStreamingAssets: {dhaoFile} -> {dstFile}");
- }
- }
+ public const string EncrypedDllDir = "HybridCLRData/EncryptedDll";
+
+ public const string DhaoDir = "HybridCLRData/Dhao";
+
+
+ ///
+ /// 备份构建主包时生成的裁剪AOT dll
+ ///
+ [MenuItem("BuildTools/BackupAOTDll")]
+ public static void BackupAOTDllFromAssemblyPostStrippedDir()
+ {
+ BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
+ var backupDir = $"{BackupAOTDllDir}/{target}";
+ System.IO.Directory.CreateDirectory(backupDir);
+ var dlls = System.IO.Directory.GetFiles(SettingsUtil.GetAssembliesPostIl2CppStripDir(target));
+ foreach (var dll in dlls)
+ {
+ var fileName = System.IO.Path.GetFileName(dll);
+ string dstFile = $"{BackupAOTDllDir}/{target}/{fileName}";
+ System.IO.File.Copy(dll, dstFile, true);
+ Debug.Log($"BackupAOTDllFromAssemblyPostStrippedDir: {dll} -> {dstFile}");
+ }
+ }
+
+ ///
+ /// 生成热更包的dhao数据
+ ///
+ [MenuItem("BuildTools/GenerateDHAODatas")]
+ public static void GenerateDHAODatas()
+ {
+ BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
+ string backupDir = $"{BackupAOTDllDir}/{target}";
+ string dhaoDir = $"{DhaoDir}/{target}";
+ string currentDllDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
+ BuildUtils.GenerateDHAODatas(SettingsUtil.DifferentialHybridAssemblyNames, backupDir, currentDllDir, null, HybridCLRSettings.Instance.injectRuleFiles, dhaoDir);
+ }
+
+ [MenuItem("BuildTools/CompileHotUpdateDlls")]
+ public static void CompileHotUpdateDlls()
+ {
+ BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
+ CompileDllCommand.CompileDll(target);
+ }
+
+
+ [MenuItem("BuildTools/CompileHotUpdateDllsAndGenerateDHAODatas")]
+ public static void CompileHotUpdateDllsAndGenerateDHAODatas()
+ {
+ CompileHotUpdateDlls();
+ GenerateDHAODatas();
+ }
+
+ ///
+ /// 复制热更新dll和dhao文件到HotUpdateDatas
+ ///
+ [MenuItem("BuildTools/CopyDllAndDhaoFileToHotUpdateDataDir")]
+ public static void CopyDllAndDhaoFileToHotUpdateDataDir()
+ {
+ BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
+ string hotUpdateDatasDir = $"{Application.dataPath}/../HotUpdateDatas";
+ Directory.CreateDirectory(hotUpdateDatasDir);
+
+ string dllDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
+ string dhaoDir = $"{DhaoDir}/{target}";
+ foreach (var dll in SettingsUtil.DifferentialHybridAssemblyNames)
+ {
+ string srcFile = $"{dllDir}/{dll}.dll";
+ string dstFile = $"{hotUpdateDatasDir}/{dll}.dll.bytes";
+ System.IO.File.Copy(srcFile, dstFile, true);
+ Debug.Log($"Copy: {srcFile} -> {dstFile}");
+ string dhaoFile = $"{dhaoDir}/{dll}.dhao.bytes";
+ dstFile = $"{hotUpdateDatasDir}/{dll}.dhao.bytes";
+ System.IO.File.Copy(dhaoFile, dstFile, true);
+ Debug.Log($"Copy: {dhaoFile} -> {dstFile}");
+ }
+ }
}
```
-## Create hot update script
+## Create a hot update script
-Create the `Assets/HotUpdate/Hello.cs` file with the following code content
+Create the `Assets/HotUpdate/Hello.cs` file, the code content is as follows
```csharp
using System.Collections;
@@ -283,19 +249,21 @@ using UnityEngine;
public class Hello
{
- public static void Run()
- {
- Debug.Log("Hello, HybridCLR");
- }
+ public static void Run()
+ {
+ // Original code
+ Debug.Log("Hello, World");
+ // After hot update, change to
+ //Debug.Log("Hello, HybridCLR");
+ }
}
```
-## Load hot update assembly
-
-To simplify the demonstration, we do not download HotUpdate.dll through the http server, but directly place HotUpdate.dll in the StreamingAssets directory.
+## Load the hot update assembly
-Create the `Assets/LoadDll.cs` script, then **create a GameObject object in the main scene and mount the LoadDll script**.
+To simplify the demonstration, we do not download HotUpdate.dll through the http server, but directly put HotUpdate.dll in the StreamingAssets directory.
+Create the `Assets/LoadDll.cs` script, and then **create a GameObject object in the main scene and mount the LoadDll script**.
```csharp
using HybridCLR;
@@ -314,65 +282,89 @@ using UnityEngine.Networking;
public class LoadDll : MonoBehaviour
{
- void Start()
- {
- // In the Editor environment, HotUpdate.dll.bytes has been automatically loaded and does not need to be loaded. Repeated loading will cause problems.
+ void Start()
+ {
+ // Editor环境下,HotUpdate.dll.bytes已经被自动加载,不需要加载,重复加载反而会出问题。
#if !UNITY_EDITOR
- Assembly hotUpdateAss = LoadDifferentialHybridAssembly("HotUpdate");
-#else
- // No need to load under Editor, directly find the HotUpdate assembly
- Assembly hotUpdateAss = System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "HotUpdate");
+ LoadDifferentialHybridAssembly("HotUpdate");
#endif
- Type helloType = hotUpdateAss.GetType("Hello");
- MethodInfo runMethod = helloType.GetMethod("Run");
- runMethod.Invoke(null, null);
- }
-
- private Assembly LoadDifferentialHybridAssembly(string assName)
- {
- byte[] dllBytes = File.ReadAllBytes($"{Application.streamingAssetsPath}/{assName}.dll.bytes");
- byte[] dhaoBytes = File.ReadAllBytes($"{Application.streamingAssetsPath}/{assName}.dhao.bytes");
- LoadImageErrorCode err = RuntimeApi.LoadDifferentialHybridAssemblyUnchecked(dllBytes, dhaoBytes);
- if (err == LoadImageErrorCode.OK)
- {
- Debug.Log($"LoadDifferentialHybridAssembly {assName} OK");
- return System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == assName);
- }
- else
- {
- Debug.LogError($"LoadDifferentialHybridAssembly {assName} failed, err={err}");
- return null;
- }
- }
+ Assembly hotUpdateAss = System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "HotUpdate");
+ Type helloType = hotUpdateAss.GetType("Hello");
+ MethodInfo runMethod = helloType.GetMethod("Run");
+ runMethod.Invoke(null, null);
+ }
+
+
+ ///
+ ///
+ ///
+ /// 不含文件名后缀的程序集名,如HotUpdate
+ ///
+ private void LoadDifferentialHybridAssembly(string assName)
+ {
+ string assFile = $"{Application.streamingAssetsPath}/{assName}.dll.bytes";
+ // 如果不存在,则使用原始AOT程序集
+ if (!File.Exists(assFile))
+ {
+ LoadImageErrorCode err = RuntimeApi.LoadOriginalDifferentialHybridAssembly(assName);
+ if (err == LoadImageErrorCode.OK)
+ {
+ Debug.Log($"LoadOriginalDifferentialHybridAssembly {assName} OK");
+ }
+ else
+ {
+ Debug.LogError($"LoadOriginalDifferentialHybridAssembly {assName} failed, err={err}");
+ }
+ }
+ else
+ {
+ byte[] dllBytes = File.ReadAllBytes($"{Application.streamingAssetsPath}/{assName}.dll.bytes");
+ byte[] dhaoBytes = File.ReadAllBytes($"{Application.streamingAssetsPath}/{assName}.dhao.bytes");
+ LoadImageErrorCode err = RuntimeApi.LoadDifferentialHybridAssemblyUnchecked(dllBytes, dhaoBytes);
+ if (err == LoadImageErrorCode.OK)
+ {
+ Debug.Log($"LoadDifferentialHybridAssembly {assName} OK");
+ }
+ else
+ {
+ Debug.LogError($"LoadDifferentialHybridAssembly {assName} failed, err={err}");
+ }
+ }
+ }
}
-```
+```
At this point, the creation of the entire hot update project is completed! ! !
## Trial run in Editor
-Run the main scene and 'Hello,HybridCLR' will be displayed on the screen, indicating that the code is working properly.
+Run the main scene, and 'Hello, World' will be displayed on the screen, indicating that the code is working properly.
-## Package and run
+## Build the game
-- Run menu `HybridCLR/Generate/All` to perform necessary generation operations. **This step cannot be missed**!!!
+- Run the menu `HybridCLR/Generate/All` to perform necessary generation operations. **This step cannot be omitted**!!!
- Open the `Build Settings` dialog box, click `Build`, select the output directory `{build}`, and execute the build
-- Run `BuildTools/BackupAOTDll` to back up the trimmed dhe dll. In practice, these dlls should be added to version management for later generation of dhao files. These files will not be modified again.
-- Run `BuildTools/GenerateUnchangedDHAODatas` to generate the dhao file of the first package
-- Run `BuildTools/CopyUnchangedDllAndDhaoFileToStreamingAssets` to copy the first package dhe assembly and dhao files to StreamingAssets
-- Copy the `Assets/StreamingAssets` directory to `{build}\dhe_demo2_Data\StreamingAssets`
-- Run `{build}/Xxx.exe`, and the screen will display `Hello,HybridCLR`, indicating that the hot update code has been successfully executed!
+- Run `BuildTools/BackupAOTDll` to back up the dhe dll generated during the build. **This step must be after `Build`**, because the original AOT dll must be the dll generated during the build, not generated during `HybridCLR/Generate/all`
-## Test hot update
+:::tip
+
+The dll backed up by `BuildTools/BackupAOTDll` should be added to the version management for generating dhao files during future hot updates.
-- Modify the `Debug.Log("Hello, HybridCLR");` code in the Run function of `Assets/HotUpdate/Hello.cs` to `Debug.Log("Hello, World");`.
-- Run `HybridCLR/CompileDll/ActiveBulidTarget` to generate hot update dll
-- Run `BuildTools/GenerateDHAODatas` to generate dhao files
-- Run `BuildTools/CopyDllAndDhaoFileToStreamingAssets` to copy the hot update dll and dhao files to the StreamingAssets directory
-- Copy the `Assets/StreamingAssets` directory to `{build}\dhe_demo2_Data\StreamingAssets`
-- Rerun the program and you will find `Hello, World` displayed on the screen, indicating that the hot update code has taken effect!
+:::
+
+## First package test
+
+- Run `{build}/Xxx.exe`, and the screen displays `Hello, World`, indicating that the original code has been executed!
+
+## Test hot update
+- Please make sure that `BuildTools/BackupAOTDll` has been executed in the `Build Game` step. Run it once, do not run it multiple times
+- Modify `Debug.Log("Hello, World")` in the `Hello::Run` function to `Debug.Log("Hello, HybridCLR")`
+- Run `BuildTools/CompileHotUpdateDllsAndGenerateDHAODatas` to generate hot update dll and corresponding dhao files
+- Run `BuildTools/CopyDllAndDhaoFileToHotUpdateDataDir` to copy HotUpdate.dll.bytes and HotUpdate.dhao.bytes to the `HotUpdateDatas` directory
+- Manually copy HotUpdate.dll.bytes and HotUpdate.dhao.bytes in the `HotUpdateDatas` directory to the `{build}\StreamingAssets` directory
+- Run again, and `Hello, HybridCLR` will be printed on the screen
-This completes the hot update experience!
+This completes the hot update experience! ! !
diff --git a/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/useIncodes.md b/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/useIncodes.md
new file mode 100644
index 00000000..6f29d35c
--- /dev/null
+++ b/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/useIncodes.md
@@ -0,0 +1,53 @@
+# Use in code
+
+## RuntimeApi::LoadOriginalDifferentialHybridAssembly
+
+:::tip
+
+The interface is supported since v6.6.0.
+
+:::
+
+When no code update occurs during the initial build of the App, or when there is a code update but the code of the DHE assembly is not updated, this interface can be called to indicate that the original AOT implementation is used completely.
+
+Sample code:
+
+```csharp
+string assFile = $"{Application.streamingAssetsPath}/{assName}.dll.bytes";
+// If it does not exist, use the original AOT assembly
+if (!File.Exists(assFile))
+{
+LoadImageErrorCode err = RuntimeApi.LoadOriginalDifferentialHybridAssembly(assName);
+if (err == LoadImageErrorCode.OK)
+{
+Debug.Log($"LoadOriginalDifferentialHybridAssembly {assName} OK");
+}
+else
+{
+Debug.LogError($"LoadOriginalDifferentialHybridAssembly {assName} failed, err={err}");
+}
+}
+```
+
+## RuntimeApi::LoadDifferentialHybridAssemblyUnchecked
+
+When a DHE assembly code changes, this interface is needed to load the DHE assembly. Note that you cannot use Assembly.Load to load the DHE assembly, which will result in an error.
+
+This interface has two parameters: currentDllBytes and optionBytes.
+
+- currentDllBytes is the bytes of the latest DHE assembly file
+
+- optionBytes is the bytes of the dhao file. [dhao file](./dhao) contains DHE change information, which is used to indicate which functions run in aot mode and which are executed in interpreted mode.
+
+```csharp string assFile = $"{Application.streamingAssetsPath}/{assName}.dll.bytes"; // If it does not exist, use the original AOT assembly if (File.Exists(assFile)) { byte[] dllBytes = File.ReadAllBytes($"{Application.streamingAssetsPath}/{assName}.dll.bytes"); byte[] dhaoBytes = File.ReadAllBytes($"{Application.streamingAssetsPath}/{assName}.dhao.bytes"); LoadImageErrorCode err = RuntimeApi.LoadDifferentialHybridAssemblyUnchecked(dllBytes, dhaoBytes); if (err == LoadImageErrorCode.OK) { Debug.Log($"LoadDifferentialHybridAssembly {assName} OK" ); } else { Debug.LogError($"LoadDifferentialHybridAssembly {assName} failed, err={err}");
+}
+}
+
+```
+
+## Notes:
+
+- Even if the DHE assembly has not changed, RuntimeApi::LoadOriginalDifferentialHybridAssembly must be explicitly executed before running any code in the DHE assembly
+- LoadOriginalDifferentialHybridAssembly or LoadDifferentialHybridAssemblyUnchecked to load the DHE assembly in the order of assembly dependencies
+- The DHE assembly loaded by RuntimeApi::LoadOriginalDifferentialHybridAssembly is a normal AOT assembly. If the generics in the DHE assembly are referenced in other hot update assemblies and full generic sharing is not enabled, the AOT generic problem will occur like a normal AOT assembly. This can be solved by using full generic sharing or supplementary metadata mechanism
+- The DHE assembly loaded by RuntimeApi::LoadDifferentialHybridAssemblyUnchecked already contains metadata. Even if full generic sharing is not enabled, do not add metadata to the DHE assembly. It will fail if added. Other non-DHE AOT assemblies can add metadata as usual.
diff --git a/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/workflow.md b/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/workflow.md
deleted file mode 100644
index 901758eb..00000000
--- a/i18n/en/docusaurus-plugin-content-docs/current/business/ultimate/workflow.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Simplify dhao workflow
-
-Based on the same version of the original project, the original dll will have slight differences when publishing different platforms, resulting in the need to calculate a separate dhao file for each platform (even for the same platform, due to the instability of code compilation, the generated original dll may also have slight differences), which makes the maintenance of dhao complicated and error-prone. This problem is particularly serious when multiple new and old game packages exist at the same time.
-
-The solution to this problem mainly relies on `merging dhao files`.
-
-## Merging dhao files
-
-Based on the same or similar source code, the original dhe assemblies of game packages released on different platforms have only slight differences, and the dhao files generated during hot updates also have only slight differences.
-
-You can consider merging the dhao files of multiple platforms corresponding to the same dhe assembly, which does not affect the correctness of the operation and has little impact on performance.
-
-We provide the `HybridCLR.Editor.DHE.BuildUtil::MergeDHAOFiles` function to achieve the goal of merging dhao files.
-
-Note that the workflow with verification cannot use the method of merging dhao files, because the workflow with verification will check the md5 code of the original dll, which is definitely not a match.
\ No newline at end of file
diff --git a/sidebars.js b/sidebars.js
index b9cdec36..58e87252 100644
--- a/sidebars.js
+++ b/sidebars.js
@@ -118,10 +118,10 @@ const sidebars = {
collapsed: true,
items: [
'business/ultimate/intro',
- 'business/ultimate/quickstartchecked',
'business/ultimate/quickstartunchecked',
+ 'business/ultimate/build',
+ 'business/ultimate/dhao',
'business/ultimate/manual',
- 'business/ultimate/workflow',
'business/ultimate/freetrial',
'business/ultimate/injectrules',
'business/ultimate/commonerrors',