浅谈Unity与.NetMonoIL2CPP
Posted Hello Bug.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈Unity与.NetMonoIL2CPP相关的知识,希望对你有一定的参考价值。
一:什么是.Net?
.Net是微软的一种技术平台/一种规范,而不是一种语言,可以理解为接口
.NET平台支持多种语言开发:C#、F#、Visual Basic等
目前.Net有三种主流实现
——.Net Framework:主要是基于Windows上开发
——.Net Core:支持跨平台开发
——Mono:支持跨平台开发
二:.Net代码的编译过程
首先我们写的代码通过特定语言的编译器编译成CIL(Common Intermediate Language:中间语言,也可以称为IL或MSIL),它是一种托管代码类似于Java的虚拟机,它会存储在.DLL或.EXE的程序集中,CIL是一种伪代码不能被计算机直接识别。它与平台操作系统无关与CPU无关,这也为跨平台奠定了基础
之后在程序运行时再通过CLR(Common Language Runtime:公共语言运行时)内部的JIT编译器将CIL编译成计算机可以识别的CPU指令(机器码:01010101),IL语言对于CLR来说是透明的,CLR并不知道IL是由哪种语言编译而来
这是一个二次编译的过程
我们知道程序运行时候需要占用计算机的内存,C++的程序员是需要自己手动操作管理内存的,需要自己分配和释放内存。但是.NET程序员是不需要进行这个操作的,这是因为CLR帮我们自动做了分配内存和释放内存的操作
托管代码与非托管代码:
例如C#,Java等,托管代码包含中间语言,需要经过虚拟机/CLR转换为CPU指令,代码执行效率低,但是它不依赖于操作系统和CPU,在各个操作系统上都能执行,它是运行在虚拟机/CLR上的
例如C++等,非托管代码是直接对接CPU指令,代码执行效率高,但是不同的操作系统需要单独编写代码,重复低效,它是运行在机器上的。C++能跨平台可以理解为每个平台都实现了一套解析c++的运行库
三:什么是Mono?
因为.Net Framework本身只能在Windows平台上运行,对于跨平台的需求Mono就产生了
Mono是基于CLI和C#的ECMA标准提供的.Net的另一种实现,与.Net不同的是它将CLR在所有支持的平台上重新实现了一遍(安卓、Switch,PS4)并且还将.Net Framework提供的基础类库也重新实现了一遍
四:Mono的组成
——C#编译器:C#编译器称为mcs,可以完成C#的编译工作,作用就是将C#源码编译成中间语言CIL,在非Windows平台上需要Mono运行时来运行,而在非Windows平台上既可以用.Net运行时,也可以使用Mono运行时
——Mono运行时(Mono VM): 实现了ECMA公共语言架构,提供了一个即时编译器(JIT)、预编译器(AOT)、类库加载器、垃圾回收器、线程系统和互操作性功能
——基础类库(.Net类库):提供一组全面的类,这些类兼容.Net框架并保持一致,时候构建程序的结实基础
——Mono类库:提供了很多超越基础类库的类,提供了额外的功能,例如一些处理Gtk+,Zip文件,LDAP,OpenGL、Cairo、POSIX等等
五:什么是Mono运行时?
C#编译器mcs的作用是将C#源码编译成中间语言CIL,Mono运行时的作用是将CIL转换成机器语言
Mono运行时提供了三种转译方式
——即时编译(JIT):在运行过程中,将CIL编译成机器码。它是在程序运行时才编译代码,解释一条语句执行一条语句,同时也会将编译过的代码进行缓存,而不是每一次都进行编译
——提前编译(AOT):在运行前,将CIL编译成机器码并储存起来,但还是有一部分编译需要用到JIT
——完全静态编译(Full AOT):在ios平台上是禁止JIT的,所以Mono只能以Full AOT模式运行。及其器码被禁止映射到内存,即封存了内存的可执行权限,变相的封锁了jit编译方式
六:IL2CPP
由于Mono的一些不足而引发出了一种新的解决方案:IL2CPP,在得到中间语言IL后,使用IL2CPP将他们重新变回C++代码,然后再由各个平台的C++编译器直接编译成能执行的机器码
IL2CPP很好理解她的含义:将IL代码转换成CPP文件
现在的大趋势都是把语言加上动态特性,哪怕是C++这样的静态语言,也出现了适合IL的C++编译 器,那为什么Unity要把IL再转回静态的CPP呢?原因如下:
——Mono VM在各个平台移植,维护非常耗时,有时甚至不可能完成
Mono的跨平台是通过Mono VM实现的,有几个平台,就要实现几个VM,像Unity这样支持多平台的引擎,Mono官方的VM肯定是不能满足需求的。所以针对不同的新平台,Unity的项目组就要把VM给移植一遍,同时解决VM里面发现的bug,这非常耗时耗力。而且有些平台无法进行移植
2.Mono版本授权受限
因为Mono的授权受限,Unity无法升级Mono版本导致一些新的C#特性无法使用,如果换作是IL2CPP,IL2CPP VM这套完全自己开发的组件,就解决了这个问题
3.提高运行效率
根据官方的实验数据,换成IL2CPP以后,程序的运行效率有了1.5-2.0倍的提升
七:Mono和IL2CPP总结
——IL2CPP只支持AOT方式,Mono支持AOT,JIT所有方式
——平台支持:android平台支持Mono和IL2CPP的所有编译方式,而IOS只支持Mono的Full AOT模式和IL2CPP
以上是关于浅谈Unity与.NetMonoIL2CPP的主要内容,如果未能解决你的问题,请参考以下文章
[Unity]浅谈AssetBundle的依赖关系打包与加载