跳到主要内容

加载和运行

加载更新assembly

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

执行Assembly.Load时内部会将assemblyData和pdbSymbolData都复制一份,调用完后请不要保存assemblyData和pdbSymbolData,否则将造成内存浪费。

代码如下:

    // 从你的资源管理系统中获得热更新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后,有多种方式运行热更新代码,这些技巧跟不考虑热更新时完全相同。

提示

如果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"));

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