HybridCLR热更打包后AOT泛型函数实例化缺失处理

在工程打包后,运行报错

MissingMethodException:AOT generic method not instantiated in aot.assembly:mscorlib.dll,method:System.Collections.Generic.Dictionary`2+Enumerator[FormName,System.Int64]System.Collections.Generic.Dictionary`[FormName,System.Int64]::GetEnumerator()

该问题是因为AOT泛型函数实例化缺失导致的,所以需要补充元数据。HybridCLR官方提供了一种解决方案:基于补充元数据的泛型函数实例化技术(HybridCLR的专利技术)

官方文档可参考:AOT泛型 | HybridCLR

操作步骤

第一步

1、该操作可以收集热更新中用到的AOT泛型实例,生成的裁剪后的AOT dll可以用于补充元数据

HybridCLR会自动把dll文件复制到{project}/HybridCLRData/AssembliesPostIl2CppStrip/{target}文件夹下

第二步

选择最常用的几个dll文件,复制到工程中,并进行添加后缀.bytes(可以用于资源热更新)

复制代码
"mscorlib"
"System"
"System.Core"
"Assembly-CSharp"
"Google.Protobuf"

第三步

流程说明:运行时在加载热更dll后,再进行加载补充元数据dll(即上文中操作的dll.bytes文件),最后再进行初始化场景和处理其他游戏逻辑。

加载补充元数据示例代码

cs 复制代码
public void OnInit()
{
    StartCoroutine(LoadAOTMetadata());
}


IEnumerator LoadAOTMetadata()
{
    // 前三个是系统自带,推荐带上,第四个是自己游戏AOT的程序集
    var AotAssemblyDlls = new string[] {
        "mscorlib",
        "System",
        "System.Core",
        "Assembly-CSharp",
        "Google.Protobuf"
        };

    for (var i = 0; i < AotAssemblyDlls.Length; i++)
    {
        var aotDllName = AotAssemblyDlls[i];
        var path = $"Assets/HotUpdate/MetaDataDlls/{aotDllName}.dll.bytes";
        var handle = Addressables.LoadAssetAsync<TextAsset>(path);
        yield return handle;
        handle.Completed += (asset) =>
        {
            LoadImageErrorCode err = RuntimeApi.LoadMetadataForAOTAssembly(asset.Result.bytes,HomologousImageMode.SuperSet);
            if (err == LoadImageErrorCode.OK)
                Debug.Log($"LoadMetadataForAOTAssembly:{aotDllName}. ret:{err}");
            else
                Debug.LogError($"LoadMetadataForAOTAssembly:{aotDllName}. ret:{err}");
        };
    }

   //开始处理场景初始化和游戏逻辑

}

注意事项

1、PatchedAOTAssemblyList列表的计算结果是保守的,实践中很可能不需要补充这么多。如果没有明显的内存压力,直接按列表全补充比较省事。如果需要优化则可以只补充最常见的几个dll(如mscorlib之类),后面遇到AOT泛型错误再加上相应的dll。补充元数据dll是可以热更的,不用担心发布后在某个版本突然遇到泛型错误的问题。

2、目前支持两种元数据模式:

|------------------------------------|--------------------------------------------------------------------------|
| HomologousImageMode.Consistent | 即补充的dll与打包时裁剪后的dll精确一致。因此必须使用build过程中生成的裁剪后的dll,则不能直接复制原始dll。 |
| HomologousImageMode.SuperSet | 即补充的dll是打包时裁剪后的dll的超集。这个模式放松对了AOT dll的要求,你既可以用裁剪后的AOT dll,也可以用原始AOT dll。 |

3、使用补充元数据方案是免费的,补充元数据加载后,大约会占用6倍dll大小的内存,而且这些内存无法回收。如果对内存有较高的要求,请使用商业版本的完全泛型共享技术,不再需要补充元数据,节省这部分内存。

4、如果补充元数据的dll作为额外数据文件也打入了主包(例如放到StreamingAssets下),则主工程启动时加载更优。

5、不同BuildTarget平台的裁剪AOT dll不可复用。

相关推荐
mxwin12 小时前
Unity Shader 半透明物体为什么不能写入深度缓冲?
unity·游戏引擎·shader
晚枫歌F13 小时前
三层时间轮的实现
网络·unity·游戏引擎
咸鱼永不翻身14 小时前
Lua脚本事件检查工具
unity·lua·工具
leo__52016 小时前
单载波中继系统资源分配算法MATLAB仿真程序
算法·matlab·unity
努力长头发的程序猿17 小时前
Unity使用ScriptableObject序列化资源
unity·游戏引擎
mxwin17 小时前
Unity Shader 手写基于 PBR 的 URP Lit Shader 核心光照计算
unity·游戏引擎·shader
小贺儿开发18 小时前
Unity3D 智能云端数字标牌系统
unity·阿里云·人机交互·视频·oss·广告·互动
魔士于安18 小时前
Unity windows 同步 异步 打开文件文件夹工具
游戏·unity·游戏引擎·贴图·模型
魔士于安19 小时前
unity lowpoly 风格 城市 建筑 道路 交通标志
游戏·unity·游戏引擎·贴图·模型
mxwin19 小时前
Unity GPU Shader 性能优化指南
unity·游戏引擎·shader