CDN + HybridCLR
CDN + HybridCLR
HybridCLR 具有以下几方面的特性和优势:
- HybridCLR扩充了il2cpp的代码,使它由纯AOT runtime变成AOT+Interpreter 混合runtime,进而原生支持动态加载assembly,使得基于il2cpp backend打包的游戏不仅能在Android平台,也能在IOS、Consoles等限制了JIT的平台上高效地以AOT+interpreter混合模式执行,从底层彻底支持了热更新。
- HybridCLR不仅支持传统的全解释执行模式,还开创性地实现了 Differential Hybrid Execution(DHE) 差分混合执行技术。即可以对AOT dll任意增删改,会智能地让变化或者新增的类和函数以interpreter模式运行,但未改动的类和函数以AOT方式运行,让热更新的游戏逻辑的运行性能基本达到原生AOT的水平。
UOS CDN + HybridCLR 使用示例
核心思路是通过 UOS CDN 的 Release / Badge 功能,手动控制 dll 文件的版本更新。
样例为单个 dll 文件的更新流程,样例中每次均会下载远程的 dll 文件,可自行判断远程文件是否更新再下载。
1. 创建和上传资源
首先创建一个空的 Unity Project,在 Unity 项目的 Assets 目录新建 HotUpdate 目录,创建用于热更新的脚本文件(内容可参考Entry.cs)。
通过 HybridCLR (HybridCLR教程参考) 生成 HotUpdate.dll 文件,重命名为 HotUpdate.dll.bytes,上传到 UOS CDN 的 Bucket里:
2. 创建新的发布版本
创建新的发布版本 "Release #1",创建并分配 Badge "v1.0.0",在「RELEASES」页面,复制以 Badge 为前缀的 URL,记为 UOS CDN URL
3. 配置
将UOS CDN URL填入样例代码(内容可参考下方的 LoadDll.cs),执行客户端,即可测试修改前的代码逻辑:
4. 更新流程
修改Entry.cs文件内容,重新打包dll上传,创建新的发布版本 "Release #2",将 Badge "v1.0.0" 指向 "Release #2"。
此时运行客户端,可以看见会执行修改后的代码逻辑(由于缓存,这里可能会有约一分钟的延迟才生效)。
至此,您已经完成了 UOS 与 HybridCLR 的搭配操作,期待您在后续的探索中有更多的发现。
示例代码
1. Entry.cs
public static class Entry
{
public static void Start()
{
Debug.Log("[Entry::Start] 看到这个日志表示你成功运行了热更新代码 v1.0");
}
}2. LoadDll.cs
public class LoadDll : MonoBehaviour
{
private const string uos_cdn_prefix = {UOS CDN URL};
void Start()
{
StartCoroutine(InitHotUpdate("HotUpdate.dll.bytes"));
}
IEnumerator InitHotUpdate(string filename)
{
UnityWebRequest req = UnityWebRequest.Get(uos_cdn_prefix + filename);
yield return req.SendWebRequest();
if (req.isDone)
{
if (req.responseCode == 200)
{
var data = req.downloadHandler.data;
string savePath = string.Format("{0}/{1}", Application.streamingAssetsPath, filename);
System.IO.File.WriteAllBytes(savePath, data);
StartGame();
}
}
else
{
Debug.Log("Not Done");
}
}
public static byte[] ReadBytesFromStreamingAssets(string file)
{
// 不同平台对StreamingAssets目录的支持情况不同,请自行修改实现
return File.ReadAllBytes($"{Application.streamingAssetsPath}/{file}");
}
private static Assembly _hotUpdateAss;
void StartGame()
{
#if !UNITY_EDITOR
_hotUpdateAss = Assembly.Load(ReadBytesFromStreamingAssets("HotUpdate.dll.bytes"));
#else
_hotUpdateAss = System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "HotUpdate");
#endif
Type entryType = _hotUpdateAss.GetType("Entry");
entryType.GetMethod("Start").Invoke(null, null);
}
}