5.9 KiB
#unity/日常积累
在 Unity 中,AOT(Ahead-of-Time)编译是一种将 C# 代码在运行时之前编译为机器代码的技术。AOT 编译通常与 IL2CPP(Intermediate Language to C++)相关联,是 Unity 中的一种编译模式,尤其在 iOS 和其他一些平台上使用。
AOT 编译的主要目的是提高性能和缩短启动时间。通过将 C# 代码在应用构建时预先编译成本地代码,Unity 可以避免在运行时进行 JIT(Just-In-Time)编译,进而提高游戏或应用的性能和稳定性。
AOT 编译的基本概念:
- IL2CPP:IL2CPP 是 Unity 提供的一种技术,它将 C# 程序的中间语言(IL,Intermediate Language)转换为 C++,然后再通过 C++ 编译器编译为平台特定的本地代码。IL2CPP 是 Unity 中 AOT 编译的核心技术。
- JIT 编译:与 AOT 编译相反,JIT 编译是在应用程序运行时,将中间语言代码动态编译为机器代码。这种方式通常会增加启动时间,并消耗更多的系统资源。
使用 AOT 编译的优点:
-
性能提升:
- AOT 编译生成的本地代码在运行时执行得更快,因为不需要执行中间代码的编译。
- 对于内存有限的设备(如移动设备),AOT 编译有助于减少运行时的内存使用。
-
提高稳定性:
- AOT 编译能有效避免由于 JIT 编译引发的运行时错误(如 JIT 编译器的不稳定性)。
- 对于 iOS 和一些控制严格的平台(如 WiiU、PlayStation 等),Apple 和其他平台厂商要求应用使用 AOT 编译以确保安全性和稳定性。
-
减少启动时间:
- 由于在构建时就已经完成了编译过程,应用程序的启动时间通常较短,因为它不需要在第一次运行时编译代码。
-
适应更多平台:
- 一些平台(如 iOS)不允许使用 JIT 编译,而必须使用 AOT 编译,这使得 AOT 编译成为支持这些平台的必需选项。
Unity 中启用 AOT 编译:
Unity 默认在某些平台(如 iOS)上使用 AOT 编译。例如,在 iOS 构建时,Unity 会强制使用 IL2CPP 并生成 AOT 代码。对于其他平台,AOT 编译通常用于 IL2CPP 后端,而使用 Mono 后端的项目则依赖于 JIT 编译。
1. iOS AOT 编译:
iOS 平台是最常见的 AOT 编译使用场景,因为 iOS 不允许使用 JIT 编译。在 iOS 构建中,Unity 会使用 IL2CPP 进行 AOT 编译。构建过程中,Unity 会将 C# 代码转换为 C++,然后再编译为适合 iOS 的本地代码。
设置 iOS AOT 编译:
- 在 Unity 中,选择 File > Build Settings,然后选择 iOS。
- 在 Player Settings 中,确保设置为使用 IL2CPP 作为脚本后端:
Scripting Backend
设置为 IL2CPP。Architecture
设置为 ARM64(苹果设备要求使用 64 位架构)。
2. 安卓 AOT 编译:
对于 Android 平台,Unity 允许选择使用 AOT 编译(IL2CPP)或者 JIT 编译(Mono)。默认情况下,使用 Mono 时是 JIT 编译,使用 IL2CPP 时会启用 AOT 编译。
设置 Android AOT 编译:
- 在 Player Settings 中,将
Scripting Backend
设置为 IL2CPP。 - 如果希望启用 AOT,可以选择优化选项来缩减最终构建大小或增强性能。
3. 其他平台:
在一些支持 IL2CPP 的平台(如 WebGL、Windows、Linux 和 macOS)上,Unity 也可以选择使用 AOT 编译。你可以通过选择 IL2CPP 作为 Scripting Backend 来启用 AOT 编译。
如何优化 AOT 编译:
-
预生成 AOT 代码:
- 在 Unity 中,你可以使用
AOT
编译时生成的代码来优化构建的大小和运行时性能。你可以通过为 AOT 编译添加 AOT 预编译,优化代码的生成。
- 在 Unity 中,你可以使用
-
去除未使用的代码:
- 使用 Managed Stripping Level 或 Linking 设置来剔除未使用的代码。这样可以减小 AOT 编译后的代码体积。
-
合理利用程序集:
- 将项目分成多个程序集,并优化每个程序集的 AOT 编译部分。只编译你需要的代码和资源,减少不必要的构建时间。
AOT 编译与 IL2CPP
- IL2CPP(Intermediate Language to C++)是 Unity 推出的 C# 到 C++ 的编译后端。它通过将中间语言(C#)编译成 C++ 代码,再编译为平台特定的二进制代码,从而避免了 JIT 编译。
- 由于 AOT 编译的执行模式不同,IL2CPP 生成的二进制文件通常比传统的 Mono 编译文件大,但它也提供了更好的性能和跨平台支持,尤其在 iOS 等平台上是必需的。
AOT 编译中的限制:
-
不支持反射:
- AOT 编译限制了反射的使用,因为反射通常在运行时动态解析类型,这与 AOT 编译的预编译模式不兼容。
- Unity 提供了
AOT
编译时的反射解决方案,可以通过 Link.xml 文件来告诉 Unity 保留特定类型或成员,避免因 AOT 编译导致的运行时错误。
-
代码大小:
- AOT 编译的代码通常比 JIT 编译的代码要大,这可能导致构建文件的体积增大。
- 你需要确保通过优化和去除未使用的代码来减小最终构建的大小。
-
构建时间:
- AOT 编译可能会导致较长的构建时间,尤其是在大型项目中,因为所有代码都需要提前编译为本地代码。
总结:
AOT 编译是 Unity 中提升应用性能和稳定性的关键技术之一,尤其适用于需要严格性能和安全要求的平台(如 iOS)。它通过将 C# 代码预先编译成本地机器代码,避免了运行时的 JIT 编译,能够显著提高运行时性能并减少启动时间。Unity 支持通过 IL2CPP 后端来进行 AOT 编译,而不同平台的 AOT 编译设置略有不同,需要根据平台需求进行配置和优化。