【Unity游戏开发】Mono和IL2CPP的区别

2023-10-24 19:50

本文主要是介绍【Unity游戏开发】Mono和IL2CPP的区别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

https://zhuanlan.zhihu.com/p/352463394

前言

用了好几年的unity,都是摸着石头过河,对于一些底层的知识,并没有了解,都停留在知其然,不知所以的状态,每每大家提到Mono堆内存啊,IL2cpp啊,都有点迷幻,今天决定自己分清楚这几个东西。

目录

  • Unity是如何实现跨平台的?
  • Mono介绍
  • IL2CPP介绍
  • Mono与IL2CPP的区别

一、Unity是如何实现跨平台的?

首先,什么是跨平台?

跨平台:一次编译,不需要任何代码修改,应用程序就可以运行在任意在平台上跑,即代码不依赖于操作系统,也不依赖硬件环境。

做游戏都知道,游戏肯定需要跨平台,不能只支持一种平台,不然每个对应的平台做出一种对应的编译器,那真的会累死。所以对于跨平台的需求,对于游戏开发而言,很重要。Unity的架构需求设计当然也需要这个特性。

至于Unity是如何实现跨平台的?这就得提到Unity脚本后处理(Scripting Backend)的两种方式Mono和IL2CPP。让我们来搞清楚这2个的区别。

二、Mono介绍

Mono是一个由 Xamarin公司所主持的自由开放源码项目。
Mono的目标是在尽可能多的平台上使.net标准的东西能正常运行的一套工具,核心在于“跨平台的让.net代码能运行起来“。
Mono组成组件:C# 编译器,CLI虚拟机,以及核心类别程序库。
Mono的编译器 负责生成符合公共语言规范的映射代码,即公共中间语言(Common Intermediate Language, CIL),我的理解就是工厂方法实现不同解析。
IL科普
IL的全称是 Intermediate Language,很多时候还会看到 CIL(特指在.Net平台下的IL标准)。翻译过来就是中间语言。
它是一种属于通用语言架构和.NET框架的低阶的人类可读的编程语言。
CIL类似一个面向对象的汇编语言,并且它是完全基于堆栈的,它运行在虚拟机上(.Net Framework, Mono VM)的语言。

2.1 工作流程:

  1. 通过C#编译器mcs,将C#编译为IL(中间语言,byte code)
  2. 通过Mono运行时中的编译器将IL编译成对应平台的原生码

2.2 知识点:

2.2.1. 编译器

C#编译器mcs:将C#编译为 IL
Mono Runtime编译器:将IL转移为 原生码

2.2.2. 三种转译方式:

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

2.2.3 Unity跨平台的原理

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

2.2.4 IOS不支持jit编译原因:

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

2.2.5 JIT编译

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

2.3 优点:

  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编译】

IL2CPP分为两个独立的部分:
1. AOT(静态编译)编译器:把IL中间语言转换成CPP文件
2. 运行时库:例如 垃圾回收、线程/文件获取(独立于平台,与平台无关)、内部调用直接修改托管数据结构的原生代码的服务与抽象

3.1 AOT编译器

IL2CPP AOT编译器名为il2cpp.exe。
在Windows上,您可以在 Editor \ Data \ il2cpp目录中找到它。
在OSX上,它位于Unity安装的 Contents / Frameworks / il2cpp / build目录中
il2cpp.exe 是由C#编写的受托管的可执行程序,它接受我们在Unity中通过Mono编译器生成的托管程序集,并生成指定平台下的C++代码。

IL2CPP工具链:

3.2 运行时库

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

3.3 为啥要转成CPP呢?

  1. 运行效率快
根据官方的实验数据,换成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可以做的很小并且使得游戏载入时间缩短

3.4 编译区别

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

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

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

3.5 优点

  1. 相比Mono, 代码生成有很大的提高
  2. 可以调试生成的C++代码
  3. 可以启用引擎代码剥离(Engine code stripping)来减少代码的大小
  4. 程序的运行效率比Mono高,运行速度快
  5. 多平台移植非常方便
  6. 相比Mono构建应用慢
  7. 只支持AOT(Ahead of Time)编译

四、Mono与IL2CPP的区别

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

参考:

Unity之IL2CPP_折羽-CSDN博客

Mono运行时总结_LMLBY的专栏-CSDN博客

Unity 与Mono和.Net的关系

Mono运行时总结

小玉:Unity将来时:IL2CPP是什么?

Unity官方博客:IL2CPP内部介绍

这篇关于【Unity游戏开发】Mono和IL2CPP的区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/277399

相关文章

关于Mybatis和JDBC的使用及区别

《关于Mybatis和JDBC的使用及区别》:本文主要介绍关于Mybatis和JDBC的使用及区别,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、JDBC1.1、流程1.2、优缺点2、MyBATis2.1、执行流程2.2、使用2.3、实现方式1、XML配置文件

一文教你如何解决Python开发总是import出错的问题

《一文教你如何解决Python开发总是import出错的问题》经常朋友碰到Python开发的过程中import包报错的问题,所以本文将和大家介绍一下可编辑安装(EditableInstall)模式,可... 目录摘要1. 可编辑安装(Editable Install)模式到底在解决什么问题?2. 原理3.

exfat和ntfs哪个好? U盘格式化选择NTFS与exFAT的详细区别对比

《exfat和ntfs哪个好?U盘格式化选择NTFS与exFAT的详细区别对比》exFAT和NTFS是两种常见的文件系统,它们各自具有独特的优势和适用场景,以下是关于exFAT和NTFS的详细对比... 无论你是刚入手了内置 SSD 还是便携式移动硬盘或 U 盘,都需要先将它格式化成电脑或设备能够识别的「文

什么是ReFS 文件系统? ntfs和refs的优缺点区别介绍

《什么是ReFS文件系统?ntfs和refs的优缺点区别介绍》最近有用户在Win11Insider的安装界面中发现,可以使用ReFS来格式化硬盘,这是不是意味着,ReFS有望在未来成为W... 数十年以来,Windows 系统一直将 NTFS 作为「内置硬盘」的默认文件系统。不过近些年来,微软还在研发一款名

Python+PyQt5开发一个Windows电脑启动项管理神器

《Python+PyQt5开发一个Windows电脑启动项管理神器》:本文主要介绍如何使用PyQt5开发一款颜值与功能并存的Windows启动项管理工具,不仅能查看/删除现有启动项,还能智能添加新... 目录开篇:为什么我们需要启动项管理工具功能全景图核心技术解析1. Windows注册表操作2. 启动文件

使用Python开发Markdown兼容公式格式转换工具

《使用Python开发Markdown兼容公式格式转换工具》在技术写作中我们经常遇到公式格式问题,例如MathML无法显示,LaTeX格式错乱等,所以本文我们将使用Python开发Markdown兼容... 目录一、工具背景二、环境配置(Windows 10/11)1. 创建conda环境2. 获取XSLT

Android开发环境配置避坑指南

《Android开发环境配置避坑指南》本文主要介绍了Android开发环境配置过程中遇到的问题及解决方案,包括VPN注意事项、工具版本统一、Gerrit邮箱配置、Git拉取和提交代码、MergevsR... 目录网络环境:VPN 注意事项工具版本统一:android Studio & JDKGerrit的邮

Python开发文字版随机事件游戏的项目实例

《Python开发文字版随机事件游戏的项目实例》随机事件游戏是一种通过生成不可预测的事件来增强游戏体验的类型,在这篇博文中,我们将使用Python开发一款文字版随机事件游戏,通过这个项目,读者不仅能够... 目录项目概述2.1 游戏概念2.2 游戏特色2.3 目标玩家群体技术选择与环境准备3.1 开发环境3

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

go 指针接收者和值接收者的区别小结

《go指针接收者和值接收者的区别小结》在Go语言中,值接收者和指针接收者是方法定义中的两种接收者类型,本文主要介绍了go指针接收者和值接收者的区别小结,文中通过示例代码介绍的非常详细,需要的朋友们下... 目录go 指针接收者和值接收者的区别易错点辨析go 指针接收者和值接收者的区别指针接收者和值接收者的