Unity跨平台基本原理
-
- Unity跨平台基本原理
-
- 微软的.Net是什么
- [微软做 .Net平台的目的](#微软做 .Net平台的目的)
- 如何实现的.Net跨语言?
- 如何实现的跨平台?
-
- [.Net Core](#.Net Core)
- [.Net FrameWork 到 .Net Core](#.Net FrameWork 到 .Net Core)
- Mono
- Mono如何实现跨平台
- 总结如何实现的跨平台?
- 主要内容
- Unity和Mono的关系
- Unity跨平台的必备概念
- Mono跨平台基本原理
- Mono主要构成部分
- Unity跨平台的基本原理(Mono)
- 基于Mono跨平台的优缺点
- 总结
- IL2CPP是什么
- IL2CPP跨平台原理
- IL2CPP和Mono的区别
- Mono优缺点
- IL2CPP优缺点
- Mono和IL2CPP的最大区别
- Mono和IL2CPP的使用建议
- 总结
Unity跨平台基本原理
微软的.Net是什么
微软的 .Net既不是编程语言也不是框架 是类似于 互联网时代、次时代、21世纪、信息时代之类的宣传口号
它是一整套技术体系的统称,或者说它是微软提供的技术平台的代号
包含的内容有
框架体系:.Net Framework、.Net Core、Mono等等
开发语言:C#、VB、F#等等(C#是.Net平台主推的开发语言)
开发工具:Visual Studio、Visual Studio Code 等等
你可以简单理解.Net本质上就是微软为自己的一系列产品取的一个代号
微软做 .Net平台的目的
- 跨语言
只要是面向.NET平台的编程语言(C#、VB、C++、F#等等),用其中一种语言编写的内容可以无缝地用在另一种语言编写的应用程序中
- 跨平台
一次编译,不需要任何代码修改 ,应用程序就可以运行在任意有**.NET框架实现的操作系统上,即代码不依赖于操作系统,也不依赖硬件环境**
如何实现的.Net跨语言?
CLS(Common Language Specification) 公共语言规范
.Net专门参考每种语言并找出了语言间的共性,定义了一组规则。
与其说是规则,不如说它是一组语言互操作的标准规范
只要开发者都遵守这个规则来编码,那么代码就能被任意.Net平台支持的语言所通用,即可以通过不同的编程语言 (C#、VB、J#等等)来创建应用程序
CTS(Common Type System) 公共类型系统
当你需要设计面向.Net的语言时需要遵循一个体系,这个体系就是CTS
刚才提到的CLS公共语言规范就是是CTS公共类型系统的子级
一个编程语言,如果它能够支持CTS,那么我们就称它为**面向.NET平台的语言 **
CLI(Common Language Infrastructure) 公共语言基础结构
是微软将CTS等内容提交给国际组织计算机制造联合会ECMA的一个工业标准
总结
微软为了实现跨语言,制定了一些规范
只要一门语言支持CTS(公共类型系统)的规则
那么我们就能够使用它在.Net平台下开发应用程序 CLS(公共语言规范)是CTS的一个子级,是一组语言互操作的标准规范
我们经常可以看到的CLI公共语言基础结构,它包含CTS公共类型系统 它是微软将CTS等内容提交给国际组织计算机制造联合会ECMA的一个工业标准
Net的跨语言是让各种语言支持.Net的规范CLI(也就是CTS等规范)
早期的.Net系列产品主要是为了给Windows操作系统服务的 并没有跨平台的特性,即使跨语言了
也只是可以使用多语言开发Windows上的应用程序
那么这里就不得不提几个个概念 .Net Framework 、 .Net、Mono
.Net Framework
.Net Framework 在2002年推出1.0版本 .NET Framework 是一个可以快速开发、部署网站服务及应用程序的开发框架 是 Windows 中的一个组件,部分开源,主要用于开发Windows下应用程序
包括 公共语言运行时(Common Language Runtime, CLR) 虚拟执行系统 .NET Framework 类库
.Net Framework的体系结构
制作应用程序
编程语言 + 调用各种类库进行开发 生成程序集
-
只要支持CLS公共语言规范的语言都可以用于 开发Windows下的各种应用程序和网站程序
-
**BCL(基础类库)和FCL(框架类库)**是这个 框架体系中为我们实现好的各种API
-
程序集 的表现就是后缀为.dll或者.exe格式的文件 其中包含的最关键信息:
PE头、CLR头(就是一些程序的格式信息,比如入口方法,版本号等等)
CIL代码(通用中间代码) 是介于源代码和机器码之间的代码之后会通过CLR产生机器码
CIL代码你可以理解为由于可能使用不同的代码进行开发 ,所以会将这些代码翻译为统一规范的中间代码
CLR
让应用程序在操作系统上运行 CLR(Common Language Runtime) 公共语言运行时,
它是.Net Framework的基础, 所有的.Net技术都是建立在此之上的 它是一个在执行时管理代码的代码,提供内存管理、 线程管理等等核心服务,就好像一个小型的操作系统一样 所以形象的把它称为**".Net虚拟机" 。**
如果想要应用程序在目标操作系统上能够运行 就必须依靠.Net提供的CLR环境来支持
那就必须在操作系统上安装.Net Framework 它会把程序集中的IL(中间代码)翻译成机器码
最终在操作系统上运行
总结
.Net Framework 是一个主要用于跨语言开发 Windows操作系统下的 应用程序的框架结构
他并不支持跨平台
如何实现的跨平台?
.Net Core
Net Core 是2016年推出的.Net Framework的新一代版本
它就像是.Net Framework的兄弟 是.Net Framework的翻版实现,它是一个开源项目
它是基于.Net Framework来进行设计的主要目的就是跨平台
是.Net技术框架组成在Windows、MacOS、类Linux系统下的具体实现
它的原理就是为不同的操作系统实现对应的 CLR公共语言运行时(.Net虚拟机)
这样就可以在不同的平台上 将IL(中间代码)翻译成机器码最终在操作系统上运行了
.Net FrameWork 到 .Net Core
从前面.Net FrameWork 和 .Net Core相关内容
我们了解到 从并不跨平台的.Net FrameWork 在2002年正式问世 到2016年跨平台的.Net Core的诞生 中间
.Net 平台有14年的并不跨平台的空窗期 而在这段时间内,
难道.Net就并不支持跨平台了吗? 答案当然是否定的,那么我们就不得不提Mono了
Mono
Mono是一个由Xamarin公司(已被微软收购)所赞助的开源项目
它基于.Net的CLI(Common Language Infrastructure)公共语言基础结构
提供了微软.Net FrameWork的另一种实现 它相对.Net FrameWork最大的区别就是具备跨平台的能力
它不仅可以运行在Windows、MacOS、Linux等操作系统 甚至还可以运行在PS3、XBOX、Wii等主机平台上 Mono的1.0版本出现在2004年 也就是说在.Net Core出现之前,Mono是.Net平台实现跨平台的不二之选
Mono如何实现跨平台
Mono利用 .Net平台制定的CLI公共语言基础结构规则
利用它我们可以把很多种语言编译成通用规范的CIL公共中间语言
再利用CLR公共语言运行时,将这些CIL公共中间语言转换为 操作系统的原生代码(主要做的就是在各种操作系统上实现了对应的CLR内容)
这样用各种不同语言编写的逻辑就能够在指定操作系统上运行了 它的这一套规则是在**.Net Framework规则上进行的修改和添加**
总结如何实现的跨平台?
在.Net Core出现之前开发者都通过Mono来实现.Net的跨平台
我们可以使用基于.Net平台的Mono开发 便可以发布可以在主流的各种操作系统上运行的应用程序
主要内容
微软的.Net是什么
是一个包含编程语言、框架、IDE等产品的系列产品统称
.Net跨语言的实现
CLI公共语言基础结构(CTS公共类型系统)
CLS公共语言规范是它的子级
.Net跨平台的实现
基于.Net Framework的 Mono 和 .Net Core
他们两都基于CLI公共语言基础结构和CLR公共语言运行时实现跨语言和跨平台
Unity和Mono的关系
Mono是基于.Net的跨平台方案,同时它具备.Net平台的跨语言特点 Mono的第一个版本是在2004年发布的
Unity公司于2004年成立
Unity的底层是通过C/C++来完成的 但是为了更方便的让开发者使用
Mono在当时成为了不二之选 它同时具备跨平台和跨语言的两个特性
Unity希望能有更多的开发者使用其进行游戏开发并且一次开发一劳永逸
所以跨语言和跨平台对于他们来说是很重要的
虽然C++本身跨平台,但是如果使用C++作为上层逻辑开发语言,那么作为开发者来说选择性相对较少,并且对于初学者来说学习难度也较大
所以当时的Mono是非常满足Unity需求的 不仅支持跨语言还支持跨平台
Unity跨平台的必备概念
Unity主要包括两个部分:
- Unity Engine(引擎): 提供UnityEngine.dll动态库,各平台不同,C/C++编写,包含平台相关代码、 图形API、物理引擎、灯光等等所有游戏引擎底层内容
- Unity Editor(编辑器):提供UnityEditor.dll动态库,大部分由C#编写 ,用户脚本最初可以使用C#、 JavaScript、Boo语言编写,项目代码最后由Mono编译
Mono跨平台基本原理
Mono利用 .Net平台制定的CLI公共语言基础结构规则
利用它我们可以把很多种语言编译成通用规范的CIL公共中间语言
再利用CLR公共语言运行时,将这些CIL公共中间语言转换为 操作系统的原生代码(主要做的就是在各种操作系统上实现了对应的CLR内容)
这样用各种不同语言编写的逻辑就能够在指定操作系统上运行了 它的这一套规则是在**.Net Framework规则上进行的修改和添加**
Mono主要构成部分
-
C#编译器(mcs)
-
Mono Runtime 类似CLR公共语言运行时(虚拟机) 包括JIT(Just in time)即时编译器、AOT(Ahead of time)提前编译器、 GC、类库加载器 等等
-
BCL基础类库
-
Mono类库 提供很多超出.Net的一些额外功能,主要用于构建各种操作系统上的应用
Unity跨平台的基本原理(Mono)
在Unity下使用各种语言进行逻辑实现 这些语言在发布时会被编译成 IL中间代码
最终这些中间代码 在对应操作系统上 通过Mono VM(虚拟机) 真正翻译成机器码运行起来
基于Mono跨平台的优缺点
优点:只要在不同操作系统上实现Mono VM(虚拟机) 那我们能够支持的平台就会"无限"多
缺点: 维护工作耗时耗力,当Unity版本更新时,Mono VM也需要维护和更新,那多对于N多个平台来说,工作量是非常大的。(Unity的工作量) 低版本Mono无法支持新版本C#的强大新特性
总结
-
Unity和Mono的关系
利用Mono实现Unity上层逻辑的跨语言和跨平台
-
Unity跨平台的必备概念:
Unity底层是C/C++,上层逻辑支持多语言(目前只用C#)
Mono的基本构成有C#编译器、Mono运行时(虚拟机)、各种类库等
-
Unity跨平台的基本原理(Mono)
将基于CLI公共语言基础规则的语言 编译成CIL公共中间语言 ,再通过Mono VM(虚拟机) 将其在各操作系统中转译为原生机器码进行运行
-
基于Mono跨平台的优缺点
无限跨平台
维护工作量大,低版本的Mono无法支持新版C#新功能
IL2CPP是什么
IL2CPP是在Unity4.6.1 p5之后的版本中 加入的脚本后处理方式
你可以把它简单理解为是继Mono之后的一种跨平台解决方案
顾名思义就是把 IL中间代码转译为CPP代码(C++)
IL2CPP跨平台原理
通过IL2CPP我们可以将编译好的IL中间代码转译成C++代码 ,再利用各平台优化过的编译器编译为对应平台的目标代码
IL2CPP和Mono的区别
当生成了IL中间代码后
Mono是直接通过虚拟机转译运行
而IL2CPP的步骤多了一些 会将IL中间代码转译为C++代码 ,再通过各平台的C++编译器 直接编译为可执行的原生汇编代码
虽然中间代码变为了C++ 但是内存管理还是遵循C#中GC的方式 这也是为什么有一个IL2CPP VM(虚拟机) 存在的原因,它主要是用来完成 GC管理,线程创建等服务工作的
Mono优缺点
- 构建(最终打包时)速度快
- Mono编译机制是JIT即时编译,所以支持更多类库
- 必须将代码发布为托管程序集(.dll文件)
- Mono VM虚拟机平台维护麻烦,且部分平台不支持(WebGL)
- 由于Mono版本授权原因,C#很多新特性无法使用
- IOS支持Mono,但不在允许32位的Mono应用提交到应用商店
IL2CPP优缺点
- 相对Mono构建(最终打包时)速度慢
- 只支持AOT提前编译
- 可以启用引擎代码剥离来减少代码的大小
- 程序的运行效率比Mono高,运行速度快
- 多平台移植更加方便
Mono和IL2CPP的最大区别
IL2CPP不能在运行时动态生成代码和类型 ,所以必须在编译时就完全确定需要用到的类型
IL2CPP在进行AOT编译时,会裁剪掉那些在代码中没有显式引用的类型,以减小最终打包文件的大小。这是因为AOT编译需要在编译时就确定所有需要的类型,而JIT编译则可以在运行时动态加载和编译代码,因此对于类型的需求不那么严格
举例:List和List中A和B是我们自定义的类,我能必须在代码中显式的调用过,IL2CPP才能保留List和List两个类型。如果在热更新时我们调用List,但是它之前并没有在代码中显示调用过,那么这时就会出现报错等问题。主要就是因为JIT和AOT两个编译模式的不同造成的
如果你在代码中没有显式调用过List<A>
和List<B>
,那么在IL2CPP的AOT编译过程中,这两个类型可能会被裁剪掉,因为IL2CPP无法确定这两个类型在运行时是否需要。而JIT编译模式下,由于可以在运行时动态编译代码,所以不会出现这个问题
Mono和IL2CPP的使用建议
由于IL2CPP的运行效率有很大优势
所以建议大家在实际开发中 直接使用IL2CPP模式进行打包
总结
-
IL2CPP是什么
是Unity4.6.1版本之后加入的新的一种跨平台解决方案
-
Mono跨平台原理
C#代码--->Mono C#编译器--->IL中间代码--->Mono VM--->操作系统的原生代码
-
IL2CPP跨平台原理
C#代码--->Mono C#编译器--->IL中间代码--->IL2CPP--->C++--->C++编译器--->原生汇编代码--->IL2CPP VM
-
Mono和IL2CPP的区别
IL2CPP效率高于Mono,跨平台也更好维护。
Mono是JIT即时编译 ,IL2CPP是AOT提前编译
-
Mono和IL2CPP两种方式的使用建议
建议使用效率更高的IL2CPP