前断时间做项目的时候,发现一个问题:动态导入的dll(即打包成exe后再放入包中的dll),unity提供的特性RuntimeInitializeOnLoadMethod标注的方法没有被调用。
代码很简单,只是测试用,如下:
namespace TestProject
{
public class Test
{
[RuntimeInitializeOnLoadMethod]
private static void Init()
{
Debug.Log("Test.Init func");
}
}
}
Test的Init函数加上RuntimeInitializeOnLoadMethod和去掉RuntimeInitializeOnLoadMethod后分别出包,对比后发现,只有globalgamemanagers文件有不同,虽然该文件已经加密,但用BCompare打开后我们可以看到些许端倪,见下图蓝色框框处:
原来unity把有用RuntimeInitializeOnLoadMethod的相关信息存储在了该文件中,TestProject为dll名称,TestProject.Test为命名空间,Init为使用到特性的函数。
这是一个聪明的做法,大家都知道C#的反射是很耗费时间的,如果不把上面的信息提前存储起来,而等到运行时再加载所有的dll,得到所有的Type,一个一个的函数查询有没有用到RuntimeInitializeOnLoadMethod的话,那效率肯定是非常感人的。所以Unity把这部分时间分摊到了编辑期,每把一个dll考入unity工程或者有改变dll时,Unity都会对其进行分析,然后把感兴趣的内容存储起来,运行时根据这些内容,精确的找到相应的点,执行就好了(笔者自行yy的)。
那具体是怎么做的呢?其实很简单,我们一起来实现这个功能:
就是用到了一些c#反射的知识,获取RuntimeInitializeOnLoadMethod实现思路是这样的:在某个时机点,获取出所有感兴趣的dll--》依次加载dll--