【干货】Mono和IL2CPP的区别

2021-03-10
7952
0

我们都知道游戏必须是跨平台的。我们不能只支持一个平台。否则,如果每个对应的平台都做了相应的编译器,那就真的很累人了。所以跨平台的需求,对于游戏开发来说,是非常重要的。当然Unity也需要这个特性。

 

Unity是如何实现跨平台的?

这就介绍了mono和il2cpp,这两种在unity中编写后端脚本的方法。让我们弄清楚两者之间的区别。

一、Mono

Wiki:Mono是一个由Xamarin公司(先前是Novell,最早为Ximian)所主持的自由开放源码项目。该项目的目标是创建一系列符合ECMA标准的.NET工具,包括C#编译器和通用语言架构。与微软的.NET Framework不同,Mono项目不仅可以运行于Windows系统上,还可以运行于Linux、Unix、OS X,甚至一些游戏平台。
Mono组成组件:C# 编译器,CLI虚拟机,以及核心类别程序库。

 

 

工作流程:

  • 通过C#编译器mcs,将C#编译为IL(中间语言,byte code)

  • 通过Mono运行时中的编译器将IL编译成对应平台的原生码

IL科普
IL的全称是 Intermediate Language,很多时候还会看到CIL(Common Intermediate Language,特指在.Net平台下的IL标准)。翻译过来就是中间语言。
它是一种属于通用语言架构和.NET框架的低阶(lowest-level)的人类可读的编程语言。目标为.NET框架的语言被编译成CIL,然后汇编成字节码。
CIL类似一个面向对象的汇编语言,并且它是完全基于堆栈的,它运行在虚拟机上(.Net Framework, Mono VM)的语言。
具体过程是:C#或者VB这样遵循CLI规范的高级语言,被先被各自的编译器编译成中间语言:IL(CIL),等到需要真正执行的时候,这些IL会被加载到运行时库,也就是VM中,由VM动态的编译成汇编代码(JIT)然后在执行。

 

 

知识点:

 

1.1. 编译器

 

C#编译器mcs:将C#编译为IL
Mono运行时中的编译器:将IL转移为原生码

 

1.2. 三种转译方式:

 

(1)即时编译(Just-in-time,JIT):程序运行过程中,将CIL的byte code转译为目标平台的原生码。
(2) 提前编译(Ahead-of-time,AOT):程序运行之前,将.exe或.dll文件中的CIL的byte code部分转译为目标平台的原生码并且存储,程序运行中仍有部分CIL的byte code需要JIT编译。
(3)完全静态编译(Full-ahead-of-time,Full-AOT):程序运行前,将所有源码编译成目标平台的原生码。

 

1.3 Unity跨平台的原理

 

Mono运行时编译器支持将IL代码转为对应平台原生码,IL可以在任何支持CLI(Common Language Insfrastructure,通用语言环境结构)中运行,IL的运行是依托于Mono运行时。

 

1.3 Unity跨平台的原理

 

Mono运行时编译器支持将IL代码转为对应平台原生码,IL可以在任何支持CLI(Common Language Insfrastructure,通用语言环境结构)中运行,IL的运行是依托于Mono运行时。

 

1.4 IOS不支持jit编译原因:

 

机器码被禁止映射到内存,即封存了内存的可执行权限,变相的封锁了jit编译方式。

 

1.5 JIT编译

 

将IL代码转为对应平台原生码并且将原生码映射到虚拟内存中执行。JIT编译的时候IL是在依托Mono运行时,转为对应的原生码后在依托本地运行。

优点:

  1. 构建应用非常快

  2. 由于Mono的JIT(Just In Time compilation ) 机制, 所以支持更多托管类库

  3. 支持运行时代码执行

  4. 必须将代码发布成托管程序集(.dll 文件 , 由mono或者.net 生成 )

  5. Mono VM在各个平台移植异常麻烦,有几个平台就得移植几个VM(WebGL和UWP这两个平台只支持 IL2CPP)

  6. Mono版本授权受限,C#很多新特性无法使用

  7. iOS仍然支持Mono , 但是不再允许Mono(32位)应用提交到Apple Store

unity 2018 mono版本仍然是mono2.0、unity2020的版本更新到了mono 5.11。

二、IL2CPP【AOT编译】

  1. 通过AOT编译器把IL中间语言转换成CPP文件。
  2. 运行时库提供服务和抽象,例如垃圾收集器,与平台和线程和文件的独立访问以及内部调用的实现(直接修改托管数据结构的本机代码)。

2.1 AOT编译器

 

IL2CPP AOT编译器名为il2cpp.exe。在Windows上,您可以在Editor \ Data \ il2cpp目录中找到它。在OSX上,它位于Unity安装的Contents / Frameworks / il2cpp / build目录中。il2cpp.exe实用程序是一个托管可执行文件,完全用C#编写。

 

IL2CPP工具链:

 

 

2.2 运行时库

 

IL2CPP技术的另一部分是运行时库,用于支持虚拟机。
我们将运行时库称为libil2cpp,这个简单且可移植的运行时库是IL2CPP技术的主要优势之一
通过查看我们随Unity一起提供的libil2cpp的头文件,您可以找到有关libil2cpp代码组织方式的一些线索(您可以在Windows的Editor \ Data \ PlaybackEngines \ webglsupport \ BuildTools \ Libraries \ libil2cpp \ include目录中找到它们) ,或OSX上的Contents / Frameworks / il2cpp / libil2cpp目录)。

 

2.3 为啥要转成CPP呢?

 

快!!!

 

根据官方的实验数据,换成IL2CPP以后,程序的运行效率有了1.5-2.0倍的提升。

 

2. Mono VM在各个平台移植,维护非常耗时,有时甚至不可能完成

 

Mono的跨平台是通过Mono VM实现的,有几个平台,就要实现几个VM,像Unity这样支持多平台的引擎,Mono官方的VM肯定是不能满足需求的。所以针对不同的新平 台,Unity的项目组就要把VM给移植一遍,同时解决VM里面发现的bug。这非常耗时耗力。这些能移植的平台还好说,还有比如WebGL这样基于浏览 器的平台。要让WebGL支持Mono的VM几乎是不可能的。

 

3. 可以利用现成的在各个平台的C 编译器对代码执行编译期优化,这样可以进一步减小最终游戏的尺寸并提高游戏运行速度。

 

4. 由于动态语言的特性,他们多半无需程序员太多关心内存管理,所有的内存分配和回收都由一个叫做GC(Garbage Collector)的组件完成。虽然通过IL2CPP以后代码变成了静态的C ,但是内存管理这块还是遵循C#的方式,这也是为什么最后还要有一个 IL2CPP VM的原因:它负责提供诸如GC管理,线程创建这类的服务性工作。但是由于去除了IL加载和动态解析的工作,使得IL2CPP VM可以做的很小,并且使得游戏载入时间缩短。

2.4 编译区别

使用Mono的时候,脚本的编译运行如下图所示:

3大脚本被编译成IL,在游戏运行的时候,IL和项目里其他第三方兼容的DLL一起,放入Mono VM虚拟机,由虚拟机解析成机器码,并且执行IL2CPP做的改变由下图红色部分标明:

在得到中间语言IL后,使用IL2CPP将他们重新变回C 代码,然后再由各个平台的C 编译器直接编译成能执行的原生汇编代码。

优点

  1. 相比Mono, 代码生成有很大的提高

  2. 可以调试生成的C 代码

  3. 可以启用引擎代码剥离(Engine code stripping)来减少代码的大小

  4. 程序的运行效率比Mono高,运行速度快

  5. 多平台移植非常方便

  6. 相比Mono构建应用慢

  7. 只支持AOT(Ahead of Time)编译

三、区别

IL2CPP比较适合开发和发布项目 ,但是为了提高版本迭代速度,可以在开发期间切换到Mono模式(构建应用快)。

 

转载声明:本文来源于网络,不作任何商业用途

免责声明:本文内部分内容来自网络,所涉绘画作品及文字版权与著作权归原作者,若有侵权或异议请联系我们处理。
收藏

全部评论

您还没登录

暂无留言,赶紧抢占沙发
王氏教育是国内专业的CG数字艺术设计线上线下学习平台,在王氏教育,有原画、插画、漫画、影视、3D模型等培训课程,也有学习资源下载、行业社区交流。CG数字艺术学习,来王氏教育。
绘学霸iOS端二维码

IOS下载

绘学霸安卓端二维码

安卓下载

绘学霸微信小程序二维码

小程序

版权声明
本网站所有产品设计、功能及展示形式,均已受版权或产权保护,任何公司及个人不得以任何方式复制部分或全部,违者将依法追究责任,特此声明。
热线电话
18026259035
咨询时间:9:00~21:00
在线客服
联系网站客服
客服微信:18026259035
公司地址
中国·广州
广州市海珠区晓港中马路130号之19
绘学霸客户端(权限暂无,用于CG资源与教程交流分享)
王氏教育 王氏教育