HybridCLR使用泛型

作者:追风剑情 发布于:2026-1-26 16:39 分类:Unity3d

一、什么时候可直接热更泛型代码?

当 AOT 代码中已经使用过某泛型声明时,热更DLL中可以直接使用这种泛型代码。例如,当 AOT 代码中已经使用过 List<float> 时,在热更代码中才能使用 List<float> 泛型,否则会报错。

我们用上一章节使用过的测试用例来验证这一点。

using UnityEngine;

public class Hello
{
    public static void Run()
    {
        Debug.Log("Hello, World");
    }
}  

运行测试

1.png

修改测试用例

using System.Collections.Generic;
using UnityEngine;

public class Hello
{
    public static void Run()
    {
        Debug.Log("Hello, World");
        var arr = new List<float>();
        arr.Add(2.0f);
    }
}  

执行菜单:【HybridCLR】->CompileDll->ActiveBuildTarget 重新生成热更DLL,并替换掉发布程序中的 HotUpdate.dll.bytes 文件。

2.png

3.png

再次运行测试

从下图中的报错信息可以看出,当 AOT 代码中没使用过 List<float> 时,热更代码使用了 List<float> 会引起报错。这是因为 AOT 在编译时未记录 List<float> 的元数据导致。

AOT报错.png

二、补充元数据

执行菜单 【HybridCLR】->Generate->AOTDlls 重新生成包含元数据的 AOT DLL。

AOTDlls.png

重新生成的 AOT DLL 自动保存在 {工程路径}\HybridCLRData\AssembliesPostIl2CppStrip\{平台目录} 下面。

4.png

将 mscorlib.dll 改名为 mscorlib.dll.bytes 并拷贝到发布程序的 StreamingAssets 下面,如图:

5.png

mscorlib.dll.bytes 也需要动态加载,我们接下来对上一章节中的用例代码进行修改。

using System;
using System.Reflection;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
using HybridCLR;

public class LoadDll : MonoBehaviour
{
    void Start()
    {
        // 先补充元数据
        LoadMetadataForAOTAssemblies();

        // Editor环境下,HotUpdate.dll.bytes已经被自动加载,不需要加载,重复加载反而会出问题。
#if !UNITY_EDITOR
        Assembly hotUpdateAss = Assembly.Load(File.ReadAllBytes($"{Application.streamingAssetsPath}/HotUpdate.dll.bytes"));
#else
        // Editor下无需加载,直接查找获得HotUpdate程序集
        Assembly hotUpdateAss = System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "HotUpdate");
#endif

        Type type = hotUpdateAss.GetType("Hello");
        type.GetMethod("Run").Invoke(null, null);
    }

    
    private static void LoadMetadataForAOTAssemblies()
    {
        List<string> aotDllList = new List<string>
        {
            "mscorlib.dll",
            "System.dll",
            //如果使用了Linq,需要这个
            "System.Core.dll", 
            //"Newtonsoft.Json.dll", 
            //"protobuf-net.dll",
        };

        foreach (var aotDllName in aotDllList)
        {
            string filePath = $"{Application.streamingAssetsPath}/{aotDllName}.bytes";
            if (!File.Exists(filePath))
                continue;
            byte[] dllBytes = File.ReadAllBytes(filePath);
            LoadImageErrorCode err = HybridCLR.RuntimeApi.LoadMetadataForAOTAssembly(dllBytes, HomologousImageMode.SuperSet);
            Debug.Log($"LoadMetadataForAOTAssembly:{aotDllName}. ret:{err}");
        }
    }
}  

因为 LoadDll.cs 代码在 AOT 程序集中,需要重新 Build 一个包。现在热更流程变成了先加载元数据DLL,再加载需要热更的逻辑DLL。现在如果在热更代码中新增了 AOT DLL 中没使用到的泛型,只需重新生成 AOT DLL 并丢在 StreamingAssets 下,即可完成补充元数据操作。

再次运行测试。可以看到,补充了元数据后,List<float> 不再报错。

补充元数据后.png

三、优化 AOT DLL 大小

通过 【HybridCLR】->Generate->AOTDlls 生成的 AOD DLL 包含了很多没用到的元数据,接下来写个自定义菜单用来剥离未使用到的元数据。

新创建个 HybridCLREditor.cs 并放到 Assets/Editor 目录下。

using System.IO;
using UnityEditor;
using HybridCLR.Editor;
using HybridCLR.Editor.AOT;

public class HybridCLREditor
{
    // 进一步剔除AOT dll中非泛型函数元数据,输出到StrippedAOTAssembly2目录下
    [MenuItem("HybridCLR/Strip AOT Assembly")]
    public static void StripAOTAssembly()
    {
        BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
        string srcDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
        string dstDir = $"{SettingsUtil.HybridCLRDataDir}/StrippedAOTAssembly2/{target}";
        foreach (var src in Directory.GetFiles(srcDir, "*.dll"))
        {
            string dllName = Path.GetFileName(src);
            string dstFile = $"{dstDir}/{dllName}";
            AOTAssemblyMetadataStripper.Strip(src, dstFile);
        }
    }
}  

执行完 【HybridCLR】->Generate->AOTDlls 后,再执行 【HybridCLR】->Strip AOT Assembly 菜单,即可生成优化后的 AOT DLL。优化后的 AOT DLL 存放在 HybridCLRData\StrippedAOTAssembly2\{平台目录} 中。

查看优化前和优化后的大小差异。

优化前大小 1.66MB。

666.png

优化后大小 740KB。

7777.png

四、泛型共享机制

在 “Project Settings -> Other Settings -> IL2CPP Code Generation” 中可设置泛型共享机制。

1.png

Faster runtime:标准泛型共享机制,性能高,包体大。(HybridCLR官方建议启用 Faster runtime)
Faster (smaller) builds:完全泛型共享机制,性能低,包体小。

标签: Unity3d

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号