简体   繁体   English

如何在Android Player设置Unity中使用剥离级别/ IL2CPP选项

[英]How to use Stripping Level / IL2CPP option in Android Player settings Unity

I am trying to reduce size of APK built from Unity. 我正在尝试减少从Unity构建的APK的大小。 Looking at Android Player Settings docs , I fugured out that I can use one of following options to reduce size of build: 看看Android Player设置文档 ,我发现我可以使用以下选项之一来减少构建的大小:

Stripping Levels: 剥离级别:

  1. Strip Assemblies 带组件
  2. Strip ByteCode (iOS only) Strip ByteCode(仅限iOS)
  3. Use micro mscorlib 使用micro mscorlib
  4. Strip Engine Code (only available when using IL2CPP) 剥离引擎代码(仅在使用IL2CPP时可用)

I have following questions regarding this: 我有以下问题:

In IOS Build Size Optimization it says: IOS Build Size Optimization中,它说:

Strip assemblies level : the scripts' bytecode is analyzed so that classes and methods that are not referenced from the scripts can be removed from the DLLs and thereby excluded from the AOT compilation phase. 剥离程序集级别 :分析脚本的字节代码,以便可以从DLL中删除未从脚本引用的类和方法,从而将其排除在AOT编译阶段之外。 This optimization reduces the size of the main binary and accompanying DLLs and is safe as long as no reflection is used . 这种优化减少了主二进制文件和附带的DLL的大小, 只要不使用反射就是安全的

Does it apply on android as well? 它也适用于Android吗?

If thats the case, I tried to find referrences of System.Reflection in the whole project (including 3rd party plugins). 如果是这样,我试图在整个项目中找到System.Reflection引用(包括第三方插件)。 I could only see usage of reflection in Edior scripts or script under #if UNITY_EDITOR . 我只能在#if UNITY_EDITOR下的Edior脚本或脚本中看到反射的用法。 How can I make sure that stripping won't cause any problem in android build? 如何确保剥离不会导致android构建中出现任何问题?

Is stripping applied on 3rd party .dll code which is not accessible in Visual Studio/ MonoDevelop? 剥离应用于Visual Studio / MonoDevelop中无法访问的第三方.dll代码吗?

Does usage of IL2CPP or stripping level affect performance of the app in any way? IL2CPP或剥离级别的使用是否会以任何方式影响应用程序的性能?

UPDATE: 更新:

I tried IL2CPP in android project and it added aprox 10MB to build size and took ages to build as well. 我在android项目中尝试了IL2CPP,它增加了10MB的aprox来构建大小并且花了很长时间来构建。

Thanks 谢谢

Yes, the iOS Build Size Optimization information about stripping does apply to Android as well. 是的,关于剥离的iOS Build Size Optimization信息也适用于Android。 There are some trade-offs here that you should be aware of. 这里有一些你需要注意的权衡取舍。

TL;DR: If you are optimizing for build size only , then using Mono with "Strip Assemblies" is the best option. TL; DR:如果你优化构建尺寸,然后用单声道与“地带大会”是最好的选择。

Compilation options 编译选项

Of course, there are some subtle issues that might matter for your case. 当然,有一些微妙的问题可能对您的情况很重要。 For Android, Unity offers two different compilation modes. 对于Android,Unity提供两种不同的编译模式。

  1. Just-in-time (JIT) compilation 即时(JIT)编译
  2. Ahead-of-time (AOT) compilation 提前(AOT)编译

JIT compilation happens with the Mono scripting backend. JIT编译发生在Mono脚本后端。 The managed code in your project is compiled to IL byte code and shipped to the end user as IL assemblies. 项目中的托管代码被编译为IL字节代码,并作为IL程序集发送给最终用户。 The IL assemblies are compiled to native machine code on the user's device. IL程序集被编译为用户设备上的本机机器代码。

AOT compilation happens with the IL2CPP scripting backend. AOT编译与IL2CPP脚本后端一起发生。 The managed code in your project is compiled to IL byte code, then translated to C++ code, then compiled on your machine to native machine code. 项目中的托管代码编译为IL字节代码,然后转换为C ++代码,然后在您的机器上编译为本机代码。 That native machine code is shipped to the end user and run on the user's device. 该本机代码将发送给最终用户并在用户的设备上运行。

In almost all cases, the IL byte code is a more compact representation than the native machine code, so the APK size with the Mono scripting backend will be smaller. 在几乎所有情况下,IL字节代码都比本机代码更紧凑,因此使用Mono脚本后端的APK大小会更小。

Also, the Mono scripting backend does less work on your machine during the build process, so the project build will be faster. 此外,Mono脚本后端在构建过程中对您的计算机执行的工作较少,因此项目构建将更快。

Finally, the IL2CPP scripting backend builds two native binaries by default, one for armv7, and one for x86. 最后,IL2CPP脚本后端默认构建两个本机二进制文件,一个用于armv7,另一个用于x86。 You can change the player settings to build only one of them (armv7, likely) if you don't need to support x86. 如果您不需要支持x86,则可以更改播放器设置以仅构建其中一个(可能是armv7)。

Stripping options 剥离选项

Unity does two different types of stripping: Unity执行两种不同类型的剥离:

  1. Managed code stripping 托管代码剥离
  2. Engine code stripping 引擎代码剥离

Managed code stripping is performed on the managed assemblies after the managed compilers run, but before any code is packaged in the APK. 在托管编译器运行之后,但在将任何代码打包到APK之前,在托管程序集上执行托管代码剥离 This process uses a known set of roots (like any classes deriving from MonoBehaviour in your project) and builds a dependency graph of all code that can be provably called. 此过程使用一组已知的根(如项目中从MonoBehaviour派生的任何类),并构建可以被证明调用的所有代码的依赖关系图。 Any IL code that cannot be provably called will be removed from the IL assembly, and will not be part of the APK. 任何无法被证明调用的IL代码都将从IL程序集中删除,并且不会成为APK的一部分。

Is stripping applied on 3rd party .dll code which is not accessible in Visual Studio/ MonoDevelop? 剥离应用于Visual Studio / MonoDevelop中无法访问的第三方.dll代码吗?

This process is applied to all managed assemblies (.dll files) in the project. 此过程适用于项目中的所有托管程序集(.dll文件)。

Engine code stripping causes subsystems in the native engine code to be removed by the native linker at the end of the project build process. 引擎代码剥离导致本机引擎代码中的子系统在项目构建过程结束时由本机链接器删除。 For example, if engine code stripping is enabled, and your project does not use any 3D physics features, the 3D physics system should not be included in the final APK. 例如,如果启用了引擎代码剥离,并且您的项目不使用任何3D物理特性,则3D物理系统不应包含在最终的APK中。

Compilation and stripping 编译和剥离

The compilation and stripping options intersect like this: 编译和剥离选项交叉如下:

  • Mono scripting backend 单声道脚本后端
    • Default is no managed or engine code stripping 默认是没有托管或引擎代码剥离
    • Strip Assemblies causes managed code stripping and engine code stripping to be enabled. Strip Assemblies导致托管代码剥离和启用引擎代码剥离。
  • IL2CPP scripting backend IL2CPP脚本后端
    • Managed code stripping is always enabled. 始终启用托管代码剥离。
    • Engine codes stripping is optional. 发动机代码剥离是可选的。

Compilation, stripping, and reflection 编译,剥离和反思

Since the IL2CPP scripting backend is AOT-only, the System.Reflection.Emit namespace is not supported. 由于IL2CPP脚本后端仅为AOT,因此不支持System.Reflection.Emit命名空间。 Any calls into it will throw a NotSupportedException at runtime. 对它的任何调用都会在运行时抛出NotSupportedException

Mono does support the System.Reflection.Emit namespace, but you must be careful about using it and the System.Reflection namespace with managed code stripping enabled. Mono确实支持System.Reflection.Emit命名空间,但是必须小心使用它和启用了托管代码剥离的System.Reflection命名空间。 Since the managed code stripper cannot statically prove code that is only accessed be reflection is used, the stripper will remove that code. 由于托管代码剥离器无法静态证明只能访问的代码是使用反射,因此剥离器将删除该代码。

How can I make sure that stripping won't cause any problem in android build? 如何确保剥离不会导致android构建中出现任何问题?

The only good way to know this is with runtime testing. 了解这一点的唯一好方法是运行时测试。 There is no way to be sure, prior to runtime, that the stripper won't be too aggressive and remove code. 在运行之前,无法确定剥离器是否过于激进并删除代码。

Since you have inspected the code in your project, you can be relatively confident, but there is not a way to prove things will work without exercising all of the code paths in the project. 由于您已经检查了项目中的代码,因此您可以相对自信,但如果不运行项目中的所有代码路径,就无法证明事情是否有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM