Как сжать и оптимизировать код Unreal Engine с помощью R8

Хотя основная логика игры в Unreal Engine написана на C++ или Blueprints, при упаковке для Android компилируется байт-код Java и Kotlin (classes.dex), чтобы обрабатывать события жизненного цикла GameActivity, сервисы Google Play, платежи, аудио и плагины аналитики.

R8 – это инструмент для сжатия и оптимизации кода, который по умолчанию используется в плагине Android Gradle (AGP). Он удаляет неиспользуемые классы и методы, а также оптимизирует байт-код. Это не только уменьшает размер скачиваемого пакета, но и снижает объем потребляемой памяти для страниц DEX, сопоставленных с памятью (mmap), и базовых процессов Java. В результате снижается нагрузка на физическую память и реже происходит принудительное завершение работы из-за нехватки памяти. Google Play также отслеживает уровень оптимизации DEX-файлов игры с помощью показателя Оптимизация DEX-кода в Android Vitals.

Режим работы по умолчанию и поддержка версий Unreal Engine

Начиная с версии UE 4.22.0, UEDeployAndroid.cs Unreal Engine по умолчанию добавляет minifyEnabled true в сгенерированную конфигурацию сборки Android Release (buildAdditions.gradle). Поскольку в UE 4.25 набор инструментов был обновлен до AGP 4.0.0, R8 по умолчанию включен (true) во всех сборках Release (Shipping и Distribution) в UE 4.25 и более поздних версиях без дополнительной настройки.

Версия Unreal Engine Пакетный AGP Выпуск по умолчанию Отладка по умолчанию Поведение
UE 4.21 и более ранние версии Устаревшие версии Gradle или Ant Отключено (false) Отключено (false) Система не добавила конфигурацию minifyEnabled.
UE 4.22–4.24 Ранние версии (до 3.4) Включено (ProGuard) Отключено (false) minifyEnabled true включен по умолчанию в конечных сборках (запускает ProGuard).
UE 4.25–5.3 4.0.0 Включено (R8) Отключено (false) В AGP 4.0 R8 используется по умолчанию в конечных сборках.
UE 5.4–5.7 7.4.2 Включено (R8) Отключено (false) В AGP 7.x удалены устаревшие параметры useProguard, и R8 запускается в эксклюзивном режиме.
UE 5.8 (5.8.3+) 8.13.0 Включено (R8) Отключено (false) По умолчанию использует AGP 8.x и современные конвейеры оптимизации R8.

Различия между рабочей и отладочной сборками

UnrealBuildTool (UEDeployAndroid.cs) по-разному настраивает сгенерированный файл buildAdditions.gradle для релизных и отладочных сборок:

buildTypes {
    release {
        signingConfig signingConfigs.release
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
    debug {
        debuggable true
        signingConfig signingConfigs.debug
    }
}
  • Релиз (доставка или распространение). По умолчанию задает minifyEnabled true и применяет proguard-rules.pro, выполняя сжатие и обфускацию кода R8.
  • Отладка (разработка). Включает debuggable true и пропускает minifyEnabled (по умолчанию false), чтобы сохранить быструю итерацию сборки и отладку символов.

Добавьте правила сохранения с помощью Unreal Plugin Language (UPL)

Поскольку R8 автоматически запускается для конечных сборок в UE 4.25 и более поздних версиях, необходимо сохранить классы Java, доступные только через C++ JNI (JNIEnv->FindClass, GetMethodID) или манифест. Классы без сайтов вызова Java считаются неиспользуемыми и удаляются R8. Из-за этого функции, которые работают в сборках для разработки, могут не работать в сборках для доставки, вызывая ошибку ClassNotFoundException или NoSuchMethodError.

Используйте тег <proguardAdditions> в XML-файле Unreal Plugin Language (UPL), чтобы объединить собственные правила сохранения в proguard-rules.pro во время упаковки. Добавьте в файл *_UPL.xml проекта или плагина следующий блок:

<root xmlns:android="http://schemas.android.com/apk/res/android">
    <proguardAdditions>
        <insert>
            -keep class com.epicgames.unreal.** { *; }
            -keep class com.example.plugin.** { public *; }
            -dontwarn com.example.plugin.**
        </insert>
    </proguardAdditions>
</root>

Устранение неполадок

В этом разделе описывается, как устранять распространенные проблемы с упаковкой и средой выполнения при использовании R8 в Unreal Engine.

Как временно отключить R8 для отладки

Чтобы определить, вызваны ли сбои в рабочей версии тем, что R8 удаляет необходимые классы, вставьте DISABLE_MINIFY=1 под <gradleProperties> в файле UPL. Если он есть, UEDeployAndroid.cs генерирует minifyEnabled false:

<gradleProperties>
    <insert>
        DISABLE_MINIFY=1
    </insert>
</gradleProperties>

Missing classes detected while running R8 ошибок упаковки

В UE 5.4 и более поздних версиях (AGP 7.4.2 и выше) R8 строго проверяет отсутствие классов. Если упаковка завершается с этой ошибкой, проверьте файл missing_rules.txt в промежуточном каталоге сборки (в Intermediate/Android/.../gradle/app/build/outputs/mapping/release/missing_rules.txt) и добавьте отсутствующие зависимости библиотек или необходимые правила в <proguardAdditions> в файле UPL.

Совместимость полного режима R8 со сторонними SDK

В UE 5.8 и более поздних версиях (AGP 8.13.0+) по умолчанию включен полный режим R8, который позволяет выполнять более агрессивную оптимизацию. Если устаревший сторонний Android SDK не работает во время выполнения из-за проблем с рефлексией, обновите правила ProGuard для плагина или верните R8 в режим совместимости, добавив в файл UPL следующее свойство:

<gradleProperties>
    <insert>
        android.enableR8.fullMode=false
    </insert>
</gradleProperties>