แม้ว่าตรรกะหลักของเกมใน Unity จะเขียนด้วย C# (คอมไพล์ด้วย IL2CPP) แต่บิลด์ Android จะมีไบต์โค้ด Java และ Kotlin (classes.dex) จำนวนมากเพื่อจัดการเหตุการณ์ในวงจรของ UnityPlayerActivity, บริการ Google Play, การเรียกเก็บเงิน, โฆษณา และ SDK โซเชียล
การเปิดใช้ R8 ซึ่งเป็นเครื่องมือลดขนาดและเพิ่มประสิทธิภาพโค้ดเริ่มต้นในปลั๊กอิน Android Gradle (AGP) จะนำคลาสและเมธอดที่ไม่ได้ใช้ออก รวมถึงเพิ่มประสิทธิภาพไบต์โค้ด ซึ่งไม่เพียงช่วยลดขนาดการดาวน์โหลดแอปเท่านั้น แต่ยังช่วยลดหน่วยความจำที่ใช้ขณะรันไทม์ของหน้า DEX ที่แมปหน่วยความจำ (mmap) และโอเวอร์เฮดของกระบวนการ Java พื้นฐานด้วย ซึ่งจะช่วยลดแรงกดดันต่อหน่วยความจำจริงและการสิ้นสุดการทำงานของ Low Memory Killer (LMK) นอกจากนี้ Google Play ยังตรวจสอบระดับการเพิ่มประสิทธิภาพ DEX ของเกมผ่านเมตริกการเพิ่มประสิทธิภาพโค้ด DEX ใน Android Vitals ด้วย
ลักษณะการทำงานเริ่มต้นและการรองรับเวอร์ชัน Unity
ใน Unity การลดขนาดโค้ดจะปิดใช้อยู่โดยค่าเริ่มต้น (false) สำหรับทั้งบิลด์รุ่นและบิลด์การแก้ไขข้อบกพร่องเมื่อสร้างโปรเจ็กต์ใหม่
Unity เปิดตัว R8 เป็นครั้งแรกในรูปแบบปุ่มเปิด/ปิดที่ไม่บังคับใน Unity 2020.1.0f1 ตั้งแต่ Unity 2022.2.0f1 (และพอร์ตย้อนกลับไปยัง Unity 2021.3.41f1 LTS) Unity ได้อัปเกรด Toolchain ที่รวมมาเป็น 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) เปิดใช้ทั้งลดขนาด > เผยแพร่และใช้ R8 |
| 2021.3.41f1 ขึ้นไป (2021 LTS) | 7.1+ | ปิดใช้อยู่ (false) |
R8 เท่านั้น เปิดใช้ Minify > Release เพื่อเรียกใช้ R8 โดยอัตโนมัติ |
| 2022.2.0f1 ถึง Unity 6 ขึ้นไป | 7.1 ถึง 8.x | ปิดใช้อยู่ (false) |
R8 เท่านั้น เปิดใช้ Minify > Release เพื่อเรียกใช้ R8 โดยอัตโนมัติ |
เปิดใช้ R8 ในการตั้งค่าเพลเยอร์
วิธีเปิดใช้การลดขนาดโค้ดและการเพิ่มประสิทธิภาพ R8 สำหรับบิลด์ที่เผยแพร่
- ใน Unity Editor ให้เปิดแก้ไข > การตั้งค่าโปรเจ็กต์ แล้วเลือกเพลเยอร์
- เลือกแท็บ Android แล้วขยายการตั้งค่าการเผยแพร่ > บิลด์
- ในส่วนลดขนาด ให้กำหนดค่าตัวเลือกสำหรับเวอร์ชัน Unity ดังนี้
- Unity 2021.3.41f1 ขึ้นไปและ 2022.2.0f1 ขึ้นไป: เลือกรุ่น Unity จะเรียกใช้ R8 โดยอัตโนมัติระหว่างงาน
minifyReleaseWithR8Gradle - Unity 2020.1.0f1 ถึง 2021.3.40f1: เลือกทั้งรุ่นและใช้ R8
- Unity 2021.3.41f1 ขึ้นไปและ 2022.2.0f1 ขึ้นไป: เลือกรุ่น Unity จะเรียกใช้ R8 โดยอัตโนมัติระหว่างงาน
หากคุณสร้างโดยอัตโนมัติโดยใช้สคริปต์ C# Editor ให้กำหนดค่าพร็อพเพอร์ตี้เหล่านี้ผ่าน 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 และการสะท้อน
คลาสและเมธอด Java ที่เรียกใช้แบบไดนามิกจากสคริปต์ C# โดยใช้ AndroidJavaClass หรือ AndroidJavaObject ไม่มี Call Site ของ Java แบบคงที่ หากไม่มีกฎการเก็บรักษาที่ชัดเจน R8 อาจถือว่าคลาสเหล่านี้ไม่ได้ใช้และนำออกหรือเปลี่ยนชื่อ
วิธีคง Java Bridge ที่กำหนดเองไว้
- ในการตั้งค่าโปรเจ็กต์ > Player > Android > การตั้งค่าการเผยแพร่ > บิลด์ ให้เปิดใช้ไฟล์ Proguard ที่กำหนดเอง
- เปิดไฟล์
Assets/Plugins/Android/proguard-user.txtที่สร้างขึ้น - เพิ่มกฎ
-keepสำหรับคลาสที่เข้าถึงผ่าน JNI หรือที่ปลั๊กอินของบุคคลที่สามกำหนดให้มี:
# 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 { *; }
แก้ไขปัญหาทั่วไป
ส่วนนี้จะอธิบายวิธีแก้ไขปัญหาทั่วไปเกี่ยวกับบิลด์และรันไทม์เมื่อใช้ R8 ใน Unity
ข้อผิดพลาดในการบิลด์ Missing classes detected while running R8 รายการ
ใน Unity เวอร์ชันที่ใช้ AGP 7.0 ขึ้นไป (2021.3.41f1+ และ 2022.2+) R8 จะบังคับใช้การตรวจสอบคลาสที่ขาดหายไปอย่างเข้มงวด หากบิลด์ไม่สำเร็จเนื่องจากข้อผิดพลาดนี้ ให้ตรวจสอบไฟล์ missing_rules.txt ที่สร้างขึ้นในไดเรกทอรีเอาต์พุตของบิลด์ (ในส่วน Library/Bee/Android/Prj/.../build/outputs/mapping/release/missing_rules.txt หรือ Temp/gradleOut/...) แล้วเพิ่มทรัพยากร Dependency หรือกฎที่จำเป็นลงใน proguard-user.txt ดูข้อมูลเพิ่มเติมเกี่ยวกับการเขียนกฎ Keep ได้ที่หัวข้อปรับแต่งโค้ดที่จะเก็บไว้
ความเข้ากันได้ของโหมดเต็มรูปแบบ R8 กับปลั๊กอินของบุคคลที่สาม
ใน AGP 8.0 ขึ้นไป (Unity 6+) โหมดเต็มรูปแบบ R8 จะเปิดใช้โดยค่าเริ่มต้นเพื่อทำการเพิ่มประสิทธิภาพที่เข้มงวดมากขึ้น หากปลั๊กอิน Android เดิมทำงานไม่สำเร็จที่รันไทม์เนื่องจากปัญหาการสะท้อน ให้ปรับปรุงกฎ ProGuard ของปลั๊กอินหรือเปลี่ยน R8 กลับไปเป็นโหมดความเข้ากันได้ โดยทำดังนี้
- ในการตั้งค่าการเผยแพร่ > บิลด์ ให้เปิดใช้เทมเพลตพร็อพเพอร์ตี้ Gradle ที่กำหนดเอง
- เปิด
Assets/Plugins/Android/gradleTemplate.propertiesและเพิ่มพร็อพเพอร์ตี้ต่อไปนี้
android.enableR8.fullMode=false