R8 ile Unity kodunu küçültme ve optimize etme

Unity'deki temel oyun mantığınız C# dilinde yazılmış (IL2CPP ile derlenmiş) olsa da Android derlemeleri, UnityPlayerActivity yaşam döngüsü olaylarını, Google Play Hizmetleri'ni, faturalandırmayı, reklamları ve sosyal SDK'ları işlemek için önemli miktarda Java ve Kotlin bayt kodu (classes.dex) içerir.

Android Gradle Eklentisi'ndeki (AGP) varsayılan kod küçültücü ve optimize edici olan R8'i etkinleştirdiğinizde kullanılmayan sınıflar ve yöntemler kaldırılır, bayt kodu optimize edilir. Bu sayede uygulamanızın indirme boyutu küçülür, bellekle eşlenen (mmap) DEX sayfalarının çalışma zamanı bellek kullanımı ve temel Java işlemi ek yükü azalır. Böylece fiziksel bellek baskısı ve düşük bellek durumu nedeniyle işlem sonlandırma (LMK) işlemleri azalır. Google Play, Android vitals'daki DEX kodu optimizasyonu metriği aracılığıyla oyununuzun DEX optimizasyon seviyelerini de izler.

Varsayılan davranış ve Unity sürümü desteği

Unity'de, yeni bir proje oluştururken hem Sürüm hem de Hata Ayıklama derlemeleri için kod sadeleştirme varsayılan olarak devre dışıdır (false).

Unity, R8'i ilk olarak Unity 2020.1.0f1'de isteğe bağlı bir açma/kapatma düğmesi olarak kullanıma sundu. Unity 2022.2.0f1'den itibaren (ve Unity 2021.3.41f1 LTS'ye geri taşınmıştır) Unity, paketlenmiş araç zincirini AGP 7.1.2+ sürümüne yükseltti, eski ProGuard desteğini kaldırdı ve küçültme etkinleştirildiğinde yalnızca R8'i çalıştırır.

Unity sürümü Paket halinde sunulan AGP Varsayılan sürüm R8 desteği ve gerekli yapılandırma
2019.4 LTS ve önceki sürümler 3.4'ten önceki sürümler Devre dışı (false) Desteklenmiyor (yalnızca eski ProGuard).
2020.1.0f1 - 2021.3.40f1 3,4 - 4,0 Devre dışı (false) İsteğe bağlı (varsayılan olarak ProGuard'dır). Hem Minify > Release (Küçült > Sürüm) hem de Use R8 (R8 kullan) seçeneklerini etkinleştirin.
2021.3.41f1 ve sonraki sürümler (2021 LTS) 7.1+ Devre dışı (false) Yalnızca R8. R8'i otomatik olarak çalıştırmak için Küçült > Sürüm'ü etkinleştirin.
2022.2.0f1 - Unity 6+ 7.1 - 8.x Devre dışı (false) Yalnızca R8. R8'i otomatik olarak çalıştırmak için Küçült > Sürüm'ü etkinleştirin.

Player Settings'de (Oynatıcı Ayarları) R8'i etkinleştirme

Yayınlanan derlemeler için R8 kod daraltma ve optimizasyonunu etkinleştirmek üzere:

  1. Unity Editor'da Edit > Project Settings'i (Düzenle > Proje Ayarları) açın ve Player'ı (Oynatıcı) seçin.
  2. Android sekmesini seçin ve Yayınlama Ayarları > Derleme'yi genişletin.
  3. Sadeleştirme bölümünde Unity sürümünüzün seçeneklerini yapılandırın:
    • Unity 2021.3.41f1+ ve 2022.2.0f1+: Release'i (Sürüm) seçin. Unity, minifyReleaseWithR8 Gradle görevi sırasında R8'i otomatik olarak çalıştırır.
    • Unity 2020.1.0f1 - 2021.3.40f1: Hem Release (Sürüm) hem de Use R8 (R8'i kullan) seçeneğini belirleyin.

C# düzenleyici komut dosyalarını kullanarak derlemeleri otomatikleştiriyorsanız bu özellikleri PlayerSettings.Android üzerinden yapılandırın:

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 ve yansıma için saklama kuralları ekleme

AndroidJavaClass veya AndroidJavaObject kullanılarak C# komut dosyalarından dinamik olarak çağrılan Java sınıfları ve yöntemlerinin statik Java çağrı siteleri yoktur. Açık tutma kuralları olmadan R8, bu sınıfları kullanılmamış olarak değerlendirip kaldırabilir veya yeniden adlandırabilir.

Özel Java köprülerinizi korumak için:

  1. Project Settings > Player > Android > Publishing Settings > Build (Proje Ayarları > Oynatıcı > Android > Yayınlama Ayarları > Derleme) bölümünde Custom Proguard File'ı (Özel Proguard Dosyası) etkinleştirin.
  2. Oluşturulan Assets/Plugins/Android/proguard-user.txt dosyasını açın.
  3. JNI üzerinden erişilen veya üçüncü taraf eklentileri için gerekli olan sınıflar için -keep kuralları ekleyin:
# 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 { *; }

Sık karşılaşılan sorunları giderme

Bu bölümde, Unity'de R8 kullanılırken karşılaşılan yaygın derleme ve çalışma zamanı sorunlarının nasıl çözüleceği açıklanmaktadır.

Missing classes detected while running R8 derleme hatası

AGP 7.0 ve sonraki sürümleri (2021.3.41f1+ ve 2022.2+) kullanan Unity sürümlerinde R8, katı eksik sınıf kontrolleri uygular. Bir derleme bu hatayla başarısız olursa derleme çıkış dizininizde (Library/Bee/Android/Prj/.../build/outputs/mapping/release/missing_rules.txt veya Temp/gradleOut/... altında) oluşturulan missing_rules.txt dosyasını inceleyin ve gerekli bağımlılıkları veya kuralları proguard-user.txt dosyasına ekleyin. Saklama kuralları yazma hakkında daha fazla bilgi için Hangi kodun saklanacağını özelleştirme başlıklı makaleyi inceleyin.

Üçüncü taraf eklentileriyle R8 tam mod uyumluluğu

AGP 8.0 ve sonraki sürümlerde (Unity 6+) daha agresif optimizasyonlar gerçekleştirmek için R8 tam modu varsayılan olarak etkindir. Eski bir Android eklentisi, yansıma sorunları nedeniyle çalışma zamanında başarısız olursa eklentinin ProGuard kurallarını güncelleyin veya R8'i uyumluluk moduna geri döndürün:

  1. Publishing Settings > Build (Yayınlama Ayarları > Derleme) bölümünde Custom Gradle Properties Template'i (Özel Gradle Özellikleri Şablonu) etkinleştirin.
  2. Assets/Plugins/Android/gradleTemplate.properties dosyasını açın ve aşağıdaki özelliği ekleyin:
android.enableR8.fullMode=false