Unity的IL2CPP

news2024/11/25 12:52:19

目录

背景

概念

AOT编译器

运行时库

对比

Mono

IL2CPP

IL2CPP打包注意事项

类型裁剪

泛型实例

泛型方法


背景

在Unity4.6.1 p5以后版本中,在PlayerSettings—>Other Settings—>Scripting Backend有mono和il2cpp两个选项,它们是Unity脚本后处理(Scripting Backend)的两种方式。

概念

IL2CPP 是 Unity一种新的脚本后处理(Scripting Backend)方式,针对.Net平台编译输出的IL(中间语言-Intermediate Language)进行处理。

IL2CPP主要由两部分组成:

1,AOT静态编译编译器(il2cpp.exe)

预先编译(译注:ahead-of-time,又叫AOT)

2,运行时库(libil2cpp)

其中AOT将IL转换为C++源码,再交给各平台的C++编译器进行编译,达到平台兼容的目的;运行时库则会提供诸如垃圾回收、线程/文件获取、内部调用直接修改托管数据结构的原生代的服务与抽象。

https://img-blog.csdnimg.cn/img_convert/f6dd5495c7cbd2ac2ef03db30970f8dc.webp?x-oss-process=image/format,png

AOT编译器

IL2CPP AOT编译器实际的执行文件是il2cpp.exe。在Windows平台你可以在Unity安装路径的EditorDatail2cpp目录下找到。对于OSX平台,它位于Unity安装路径的Contents/Frameworks/il2cpp/build目录内。 il2cpp.exe这个工具是一个托管代码可执行文件,其完全由C#写成。在开发IL2CPP的过程中,我们同时使用.NET和Mono编译器对其进行编译。

il2cpp 接受来自Unity自带的或者由Mono编译器产生的托管程序集,将这些程序集转换成C++代码。这些转换出的C++代码最终由部署目标平台上的C++编译器进行编译。

你可以参照下图理解IL2CPP工具链的作用:

https://img-blog.csdnimg.cn/b4ba7b1787d14e2eab037690b6da1f9e.png 

运行时库

IL2CPP的另外一个部分就是对虚拟机提供支持的运行时库。我们基本上是用C++代码来实现整个运行时库的(好吧,其实里面还是有一些和平台相关的代码使用了程序集,这个只要你知我知便好,不要告诉别人 )。我们把运行时库称之为libli2cpp,它是作为一个静态库被连接到最终的游戏可执行文件中。这么做的一个主要的好处是可以使得整个IL2CPP技术是简单并且是可移植的。

你能通过查看随Unity一起发布的libil2cpp头文件来窥探其代码组织方式(Windows平台,头文件在EditorDataPlaybackEngineswebglsupportBuildToolsLibrarieslibil2cppinclude目录中。OSX平台,头文件在Contents/Frameworks/il2cpp/libil2cpp目录中)。举个例子,由il2cpp产生的C++代码和libil2cpp之间的接口API,存在于codegen/il2cpp-codegen.h这个文件中。

运行时的另外一个重要的部分,就是垃圾收集器。在Unity 5中,我们使用libgc垃圾收集器。它是一个典型的贝姆垃圾收集器(Boehm-Demers-Weiser garbage collector)。(译注:相对使用保守垃圾回收策略)。然而我们的libil2cpp被设计成可以方便使用其他垃圾回收器。

 

对比

Mono

  • 构建应用非常快。
  • 由于Mono的JIT(Just In Time compilation)机制,所以支持更多托管类库。
  • 支持运行时代码执行。
  • 必须将代码发布成托管程序集(.dll文件,由mono或者.net生成)。
  • Mono VM在各个平台移植异常麻烦,有几个平台就得移植几个VM(WebGL和UWP这两个平台只支持 IL2CPP)。
  • Mono版本授权受限,C#很多新特性无法使用。
  • iOS仍然支持Mono,但是不再允许Mono(32位)应用提交到Apple Store。

https://img-blog.csdnimg.cn/img_convert/b0c6dba4c014d720d00bfb88f21f3e85.png

IL2CPP

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

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

https://img-blog.csdnimg.cn/img_convert/e9d6a3d5f75f99527e57f0428b5d138c.webp?x-oss-process=image/format,png

IL2CPP打包注意事项

由于IL2CPP的运行效率的大幅度优势,我们在实际项目中几乎都是直接使用IL2CPP的,在打包过程中可能会遇到一些问题。

IL2CPP和mono的最大区别就是不能在运行时动态生成代码和类型,所以这就要求必须在编译时就完全确定需要用到的类型。

类型裁剪

IL2CPP在打包时会自动对Unity工程的DLL进行裁剪,将代码中没有引用到的类型裁剪掉,以达到减小发布后ipa包的尺寸的目的。然而在实际使用过程中,很多类型有可能会被意外剪裁掉,造成运行时抛出找不到某个类型的异常。特别是通过反射等方式在编译时无法得知的函数调用,在运行时都很有可能遇到问题。

Unity提供了一个方式来告诉Unity引擎,哪些类型是不能够被剪裁掉的。具体做法就是在Unity工程的Assets目录中建立一个叫link.xml的XML文件,然后按照下面的格式指定你需要保留的类型:

<linker>

  <assembly fullname="UnityEngine" preserve="all"/>

  <assembly fullname="Assembly-CSharp">

    <namespace fullname="MyGame.Utils" preserve="all"/>

    <type fullname="MyGame.SomeClass" preserve="all"/>

  </assembly> 

</linker>

泛型实例

每个泛型实例实际上都是一个独立的类型,List<A>和 List<B>是两个完全没有关系的类型,这意味着,如果在运行时无法通过JIT来创建新类型的话,代码中没有直接使用过的泛型实例都会在运行时出现问题。

这个问题有两种方式,一个是使用CLR绑定,把用到的泛型实例都进行CLR绑定。另外一个方式是在Unity主工程中,建立一个类,然后在里面定义用到的那些泛型实例的public变量。这两种方式都可以告诉IL2CPP保留这个类型的代码供运行中使用。

泛型方法

跟泛型实例一样,foo.Bar<TypeA>和foo.Bar<TypeB>是两个完全不同的方法,需要在主工程中显式调用过,IL2CPP才能够完整保留,因此需要尽量避免在热更DLL中调用Unity主工程的泛型方法。如果在iOS上实际运行遇到报错,可以尝试在Unity的主工程中随便写一个static的方法,然后对这个泛型方法调用一下即可,这个方法无需被调用,只是用来告诉IL2CPP我们需要这个方法。

参考资料:

Unity之IL2CPP - 知乎

用Unity做游戏,你需要深入了解一下IL2CPP

【Unity3D字节跳动面试题】Unity底层如何处理C#_哔哩哔哩_bilibili

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/663045.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

面试阿里,嫌弃面试官装逼当场怒怼,“把我的简历还给我”,疑似被拉黑

好家伙&#xff0c;这奇葩事可真是多&#xff0c;前两天和粉丝聊天&#xff0c;他说前段时间面试阿里的测试岗&#xff0c;最后和面试官干起来了。 我问他为什么&#xff0c;他说没啥&#xff0c;就觉得面试官太装B了&#xff0c;就爱问一些虚而不实的东西&#xff0c;显得自己…

Web自动化中常用的跳过验证码操作

目录 前言 通过cookies值登录 通OCR识别验证码 总结 前言 自动化测试中经常需要避免手动输入验证码的操作&#xff0c;因为这会增加测试成本&#xff0c;耗费测试人员的时间。通过自动化程序跳过验证码&#xff0c;可以减少测试时间&#xff0c;提高测试效率。 安静今天通过几个…

增值税高企业发展受限怎么办?采用此方法可化险为夷!

增值税高企业发展受限怎么办&#xff1f;采用此方法可化险为夷&#xff01; 《税筹顾问》专注于园区招商&#xff0c;您的贴身节税小能手&#xff0c;合理合规节税 企业的发展&#xff0c;一方面需要依靠自身的生产经营&#xff0c;那么另一方面就需要在一些支出上尽可能的开源…

如何用 Python 给树莓派 Pico RP2040 编程

使用 MicroPython&#xff0c;仅用 8 行代码&#xff0c;我们就可以实现 LED 闪烁程序。 下载安装 Python IDE&#xff1a;Thonny Thonny 是 一个面向初学者的 Python IDE 环境&#xff0c;自带 Python&#xff0c;相对简单&#xff0c;比较容易上手。对于树莓派 Pico 开发&am…

实验篇(7.2) 12. 站对站安全隧道 - 仅一方发起连接(FortiGate-IPsec) ❀ 远程访问

【简介】上一篇实验发现&#xff0c;两端都是可以远程的公网IP的话&#xff0c;两端防火墙都可以发出连接请求&#xff0c;并且都能够连通。这样的好处是安全隧道不用随时在线&#xff0c;只在有需求时才由发起方进行连接。但是现实中很多情况下只有一端公网IP可以远程&#xf…

实战:求年月日时间前后遇到的坑和解决方式

这里写目录标题 前言正确实例&#xff1a;错误实例&#xff1a; 需求 前言 这周接到一个时间转换任务需要处理&#xff0c;本来没什么问题&#xff0c;后来完成后发现时间有偏差&#xff0c;又重写了一遍代码&#xff0c;感觉很有记录必要性&#xff0c;希望看过的小伙伴可以避…

代理ip会不会影响网络速度和稳定性

代理ip是一种可以帮助用户隐藏真实IP地址的技术&#xff0c;通常使用代理服务器作为中介来连接互联网。代理ip在网络安全、隐私保护、跨区域访问等方面都有广泛的应用。但是&#xff0c;使用 代理ip是否会影响网络速度和稳定性这一问题也一直备受关注。下面是一些有关代理ip对网…

k8s部署redis集群

写在前面 一般来说&#xff0c;REDIS部署有三种模式。 单实例模式&#xff0c;一般用于测试环境。哨兵模式集群模式 后两者用于生产部署 哨兵模式 在redis3.0以前&#xff0c;要实现集群一般是借助哨兵sentinel工具来监控master节点的状态。 如果master节点异常&#xff0c…

计算机网络管理-网络管理软件SNMPc软件的下载,安装和使用教程说明

⬜⬜⬜ &#x1f430;&#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea;(*^▽^*)欢迎光临 &#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea;&#x1f430;⬜⬜⬜ ✏️write in front✏️ &#x1f4dd;个人主页&#xff1a;陈丹宇jmu &am…

树莓派4B移植5G模块驱动(RG200U-CN)

1、查看Linux内核版本 uname -r2、根据内核版本在Github上下载Linux内核源码&#xff08;最好再Github上确定一下有没有这个分支&#xff09; git clone --depth1 https://github.com/raspberrypi/linux --branch rpi-5.15.y3、下载依赖库 $ sudo apt update$ sudo apt inst…

【白话机器学习系列】白话 Dropout

白话 Dropout 文章目录 什么是Dropout理解缩放举个例子 什么是Dropout Dropout 是神经网络的一种正则化技术&#xff0c;它在训练时以指定的概率 p p p&#xff08;常见值为 p 0.5 p0.5 p0.5&#xff09;丢弃一个单元&#xff08;连同连接&#xff09;。在测试时&#xff…

【JUC并发编程】

本笔记内容为狂神说JUC并发编程部分 目录 一、什么是JUC 二、线程和进程 1、概述 2、并发、并行 3、线程有几个状态 4、wait/sleep 区别 三、Lock锁&#xff08;重点&#xff09; 四、生产者和消费者问题 五、八锁现象 六、集合类不安全 七、Callable ( 简单 )…

windows10企业版安装西门子博途V15---03安装仿真软件

1、选点这个 2、进入03.SIMATIC_PLCSIM_Advanced_V3&#xff0c;这个是什么东西&#xff0c;它就是真实的硬件设备的仿真软件&#xff0c;也就是说&#xff0c;现在没有真正的PLC硬件&#xff0c;PLC是这样的东西&#xff0c;它是一个硬件产品&#xff0c;而现在不可能去买个硬…

TRUNCATE 语句到底因何而慢?

作者通过源码分析 truncate 语句形成慢 SQL 的原因和解决方案&#xff0c;并与 MySQL 5.7就相关实现逻辑进行对比。 问题现象 收到反馈某测试环境执行批量操作时&#xff0c;有 truncate 语句存在于慢查询日志中。担心上线后可能影响数据库&#xff0c;请求 DBA 配合分析。 …

第八章 模型篇:transfer learning for computer vision

参考教程&#xff1a; transfer-learning transfer-learning tutorial 文章目录 transfer learning对卷积网络进行finetune把卷积网络作为特征提取器何时、如何进行fine tune 代码示例加载数据集构建模型fine-tune 模型模型作为feature extractor 定义train_loop和test_loop定…

【K8S系列】如何高效查看 k8s日志

序言 你只管努力&#xff0c;其他交给时间&#xff0c;时间会证明一切。 文章标记颜色说明&#xff1a; 黄色&#xff1a;重要标题红色&#xff1a;用来标记结论绿色&#xff1a;用来标记一级论点蓝色&#xff1a;用来标记二级论点 Kubernetes (k8s) 是一个容器编排平台&#x…

【C#每日一记】多线程实现的贪吃蛇原理—不允许你还不知道

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…

软件测试技能,JMeter压力测试教程(一)

目录 前言 一、安装Java环境 二、安装JMeter环境 三、启动JMeter脚本测试 四、查看报告文件 前言 使用jmeter做压测的时候&#xff0c;在windows上不太稳定&#xff0c;所有一直在 Linux 服务器上使用 jmeter 做压力测试 本篇记录下 Linux上搭建 jmeter 环境&#xff0c…

分布式学习第二天 redis学习

目录 1. 数据库类型 1.1 基本概念 1.2 关系/非关系型数据库搭配使用 2. Redis 2.1 基本知识点 2.2 redis常用命令 2.4 redis数据持久化 3 hiredis的使用 4. 复习 1. 数据库类型 1.1 基本概念 关系型数据库 - sql 操作数据必须要使用sql语句 数据存储在磁盘 存储的…

如何使用CDN给OSS做加速详解

意义 用户直接访问OSS资源&#xff0c;速度会受到OSS下行带宽以及Bucket地域的限制&#xff0c;若通过CDNOSS的方式进行访问&#xff0c;带宽上限更高&#xff0c;并且可以将OSS的资源缓存至就近的CDN节点&#xff0c;通过CDN节点进行分发&#xff0c;可以缩短网络传输距离&am…