返回介绍

博客

帮助文档

加载和运行

发布于 2024-08-03 14:42:57 字数 6816 浏览 0 评论 0 收藏 0

加载更新assembly

根据你们项目资源管理的方式,获得热更新dll的bytes数据。然后再直接调用Assembly.Load(byte[] assemblyData)即可。自v6.4.0版本起,支持加载pdb符号文件,即可以通过 调用Assembly.Load(byte[] assemblyData, byte[] pdbSybmbolData)同时加载程序集和调试符号。

代码如下:

    // 从你的资源管理系统中获得热更新dll的数据
    byte[] assemblyData = xxxx; 

    // Assembly.Load内部会自动复制assemblyData,调用完此函数可以释放assemblyData,不需要保存起来。
    Assembly ass = Assembly.Load(assemblyData);

    // 同时加载dll和pdb文件
    byte[] assData2 = yyy;
    byte[] pdbData2 = zzz;
    Assembly ass2 = Assembly.Load(assData2, pdbData2);

如果有多个热更新dll,请一定要按照依赖顺序加载,先加载被依赖的assembly。加载完热更新dll后,有多种方式运行热更新代码,这些技巧跟不考虑热更新时完全相同。

:::tip 如果Assembly.Load花费太多时间,造成卡顿,你可以在其他线程异步加载。 :::

通过反射直接运行热更新函数

假设热更新集中有HotUpdateEntry类,主入口是静态的Main函数,代码类似:

class HotUpdateEntry
{
    public static void Main()
    {
        UnityEngine.Debug.Log("hello, HybridCLR");
    }
}

你用如下方式运行:

    // ass 为Assembly.Load返回的热更新assembly。
    // 你也可以在Assembly.Load后通过类似如下代码查找获得。
    // Assembly ass = AppDomain.CurrentDomain.GetAssemblies().First(assembly => assembly.GetName().Name == "Your-HotUpdate-Assembly");
    Type entryType = ass.GetType("HotUpdateEntry");
    MethodInfo method = entryType.GetMethod("Main");
    method.Invoke(null, null);

通过反射创造出Delegate后运行

    Type entryType = ass.GetType("HotUpdateEntry");
    MethodInfo method = entryType.GetMethod("Main");
    Action mainFunc = (Action)Delegate.CreateDelegate(typeof(Action), method);
    mainFunc();

通过反射创建出对象后,再调用接口函数

假设AOT中有这样的接口

public interface IEntry
{
    void Start();
}

热更新中实现了这样的类

class HotUpdateEntry : IEntry
{
    public void Start()
    {
        UnityEngine.Debug.Log("hello, HybridCLR");
    }
}

你用如下方式运行:

    Type entryType = ass.GetType("HotUpdateEntry");
    IEntry entry = (IEntry)Activator.CreateInstance(entryType);
    entry.Start();

通过动态AddComponent运行脚本代码

假设热更新中有这样的代码:

class Rotate : MonoBehaviour
{
    void Update()
    {

    }
}

你在AOT中运行如下代码:

    Type type = ass.GetType("Rotate");
    GameObject go = new GameObject("Test");
    go.AddComponent(type);

通过初始化从打包成assetbundle的prefab或者scene还原挂载的热更新脚本

假设热更新中有这样的入口脚本,这个脚本被挂到HotUpdatePrefab.prefab上。


public class HotUpdateMain : MonoBehaviour
{
    void Start()
    {
        Debug.Log("hello, HybridCLR");
    }
}

你通过实例化这个prefab,即可运行热更新逻辑。

        AssetBundle prefabAb = xxxxx; // 获得HotUpdatePrefab.prefab所在的AssetBundle
        GameObject testPrefab = Instantiate(prefabAb.LoadAsset<GameObject>("HotUpdatePrefab.prefab"));

这种方法不需要借助任何反射,而且跟原生的启动流程相同,推荐使用这种方式初始化热更新入口代码!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文