使用 R8 缩减和优化 Unity 代码

虽然 Unity 中的核心游戏逻辑是用 C# 编写的(使用 IL2CPP 编译),但 Android build 包含大量 Java 和 Kotlin 字节码 (classes.dex),用于处理 UnityPlayerActivity 生命周期事件、Google Play 服务、结算、广告和社交 SDK。

启用 R8(Android Gradle 插件 [AGP] 中的默认代码缩减器和优化器)可移除未使用的类和方法,并优化字节码。这不仅可以缩减应用下载大小,还可以减少内存映射 (mmap) DEX 页面和基准 Java 进程开销的运行时内存占用,从而缓解物理内存压力并减少低内存终止守护程序 (LMK) 终止。Google Play 还会通过 Android Vitals 中的 DEX 代码优化指标监控游戏的 DEX 优化级别。

默认行为和 Unity 版本支持

在 Unity 中,创建新项目时,发布 build 和调试 build 的代码缩减功能默认处于停用状态 (false)。

Unity 首次在 Unity 2020.1.0f1 中引入了 R8 作为可选切换开关。 从 Unity 2022.2.0f1(并向后移植到 Unity 2021.3.41f1 LTS)开始,Unity 将其捆绑的工具链升级到了 AGP 7.1.2+,移除了旧版 ProGuard 支持,并且只要启用了缩减大小功能,就会专门运行 R8。

Unity 版本 捆绑式 AGP 默认版本 R8 支持和所需配置
2019.4 LTS 及更早版本 早于 3.4 已停用 (false) 不支持(仅限旧版 ProGuard)。
2020.1.0f1 至 2021.3.40f1 3.4 到 4.0 已停用 (false) 可选(默认为 ProGuard)。同时启用 Minify > Release 和 Use R8。
2021.3.41f1 及更高版本 (2021 LTS) 7.1+ 已停用 (false) 仅限 R8。启用缩减大小 > 发布,以自动运行 R8。
2022.2.0f1 至 Unity 6+ 7.1 至 8.x 已停用 (false) 仅限 R8。启用缩减大小 > 发布,以自动运行 R8。

在 Player Settings 中启用 R8

如需为发布 build 启用 R8 代码缩减和优化功能,请执行以下操作:

  1. 在 Unity 编辑器中,依次打开 Edit(修改)> Project Settings(项目设置),然后选择 Player(播放器)。
  2. 选择 Android 标签页,然后展开发布设置 > 构建。
  3. 在 Minify 部分下,根据您的 Unity 版本配置选项:
    • Unity 2021.3.41f1+ 和 2022.2.0f1+:选择 Release。Unity 会在 minifyReleaseWithR8 Gradle 任务期间自动运行 R8。
    • Unity 2020.1.0f1 至 2021.3.40f1:同时选择 Release 和 Use R8。

如果您使用 C# 编辑器脚本自动执行 build,请通过 PlayerSettings.Android 配置这些属性:

using UnityEditor;

public static class AndroidBuildConfig
{
    public static void EnableR8ForRelease()
    {
        PlayerSettings.Android.minifyRelease = true;

        // Required only in Unity 2020.1.0f1 to 2021.3.40f1 and 2022.1 or earlier
        // (In Unity 2021.3.41f1+ and 2022.2+, R8 is always used when minification is enabled)
#if !UNITY_2022_2_OR_NEWER
        PlayerSettings.Android.minifyWithR8 = true;
#endif
    }
}

为 JNI 和反射添加保留规则

使用 AndroidJavaClass 或 AndroidJavaObject 从 C# 脚本动态调用的 Java 类和方法没有静态 Java 调用网站。如果没有明确的保留规则,R8 可能会认为这些类未被使用,并将其剥离或重命名。

如需保留自定义 Java 桥,请执行以下操作:

  1. 在 Project Settings(项目设置)> Player(可执行游戏文件)> Android > Publishing Settings(发布设置)> Build(构建)中,启用 Custom Proguard File(自定义 Proguard 文件)。
  2. 打开生成的 Assets/Plugins/Android/proguard-user.txt 文件。
  3. 为通过 JNI 访问的类或第三方插件所需的类添加 -keep 规则:
# Keep custom Java classes invoked from C# using JNI bridges
-keep class com.example.yourgame.** { *; }

# Keep callback interfaces passed between C# and Java
-keep interface com.example.yourgame.IPluginCallback { *; }

排查常见问题

本部分介绍了如何解决在 Unity 中使用 R8 时遇到的常见构建和运行时问题。

Missing classes detected while running R8 个构建错误

在使用 AGP 7.0 及更高版本(2021.3.41f1+ 和 2022.2+)的 Unity 版本中,R8 会强制执行严格的缺失类检查。如果 build 失败并显示此错误,请检查 build 输出目录(位于 Library/Bee/Android/Prj/.../build/outputs/mapping/release/missing_rules.txt 或 Temp/gradleOut/... 下)中生成的 missing_rules.txt 文件,并将所需的依赖项或规则添加到 proguard-user.txt。如需详细了解如何编写保留规则,请参阅自定义要保留的代码。

R8 完整模式与第三方插件的兼容性

在 AGP 8.0 及更高版本 (Unity 6+) 中,R8 完整模式默认处于启用状态,以执行更积极的优化。如果旧版 Android 插件在运行时因反射问题而失败,请更新插件的 ProGuard 规则或将 R8 还原为兼容模式:

  1. 在 Publishing Settings(发布设置)> Build(构建)中,启用 Custom Gradle Properties Template。
  2. 打开 Assets/Plugins/Android/gradleTemplate.properties 并添加以下属性:
android.enableR8.fullMode=false