【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

相关文章

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模

Go之errors.New和fmt.Errorf 的区别小结

《Go之errors.New和fmt.Errorf的区别小结》本文主要介绍了Go之errors.New和fmt.Errorf的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考... 目录error的基本用法1. 获取错误信息2. 在条件判断中使用基本区别1.函数签名2.使用场景详细对

Redis中哨兵机制和集群的区别及说明

《Redis中哨兵机制和集群的区别及说明》Redis哨兵通过主从复制实现高可用,适用于中小规模数据;集群采用分布式分片,支持动态扩展,适合大规模数据,哨兵管理简单但扩展性弱,集群性能更强但架构复杂,根... 目录一、架构设计与节点角色1. 哨兵机制(Sentinel)2. 集群(Cluster)二、数据分片

基于Java开发一个极简版敏感词检测工具

《基于Java开发一个极简版敏感词检测工具》这篇文章主要为大家详细介绍了如何基于Java开发一个极简版敏感词检测工具,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起学习一下... 目录你是否还在为敏感词检测头疼一、极简版Java敏感词检测工具的3大核心优势1.1 优势1:DFA算法驱动,效率提升10

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

C#和Unity中的中介者模式使用方式

《C#和Unity中的中介者模式使用方式》中介者模式通过中介者封装对象交互,降低耦合度,集中控制逻辑,适用于复杂系统组件交互场景,C#中可用事件、委托或MediatR实现,提升可维护性与灵活性... 目录C#中的中介者模式详解一、中介者模式的基本概念1. 定义2. 组成要素3. 模式结构二、中介者模式的特点

一文带你迅速搞懂路由器/交换机/光猫三者概念区别

《一文带你迅速搞懂路由器/交换机/光猫三者概念区别》讨论网络设备时,常提及路由器、交换机及光猫等词汇,日常生活、工作中,这些设备至关重要,居家上网、企业内部沟通乃至互联网冲浪皆无法脱离其影响力,本文将... 当谈论网络设备时,我们常常会听到路由器、交换机和光猫这几个名词。它们是构建现代网络基础设施的关键组成

Python开发简易网络服务器的示例详解(新手入门)

《Python开发简易网络服务器的示例详解(新手入门)》网络服务器是互联网基础设施的核心组件,它本质上是一个持续运行的程序,负责监听特定端口,本文将使用Python开发一个简单的网络服务器,感兴趣的小... 目录网络服务器基础概念python内置服务器模块1. HTTP服务器模块2. Socket服务器模块