UH4L2——Unity中启动ILRuntime
UH4L2——Unity中启动ILRuntime
本章代码关键字
1 | AppDomain //用于解释执行dll和pdb文件的类 |
ILRuntime关键类AppDomain
ILRuntime 的开发方式,是在 Unity 主工程和 ILRuntime 热更工程中进行开发的,两个工程之间可以相互访问调用
ILRuntime 热更代码最终会生成一个 dll 文件和一个 pdb 文件,这里面就包含了我们热更代码的相关信息
而 ILRuntime 提供了AppDomain
类,是ILRuntime提供的用于解释执行dll和pdb文件的,通过它我们才能解释执行我们的热更代码
它的作用就有点类似xLua中的 LuaEnv lua解析器
从本节Unity中启动 ILRuntime 我们更能够感受到,ILRuntime 热更新的内容其实就是热更工程中的dll文件和pdb文件
这两个文件中就包含了我们所有的热更 C# 代码信息,以后如果我们要做远端热更新,只需要把他们放入AB包下载即可
Unity中启动ILRuntime
-
声明
AppDomain
对象(命名空间ILRuntime.Runtime.Enviorment
)1
2
3
4
5
6private AppDomain appDomain;
void Start()
{
appDomain = new AppDomain();
} -
加载本地或远端下载的dll和pdb文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38public class Lesson2 : MonoBehaviour
{
private AppDomain appDomain;
void Start()
{
appDomain = new AppDomain();
StartCoroutine(LoadHotUpdateInfo());
}
/// <summary>
/// 去异步加载我们的热更新相关的dll和pdb文件
/// </summary>
/// <returns></returns>
IEnumerator LoadHotUpdateInfo()
{
//异步加载DLL文件
UnityWebRequest reqDll = UnityWebRequest.Get(Application.streamingAssetsPath + "/HotFix_Project.dll");
UnityWebRequest reqDll = UnityWebRequest.Get("file://" + Application.streamingAssetsPath + "/HotFix_Project.dll");
yield return reqDll.SendWebRequest();
if (reqDll.result != UnityWebRequest.Result.Success)
print("加载DLL文件失败" + reqDll.responseCode + reqDll.result);
//读取加载的DLL数据
byte[] dll = reqDll.downloadHandler.data;
reqDll.Dispose();
//我们还可以加载调试用的pdb文件
UnityWebRequest reqpdb = UnityWebRequest.Get(Application.streamingAssetsPath + "/HotFix_Project.pdb");
yield return reqpdb.SendWebRequest();
if (reqpdb.result != UnityWebRequest.Result.Success)
print("加载DLL文件失败" + reqpdb.responseCode + reqpdb.result);
//读取加载的DLL数据
byte[] pdb = reqpdb.downloadHandler.data;
reqpdb.Dispose();
}
} -
将加载的数据以流的形式(文件流或者内存流对象)传递给
AppDomain
对象中的LoadAssembly
方法 -
初始化ILRuntime相关信息(目前只需要告诉ILRuntimeUnity的主线程的线程ID,主要目的是能够在Unity的Profiler剖析器窗口中分析问题)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56using ILRuntime.Mono.Cecil.Pdb;
using ILRuntime.Runtime.Enviorment;
using System.Collections;
using System.IO;
using System.Threading;
using UnityEngine;
using UnityEngine.Networking;
public class Lesson2 : MonoBehaviour
{
private AppDomain appDomain;
//用于存储加载出来的两个文件的内存流对象
private MemoryStream dllStream;
private MemoryStream pdbStream;
// Start is called before the first frame update
void Start()
{
appDomain = new AppDomain();
StartCoroutine(LoadHotUpdateInfo());
}
/// <summary>
/// 去异步加载我们的热更新相关的dll和pdb文件
/// </summary>
/// <returns></returns>
IEnumerator LoadHotUpdateInfo()
{
//异步加载DLL文件
UnityWebRequest reqDll = UnityWebRequest.Get(Application.streamingAssetsPath + "/HotFix_Project.dll");
UnityWebRequest reqDll = UnityWebRequest.Get("file://" + Application.streamingAssetsPath + "/HotFix_Project.dll");
yield return reqDll.SendWebRequest();
if (reqDll.result != UnityWebRequest.Result.Success)
print("加载DLL文件失败" + reqDll.responseCode + reqDll.result);
//读取加载的DLL数据
byte[] dll = reqDll.downloadHandler.data;
reqDll.Dispose();
//编辑器环境下,我们可以加载调试用的pdb文件
UnityWebRequest reqpdb = UnityWebRequest.Get(Application.streamingAssetsPath + "/HotFix_Project.pdb");
yield return reqpdb.SendWebRequest();
if (reqpdb.result != UnityWebRequest.Result.Success)
print("加载DLL文件失败" + reqpdb.responseCode + reqpdb.result);
//读取加载的DLL数据
byte[] pdb = reqpdb.downloadHandler.data;
reqpdb.Dispose();
pdbStream = new MemoryStream(pdb);
dllStream = new MemoryStream(dll);
//将我们两个文件的内存流用于初始化 appDomain 我们之后就可以通过该对象来执行我们对应的热更代码了
appDomain.LoadAssembly(dllStream, pdbStream, new PdbReaderProvider());
//初始化ILRuntime相关信息(目前只需要告诉ILRuntime主线程的线程ID,主要目的是能够在Unity的Profiler剖析器窗口中分析问题)
appDomain.UnityMainThreadID = Thread.CurrentThread.ManagedThreadId;
}
} -
执行热更代码中的逻辑
注意:一般在一个项目中,大多数情况下只需要一个
AppDomain
对象
关于ILRuntime相关内容的释放
注意!为
AppDomain
读取 dll 文件和 pdb 文件而创建的两个内存流不可以随意关闭,只有在热更相关内容不再使用时才可用关闭
1 | private void OnDestroy() |
声明一个管理ILRuntime相关的管理器
- 由于会使用协程相关内容加载dll和pdb文件,因此该管理器是继承
MonoBehaviour
的 - 为了外部可以使用ILRuntime相关内容,因此管理器的
AppDomain
是公开的,供外部调用 -
StartILRuntime
:调用该方法会异步加载dll文件和pdb文件,然后将其作为内存流由AppDomain
读取,异步执行完毕后会执行传入的回调方法 -
StopILRuntime
:会释放两个内存流和AppDomain
对象 -
InitILRuntime
:初始化AppDomain
的方法,在AppDomain
对象读取了两个流之后就会调用 -
ILRuntimeLoadOverDo
:在加载完 dll 文件和 pdb 文件并初始化AppDomain
后,会执行的方法 -
LoadHotUpdateInfo
:异步加载 dll 文件和 pdb 文件并执行初始化方法的协程
1 | using ILRuntime.Mono.Cecil.Pdb; |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 文KRIFE齐的博客!