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

相关推荐
平行云3 小时前
实时云渲染支持数字孪生智能工厂:迈向“零原型”制造
人工智能·unity·ue5·云计算·webrtc·制造·实时云渲染
dzj20213 小时前
Unity中使用LLMUnity遇到的问题(一)
unity·llm·llmunity
DowneyJoy4 小时前
【Unity通用工具类】列表扩展方法ListExtensions
unity·c#·交互
极客柒4 小时前
Unity 大地图 高性能路径引导Shader
unity·游戏引擎
BuHuaX1 天前
Unity项目怎么接入抖音小游戏?
unity·c#·游戏引擎·wasm·游戏策划
Sator11 天前
unity Rayfire破碎插件的踩坑点
unity·游戏引擎
鱼蛋-Felix1 天前
C#浮点数在部分国家解析失效问题
开发语言·unity·c#
龚子亦1 天前
【Jenkins】实现Unity远程自动化打包
unity·自动化·jenkins
垂葛酒肝汤2 天前
放置挂机游戏的离线和在线收益unity实现
游戏·unity·c#