Unity真的挺火的,我自己使用Unity不到两年时间吧,对这个引擎的理解也就仅限于使用层面,并不精通,我一直觉得想要学好什么东西,并不是要看文档看书,看视频什么的,而是要做点东西出来,我做与Unity引擎相关的工作,所以我想模仿Unity做一个引擎,目标是订的有些太玄,但是一步一个小目标嘛,慢慢来吧。
是Unity第一次把Mono这个东西呈现到我的面前的,所以其实首先我想要做的是研究下Mono这个东西,对Mono这个框架的介绍我就不说了,网上虽然不多,不过我能说出来的也不比网上多!
我们直接来看怎么用吧,先到Mono的GitHub上把代码下载下来,然后编译,在Mono目录中有一个叫msvc的文件夹,这里面就是visual studio工程,本人比较low只会在windows下写代码,至于怎么到linux下或者mac下编译我也搞不懂,O(∩_∩)O哈哈~。
我们打开ILSpy,看一下UnityEngine这个dll,看一下GameObject这个类,我们会看到很多这样的属性标签:[MethodImpl(MethodImplOptions.InternalCall)],这个属性标签是什么意思呢?MSDN的解释是 “该调用为内部调用,也就是说它调用了在公共语言运行时中实现的方法”。说的是这个函数不是在C#中实现,而是在公共语言运行时里面实现的,放到Mono这边,他就是在Mono运行时或者是链接了Mono运行时的应用程序中实现的,Unity里就是在Unity的C++代码中实现的。
从mono源码中我们找到了mono_add_internal_call这个函数,看起来和前面那个属性标签应该是对应的,这个函数有两个参数,const char *name 和 const void* method,从字面上理解就应该是函数的名字和指向函数的指针,确实是这样的,name是C#中的函数名,method是C++中的函数地址,这样通过这个函数就能够将C#中的函数和C++中的函数关联起来了,那么这个函数名该怎么给呢?他是以这样 namespace.class::function 的形式给的,如果在C#中定义的是静态函数,那么在C++中函数的参数和C#中一致,如果在C#中定义的是成员函数,C++中函数参数的第一个参数就是这个成员函数所在类的this引用。
说到这,其实C#调用Mono C++中函数其实就那么回事,但是刚才我已经编译好了Mono的dll和一堆lib,那Mono我到底该怎么用呢?先把该链接的文件,该包含的目录,该引用的文件都配好写好,接下来初始化Mono环境,按照下面这个顺序
mono_set_assemblies_path (const char* path); // 设置运行时需要的库目录,这里面包含.net运行时需要的一些dll 如mscorlib等,注意要和你编译自己代码的.netframework版本一致
mono_config_parse(const char *filename); // 设置config ,可以给NULL
mono_jit_init (const char *file); // 填写自己编译的dll文件的路径
mono_thread_set_main(mono_thread_current());
mono_domain_assembly_open (MonoDomain *domain, const char *name);// mono_jit_init 会返回一个DoMain就是这个函数的第一个参数,name给自己编译的dll文件路径。
mono_domain_set(MonoDomain *domain, mono_bool force); // 第一个domain ,第二个给true
mono_assembly_get_image (MonoAssembly *assembly)// mono_domain_assembly_open 会返回一个MonoAssembly,传给这个函数,这个函数返回值是MonoImage*
接下来就可以注册自己在C#中写的函数了。只要初始化没有问题了,其他的就可以自己发挥了,另外在Mono里面一旦出现错误就会立即exit,很让人苦恼,很多时候程序崩溃了根本搞不清楚为什么,但是在崩溃之前都会调用一些输出日志的函数,比如下面这三个,可以在这三个里面下上断点,一旦调用就可以知道什么时候为什么崩溃了。
mono_trace_set_log_handler(MonoLogCallback, nullptr);
mono_trace_set_print_handler(MonoPrintCallback);
mono_trace_set_printerr_handler(MonoPrintCallback);
我很多时候对很多事情都抱着不求甚解的态度,其实这样不太好,尤其是面试的时候,面试官特别喜欢刁难人,所以有些事情还真得搞透彻点,用得对和用得恰到好处还是有区别的,所以希望大家不吝赐教,贴一下我的GitHub地址 https://github.com/panqingyun/E3D-Engine 这个里面就用到了Mono,上面说的比较宽泛,不够具体,详细代码可以看一下这里 https://github.com/panqingyun/E3D-Engine/tree/master/Engine/EngineCore/src/Mono,有错误欢迎批评指正!