ลดขนาดและเพิ่มประสิทธิภาพโค้ด Unreal Engine ด้วย R8

แม้ว่าตรรกะหลักของเกมใน Unreal Engine จะเขียนด้วย C++ หรือพิมพ์เขียว แต่แพ็กเกจ Android จะคอมไพล์ไบต์โค้ด Java และ Kotlin (classes.dex) เพื่อจัดการเหตุการณ์ในวงจร GameActivity, บริการ Google Play, การเรียกเก็บเงิน, เสียง และปลั๊กอินการวิเคราะห์

R8 ซึ่งเป็นเครื่องมือลดขนาดและเพิ่มประสิทธิภาพโค้ดเริ่มต้นในปลั๊กอิน Android Gradle (AGP) จะนำคลาสและเมธอดที่ไม่ได้ใช้ออก รวมถึงเพิ่มประสิทธิภาพไบต์โค้ด ซึ่งไม่เพียงแต่จะลดขนาดการดาวน์โหลดแพ็กเกจเท่านั้น แต่ยังลดหน่วยความจำที่ใช้ขณะรันไทม์ของหน้า DEX ที่แมปหน่วยความจำ (mmap) และโอเวอร์เฮดของกระบวนการ Java พื้นฐานด้วย ซึ่งจะช่วยลดแรงกดดันด้านหน่วยความจำทางกายภาพและการสิ้นสุดการทำงานของ Low Memory Killer (LMK) นอกจากนี้ Google Play ยังตรวจสอบระดับการเพิ่มประสิทธิภาพ DEX ของเกมผ่านเมตริกการเพิ่มประสิทธิภาพโค้ด DEX ใน Android Vitals ด้วย

ลักษณะการทำงานเริ่มต้นและการรองรับเวอร์ชัน Unreal Engine

ตั้งแต่ UE 4.22.0 เป็นต้นไป UEDeployAndroid.cs ของ Unreal Engine จะแทรก minifyEnabled true ลงในการกำหนดค่าบิลด์ที่เผยแพร่ของ Android ที่สร้างขึ้น (buildAdditions.gradle) โดยค่าเริ่มต้น เนื่องจาก UE 4.25 อัปเกรด Toolchain ที่รวมมาเป็น 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 ก่อนเวอร์ชัน 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
    }
}
  • Release (การจัดส่งหรือการเผยแพร่): ตั้งค่า minifyEnabled true และใช้ proguard-rules.pro โดยค่าเริ่มต้น ซึ่งจะเรียกใช้การลดขนาดโค้ดและการปรับให้ยากต่อการอ่าน (Obfuscation) ของ R8
  • แก้ไขข้อบกพร่อง (การพัฒนา): เปิดใช้ debuggable true และละเว้น minifyEnabled (ค่าเริ่มต้นคือ false) เพื่อคงการทำซ้ำบิลด์ที่รวดเร็วและการแก้ไขข้อบกพร่องของสัญลักษณ์ไว้

เพิ่มกฎการเก็บรักษาโดยใช้ Unreal Plugin Language (UPL)

เนื่องจาก R8 ทำงานโดยอัตโนมัติในบิลด์ที่เผยแพร่ใน UE 4.25 ขึ้นไป คุณจึงต้องเก็บรักษาคลาส Java ที่เข้าถึงได้ผ่าน C++ JNI (JNIEnv->FindClass, GetMethodID) หรือไฟล์ Manifest เท่านั้น คลาสที่ไม่มีไซต์การเรียก 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) แล้วเพิ่มทรัพยากร Dependency ของไลบรารีที่ขาดหายไปหรือกฎที่จำเป็นลงใน <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>