کوچک کردن و بهینه‌سازی کد Unreal Engine با R8

اگرچه منطق اصلی بازی شما در Unreal Engine به زبان C++‎ یا Blueprints نوشته شده است، بسته‌بندی Android بایت‌کد Java و Kotlin (classes.dex) را برای مدیریت رویدادهای چرخه حیات GameActivity، خدمات Google Play، صورت‌حساب، صدا، و افزایه‌های تجزیه‌وتحلیل کامپایل می‌کند.

R8، بهینه‌ساز و کوچک‌کننده کد پیش‌فرض در «افزایه Android Gradle» (AGP)، کلاس‌ها و روش‌های استفاده‌نشده را حذف می‌کند و بایت‌کد را بهینه‌سازی می‌کند. این کار نه تنها اندازه بارگیری بسته شما را کاهش می‌دهد، بلکه ردپای حافظه زمان اجرای صفحه‌های DEX نگاشت‌شده در حافظه (mmap) و سربار فرایند Java پایه را نیز کاهش می‌دهد، فشار حافظه فیزیکی را کاهش می‌دهد، و از بستن برنامه به‌دلیل کمبود حافظه (LMK) جلوگیری می‌کند. Google Play همچنین سطوح بهینه‌سازی DEX بازی‌تان را ازطریق سنجه بهینه‌سازی کد DEX در «معیارهای کلیدی Android» پایش می‌کند.

رفتار پیش‌فرض و پشتیبانی از نسخه Unreal Engine

از UE 4.22.0،‏ UEDeployAndroid.cs Unreal Engine به‌طور پیش‌فرض minifyEnabled true را به پیکربندی ساخت نسخه پخش Android تولیدشده (buildAdditions.gradle) تزریق می‌کند. چون UE 4.25 زنجیره ابزار بسته‌بندی‌شده را به AGP 4.0.0 ارتقا داده است، R8 به‌طور پیش‌فرض (true) در همه نسخه‌های ساخت Release (ارسال و توزیع) در UE 4.25 و بالاتر بدون راه‌اندازی اضافی فعال است.

نسخه Unreal Engine AGP بسته‌ای پیش‌فرض نسخه پخش اشکال‌زدایی پیش‌فرض رفتار
UE 4.21 و نسخه‌های قدیمی‌تر Gradle یا Ant قدیمی غیرفعال (false) غیرفعال (false) هیچ پیکربندی minifyEnabled توسط موتور تزریق نشده است.
UE 4.22 تا 4.24 قدیمی‌تر از نسخه ۳.۴ فعال (ProGuard) غیرفعال (false) minifyEnabled true به‌طور پیش‌فرض در ساخت‌های «نسخه پخش» فعال است (ProGuard را اجرا می‌کند).
UE نسخه ۴.۲۵ تا ۵.۳ 4.0.0 فعال (R8) غیرفعال (false) پذیرش AGP 4.0 به‌طور پیش‌فرض R8 را در ساخت‌های «نسخه پخش» اجرا می‌کند.
UE 5.4 تا 5.7 ‫۷.۴.۲ فعال (R8) غیرفعال (false) ‫AGP 7.x گزینه‌های قدیمی useProguard را برمی‌دارد؛ R8 منحصراً اجرا می‌شود.
UE 5.8 (5.8.3+) ‫۸.۱۳.۰ فعال (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) یا مانیفست قابل‌دسترسی هستند حفظ کنید. کلاس‌های بدون سایت‌های فراخوانی جاوا به‌عنوان استفاده‌نشده درنظر گرفته می‌شوند و توسط 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 نسخه ۵.۴ و بالاتر (AGP نسخه ۷.۴.۲ و بالاتر)، R8 بررسی‌های سخت‌گیرانه‌ای برای کلاس‌های مفقودشده اعمال می‌کند. اگر بسته‌بندی با این خطا مواجه شد، missing_rules.txt را در فهرست راهنمای ساخت واسطه (زیر Intermediate/Android/.../gradle/app/build/outputs/mapping/release/missing_rules.txt) بررسی کنید و وابستگی‌های کتابخانه مفقود یا قوانین لازم را به <proguardAdditions> در فایل UPL خود اضافه کنید.

سازگاری حالت کامل R8 با کیت‌های توسعه نرم‌افزار طرف سوم

در UE نسخه ۵.۸ و بالاتر (AGP نسخه ۸.۱۳.۰ و بالاتر)، حالت کامل R8 به‌طور پیش‌فرض فعال است تا بهینه‌سازی‌های تهاجمی‌تری انجام شود. اگر کیت توسعه نرم‌افزار Android قدیمی شخص ثالثی در زمان اجرا به‌دلیل مشکلات بازتابی ناموفق باشد، قوانین ProGuard افزونه را به‌روز کنید یا با افزودن ویژگی زیر به فایل UPL خود، R8 را به حالت سازگاری برگردانید:

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