Unity3D——C#编译到运行的过程分析

一、Unity引擎是如何作到跨平台运行的

咱们从基础概念开始,一步步走进真相:缓存

程序集

一个.Net程序由一个或者多个程序集组成,程序集能够是库,也能够是应用程序。.Net中,库项目导出的文件格式为.dll,应用程序导出后的文件格式为.exe。框架

相似Flash项目,也是由库项目和应用程序项目组成。在Flash中,库项目导出后的文件格式为.swc,应用程序导出后的文件格式为.swf。函数

好比:通常Unity项目里包含这四个C#库项目:测试

vs编译以后,而后咱们在项目目录的缓存目录Library\ScriptAssemblies下,能找到对应的四个dll文件:翻译

CIL(Common Language Runtime)

刚才咱们提到C#库项目导出以后生成的是一个DLL文件, 这个DLL文件里,存放的是CIL代码集。3d

它是微软在发布.Net框架的时候,一块儿发布的一个语言。CIL语言大概长这个样子:cdn

里面有几个咱们很熟悉的词汇,Hello,world,System.Consolve::WriteLine。没错,它的功能就是输出Hello,world。

它本来的C#程序是这样:blog

在.Net平台下,全部的语言(C#,VB.NET等)都会被编译成CIL,而后运行在虚拟机上,由虚拟机把CIL转换成各个平台的原生码(CPU可直接执行的代码)。游戏

是否是又有点像Flash,Flash程序也是运行在虚拟机上的。ip

虚拟机——Mono

你们在Unity项目中都见过Mono这个词,MonoDeveloper,MonoBehavior等,那Mono究竟是个什么东西?

Mono是一个基于CLR的开源项目,容许引擎和用户的托管代码运行在每个目标平台上。而CLR全称为通用语言运行平台(Common Language Runtime),是微软的.Net虚拟机。它其中两个主要做用是:1,编译——运行前把C#编译为CIL;2,运行——在运行的时把CIL转换成各平台的原生码。

这些是Mono支持的平台:Android,Apple iOS(iOS,Apple macOS,Apple tvOS,Apple watchOS),BSD (OpenBSD, FreeBSD, NetBSD),Linux,Microsoft Windows,Nintendo Wii,Sony PlayStation 3,Sony PlayStation 4,Sun Solaris

IL2CPP

刚才咱们已经知道了Unity跨平台是如何作到跨平台的:

一、把C#经过Mono compiler(其余语言用的是Unity单独开发的一个Unity compiler),编译成CIL语言;

二、各个平台下的Mono虚拟机,运行CIL语言,转换成原生码给CPU执行。

其实Unity后来出了另一个方案:IL2PP。

它会在项目转成CIL以后,再把CIL转成CCPP,而后在运行的时候,把CPP加载进来,由各个平台的IL2PP VM转换成原生码。

Mono vs IL2CPP

Mono模式下编译出来的安卓包体:

\assets\bin\Data\Managed\

Assembly-CSharp.dll 为游戏的控制逻辑,运行时调用。

\lib\armeabi-v7a\
libmono.so包含了mono VM的功能

IL2CPP模式下编译出来的安卓包体:

\assets\bin\Data\Managed\

已经没有了DLL文件。 \lib\armeabi-v7a\

libmono.so变成了libil2cpp.so,包含了Mono模式下的DLL和IL2CPP VM功能

IL2CPP的好处是:

一、运行速度快(CPP转原生码比CIL快);

二、减小Unity公司的维护成本:Mono VM官方是不支持那么多平台的,因此不少平台的Mono VM都须要Unity本身去制做和维护,而C++编译器是原本各个平台都现成的。

缺点是:

一、包体会变大;

二、编译速度慢;

三、不支持JIT。

二、Mono如何运行CIL

这个部分将会告诉你们,IOS平台究竟有和特别之处,为何在它上面实现代码热更新那么麻烦。

一、JIT(Just In Time)模式——在编译的时候,把C#编译成CIL,在运行时,逐条读入,逐条解析翻译成原生码交给CPU再执行;

二、AOT(Ahead Of Time)模式——在编译成CIL以后,会把CIL再处理一遍,编译成原生码,在运行的时候交给CPU直接执行,Mono下的AOT只会处理部分的CIL,还有一部分CIL采用了JIT的模式;

三、Full AOT模式——在编译成CIL以后,把全部的CIL编译成原生码,在运行的时候直接执行。

(留个坑:AOT模式下,编译出来的内容有两部分:原生码和CIL,它们是如何存放的,找了好多资料,没查到,本地想测试,可是环境暂时搭不起来,这个后面和IL2CPP一块儿研究)

Windows和Android系统采用的是JIT模式,那IOS用的哪种呢?

咱们看到,JIT模式是边运行,边翻译,支持运行时加载新的代码进来。而IOS是禁止内存的可执行权限的,不容许在运行过程当中建立新的函数等,因此必需要提早编译好全部的代码,更不用说在运行时加载新的代码了。就是说,在IOS下,Mono采用的是Full AOT模式运行CIL。

相关文章
相关标签/搜索