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

相关推荐
在路上看风景15 分钟前
26. Mipmap
unity
咸鱼永不翻身2 小时前
Unity视频资源压缩详解
unity·游戏引擎·音视频
在路上看风景2 小时前
4.2 OverDraw
unity
在路上看风景3 小时前
1.10 CDN缓存
unity
ellis197013 小时前
Unity插件SafeArea Helper适配异形屏详解
unity
nnsix14 小时前
Unity Physics.Raycast的 QueryTriggerInteraction枚举作用
unity·游戏引擎
地狱为王14 小时前
Cesium for Unity叠加行政区划线
unity·gis·cesium
小贺儿开发1 天前
Unity3D 八大菜系连连看
游戏·unity·互动·传统文化
在路上看风景1 天前
25. 屏幕像素和纹理像素不匹配
unity
ۓ明哲ڪ1 天前
Unity功能——创建新脚本时自动添加自定义头注释
unity·游戏引擎