การเพิ่มประสิทธิภาพหน่วยความจำของเกม Unreal ใน Android

การใช้งานหน่วยความจำเป็นสิ่งสำคัญอย่างยิ่งในการพัฒนาเกม Android เมื่อพัฒนาเกมโดยใช้ Unreal Engine คุณต้องวิเคราะห์และติดตามสถานะหน่วยความจำอย่างต่อเนื่องเพื่อให้เป็นไปตามข้อจำกัดด้านหน่วยความจำเหล่านี้ ซึ่งจะช่วยป้องกันหน่วยความจำรั่วไหลและการจัดสรรหน่วยความจำมากเกินไป

การประหยัดหน่วยความจำผ่านการลดการเรียงสับเปลี่ยนของ Shader

การนำตัวเลือกที่ไม่ได้ใช้ออกใน Lighting หรือ Mobile Shader Permutation Reduction จะช่วยลดจำนวนการเรียงสับเปลี่ยนของ Shader ได้ ซึ่งจะช่วยลดขนาดการแพ็กเกจแอปอย่างมาก ลดจำนวนออบเจ็กต์สถานะไปป์ไลน์ (PSO) และป้องกันการสร้างเป้าหมายการแสดงผลหรือพื้นผิวจำลองที่ไม่ได้ใช้ ซึ่งจะช่วยลดหน่วยความจำรันไทม์และเพิ่มประสิทธิภาพ

ดูข้อมูลเพิ่มเติมได้ที่ส่วนการตั้งค่าการลดการเรียงสับเปลี่ยนของ Shader และการจัดแสงอื่นๆ สำหรับอุปกรณ์เคลื่อนที่ ในหลักเกณฑ์ด้านประสิทธิภาพสำหรับอุปกรณ์เคลื่อนที่

การเพิ่มประสิทธิภาพการโหลดเนื้อหา

เมื่อโหลดเนื้อหาโดยใช้ข้อมูลอ้างอิงแบบฮาร์ดแวร์ ระบบจะโหลดเนื้อหาที่เชื่อมต่อซึ่งไม่ได้ใช้ในเกมลงในหน่วยความจำพร้อมกัน ซึ่งทำให้เกิดการใช้หน่วยความจำโดยไม่จำเป็น โดยเฉพาะอย่างยิ่งเมื่อใช้การสืบทอดใน Blueprints อย่างไม่ถูกต้อง ระบบจะจัดสรร CDO (ออบเจ็กต์เริ่มต้นของคลาส) ที่ไม่จำเป็นจากออบเจ็กต์ระดับบน ซึ่งทำให้สิ้นเปลืองหน่วยความจำจำนวนมาก ในกรณีเช่นนี้ ให้ใช้เทคนิคต่อไปนี้เพื่อเพิ่มประสิทธิภาพการใช้งานหน่วยความจำ

  • การกำหนดโค้ด C++ และการแยกข้อมูล: กำหนดฟังก์ชันการทำงานหลัก โดยใช้ UCLASS(Abstract) ในโค้ด C++ และแยกฟังก์ชันการทำงานดังกล่าวออกจากข้อมูลจริง
  • ลดการสืบทอด: ตั้งค่าข้อมูลและโหลดเนื้อหาใน Blueprints ของโหนดใบเท่านั้น
  • ใช้ข้อมูลอ้างอิงทางอ้อม: ใช้ข้อมูลอ้างอิงพร็อพเพอร์ตี้ทางอ้อมโดยใช้ TSoftObjectPtr เพื่อหลีกเลี่ยงข้อมูลอ้างอิงแบบฮาร์ดแวร์ และโหลดเนื้อหาแบบไม่พร้อมกัน เมื่อจำเป็นเท่านั้นในรันไทม์
  • ข้อควรระวัง: เมื่อใช้การโหลดเนื้อหาแบบไม่พร้อมกัน ให้ตรวจสอบว่าได้ทำการตรวจสอบความถูกต้อง (IsValid) ในระหว่างการเรียกกลับเมื่อการโหลดเสร็จสมบูรณ์แล้ว เพื่อป้องกัน พอยน์เตอร์ที่ค้างอยู่หรือการขัดข้อง

ดูข้อมูลเพิ่มเติมได้ที่หัวข้อ การอ้างอิงเนื้อหา และ การสร้างเกมบนอุปกรณ์เคลื่อนที่ ด้วย UE5

การปรับแต่งพอยน์เตอร์อัจฉริยะและระบบจัดการหน่วยความจำที่ไม่ใช้แล้ว (GC)

การใช้พอยน์เตอร์อัจฉริยะ (เช่น TSharedPtr และ TWeakPtr) ในระหว่างการพัฒนา C++ จะช่วยป้องกันพอยน์เตอร์ที่ค้างอยู่และหน่วยความจำรั่วไหล นอกจากนี้ การใช้ TWeakPtr ยังช่วยหลีกเลี่ยงการสร้างข้อมูลอ้างอิงที่เข้มงวดไปยังออบเจ็กต์ ดังนั้นระบบจัดการหน่วยความจำที่ไม่ใช้แล้วจึงไม่เพิ่มจำนวนข้อมูลอ้างอิงเมื่อรวบรวมออบเจ็กต์ ซึ่งจะช่วยป้องกันไม่ให้ออบเจ็กต์อยู่รอดโดยไม่จำเป็น และลดความซับซ้อนของกราฟข้อมูลอ้างอิงที่ GC ต้องข้าม ซึ่งจะช่วยลดค่าใช้จ่ายของ GC ได้อย่างมาก คุณสามารถจัดการระบบจัดการหน่วยความจำที่ไม่ใช้แล้วได้อย่างมีประสิทธิภาพในสภาพแวดล้อมบนอุปกรณ์เคลื่อนที่โดยทริกเกอร์ ForceGarbageCollection ในระหว่างการเปลี่ยนระดับหรือช่วงเวลาที่ไม่มีการใช้งาน เช่น เมื่อไม่มีการโต้ตอบของผู้ใช้ นอกจากนี้ คุณยังทริกเกอร์ได้เมื่อเกมอยู่ในสถานะที่รับรู้ได้หรือทำงานอยู่เบื้องหลัง (เช่น การเรียกกลับ onStop) เพื่อให้มั่นใจว่าระบบจัดการหน่วยความจำที่ไม่ใช้แล้วจะทำงานโดยไม่ส่งผลต่อประสบการณ์การเล่นเกมที่ใช้งานอยู่

ดูข้อมูลเพิ่มเติมได้ที่หัวข้อการจัดการหน่วยความจำที่ไม่ใช้แล้วและพอยน์เตอร์อัจฉริยะ

การเพิ่มประสิทธิภาพโดยใช้การบีบอัดตารางการย้ายตำแหน่ง

การบีบอัดตารางการย้ายตำแหน่งเป็นวิธีการเพิ่มประสิทธิภาพที่บีบอัดขนาด ตารางการย้ายตำแหน่งในไบนารี ELF เพื่อลดขนาดไบนารี Android เมื่อ minSDKVersion ของ Android เป็น 23 ขึ้นไป ระบบจะรองรับการบีบอัดตารางการย้ายตำแหน่ง APS และเมื่อ minSDKVersion เป็น 28 ขึ้นไป ระบบจะรองรับการบีบอัดตารางการย้ายตำแหน่ง RELR เพิ่มเติม ซึ่งจะช่วยลดขนาดไฟล์ .so ได้อย่างมาก การดำเนินการนี้ไม่เพียงแต่ลดขนาดการดาวน์โหลดเท่านั้น แต่ยังลดหน่วยความจำที่ใช้ของ .so mmap ในรันไทม์ ซึ่งจะช่วยลดแรงกดดันของหน่วยความจำทางกายภาพโดยรวม

AndroidToolChain.cs

if (MinSDKVersion >= 28)
{
  Result += " -Wl,--pack-dyn-relocs=android+relr,--use-android-relr-tags";
}
else if (MinSDKVersion >= 23)
{
  Result += " -Wl,--pack-dyn-relocs=android";
}

หากต้องการใช้การเพิ่มประสิทธิภาพนี้ ให้ตรวจสอบว่าได้เปิดใช้เปิดใช้การบีบอัดตารางการย้ายตำแหน่ง ในการตั้งค่าโปรเจ็กต์หรือตัวแปร bEnableAdvancedBinaryCompression แล้ว

หากต้องการตรวจสอบว่าได้ใช้การบีบอัด RELR กับไบนารีอย่างถูกต้องหรือไม่ ให้ใช้เครื่องมือ llvm-readelf จาก Android NDK

llvm-readelf -d libUnreal.so | grep RELR

ในทางปฏิบัติ การสร้างเทมเพลต ThirdPerson ของ Unreal Engine และการวัดโดยใช้ dumpsys meminfo จะยืนยันการลดการใช้ PSS และ RSS สำหรับ .so mmap

หมวดหมู่ PSS ทั้งหมด ส่วนตัวที่มีการแก้ไข ส่วนตัวที่สะอาด สลับที่มีการแก้ไข RSS ทั้งหมด
.so mmap ก่อนการบีบอัด 170,210 24,360 141,564 0 242,204
.so mmap หลังการบีบอัด 138,031 24,748 108,976 0 210,140

การบีบอัดพื้นผิว

ใช้การบีบอัดพื้นผิวที่เหมาะสมเพื่อลดหน่วยความจำที่ใช้ของทรัพยากรกราฟิกโดยรวม การใช้การบีบอัดพื้นผิวแบบปรับขนาดได้ (ASTC) ซึ่งเป็น มาตรฐานสำหรับอุปกรณ์เคลื่อนที่จะให้คุณภาพภาพที่เหนือกว่าเมื่อเทียบกับ ETC2 ที่ ขนาดเท่ากัน หรือให้อัตราการบีบอัดที่สูงขึ้นโดยใช้หน่วยความจำน้อยลงภายใต้ เป้าหมายคุณภาพภาพเดียวกัน

การเพิ่มประสิทธิภาพการสตรีมพื้นผิว

ในสภาพแวดล้อมบนอุปกรณ์เคลื่อนที่ การใช้ขนาดพูลการสตรีมพื้นผิวเริ่มต้นของ Unreal Engine โดยตรงอาจจัดสรรพูลหน่วยความจำขนาดใหญ่เกินไป เมื่อเทียบกับข้อกำหนดของอุปกรณ์ ดังนั้น การกำหนดโปรไฟล์อุปกรณ์เคลื่อนที่และเลือกขนาดพูลการสตรีมพื้นผิวที่เหมาะสมตามขีดจำกัดหน่วยความจำของอุปกรณ์จึงเป็นวิธีที่ดีที่สุด นอกจากนี้ ให้ใช้ฟีเจอร์สถิติ ของเอดิเตอร์เพื่อตรวจสอบสถิติพื้นผิวและระบุพื้นผิวที่ใช้หน่วยความจำสูงซึ่งมีความละเอียดสูงมากในรันไทม์ จับคู่ฟีเจอร์นี้กับฟีเจอร์ความละเอียดพื้นผิวที่จำเป็น เพื่อบังคับใช้ขีดจำกัดหรือลดความละเอียดสูงสุดของพื้นผิวที่ต้องการทรัพยากรมาก เพื่อให้การใช้ทรัพยากรอยู่ภายใต้การควบคุมภายในบัฟเฟอร์หน่วยความจำพื้นผิวที่จัดสรรไว้