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不可复用。

相关推荐
WarPigs37 分钟前
编辑器/AB包资源校验工具
unity
呆呆敲代码的小Y1 小时前
Unity+AI 用一句话制作完整小游戏:飞翔的牛马【AI纯添加-0手工代码】
人工智能·游戏·unity·游戏引擎·游戏制作·unityai·一句话制作游戏
mxwin13 小时前
Unity Shader FLOWMAP岩浆流动制作案例
unity·游戏引擎·shader·uv
小贺儿开发14 小时前
【Arduino与Unity交互探究】01 摇杆模块
科技·unity·游戏引擎·arduino·串口通信·摇杆·硬件交互
Yasin Chen16 小时前
Unity TMP_SDF 分析(三)顶点着色器1
unity·游戏引擎·着色器
mxwin16 小时前
Unity Shader 使用 Noise 图 制作Shader 溶解效果
unity·游戏引擎
mxwin18 小时前
Unity Shader 用 Ramp 贴图实现薄膜干涉效果
unity·游戏引擎·贴图·shader·uv
魔士于安19 小时前
Unity星球资源,八大星球,带fps显示
游戏·unity·游戏引擎·贴图·模型
张老师带你学20 小时前
unity资源,深空陨石,适合太空背景的游戏开发
游戏·unity·模型
鹿野素材屋1 天前
Unity动画幅度太大怎么办
unity·游戏引擎