目录
背景
概念
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++编译器进行编译,达到平台兼容的目的;运行时库则会提供诸如垃圾回收、线程/文件获取、内部调用直接修改托管数据结构的原生代的服务与抽象。
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工具链的作用:
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,代码生成有很大的提高。
由于IL2CPP的运行效率的大幅度优势,我们在实际项目中几乎都是直接使用IL2CPP的,在打包过程中可能会遇到一些问题。
IL2CPP和mono的最大区别就是不能在运行时动态生成代码和类型,所以这就要求必须在编译时就完全确定需要用到的类型。
IL2CPP在打包时会自动对Unity工程的DLL进行裁剪,将代码中没有引用到的类型裁剪掉,以达到减小发布后ipa包的尺寸的目的。然而在实际使用过程中,很多类型有可能会被意外剪裁掉,造成运行时抛出找不到某个类型的异常。特别是通过反射等方式在编译时无法得知的函数调用,在运行时都很有可能遇到问题。
Unity提供了一个方式来告诉Unity引擎,哪些类型是不能够被剪裁掉的。具体做法就是在Unity工程的Assets目录中建立一个叫link.xml的XML文件,然后按照下面的格式指定你需要保留的类型:
每个泛型实例实际上都是一个独立的类型,List和 List是两个完全没有关系的类型,这意味着,如果在运行时无法通过JIT来创建新类型的话,代码中没有直接使用过的泛型实例都会在运行时出现问题。
这个问题有两种方式,一个是使用CLR绑定,把用到的泛型实例都进行CLR绑定。另外一个方式是在Unity主工程中,建立一个类,然后在里面定义用到的那些泛型实例的public变量。这两种方式都可以告诉IL2CPP保留这个类型的代码供运行中使用。
跟泛型实例一样,foo.Bar
参考资料:
Unity之IL2CPP - 知乎
用Unity做游戏,你需要深入了解一下IL2CPP
【Unity3D字节跳动面试题】Unity底层如何处理C#_哔哩哔哩_bilibili