Optimisasi Mobile Unreal Engine: Membuat MetaHumans dan PCG Berjalan pada 60 FPS
Ringkasnya
Artikel ini menjelaskan strategi optimisasi fitur grafis canggih seperti MetaHumans, PCG, dan Substrate agar dapat berjalan pada 60 FPS di perangkat mobile. Optimisasi dilakukan melalui konfigurasi batas bone skinning pada DefaultEngine.ini, penggunaan hair cards untuk rambut MetaHuman, penonaktifan post-process animation blueprint, serta pre-baking graph PCG menjadi HISM. Di samping optimisasi rendering di sisi client, dibahas pula pentingnya performa jaringan mobile dan penggunaan layanan backend siap pakai seperti horizOn untuk sinkronisasi state multiplayer lintas platform.
Hambatan Mobile: Menghadirkan Visual Next-Gen ke Mobile
Proyek PC Anda yang indah dapat berjalan lancar pada 120 FPS di workstation developer Anda, tetapi begitu Anda menguji paket mobile, frame rate merosot hingga ke satu digit, ponsel target cepat panas, dan GPU crash akibat skinning buffer overflow. Fitur high-end seperti MetaHumans, Procedural Content Generation (PCG), dan material Substrate tampak memukau di PC dan konsol, tetapi fitur-fitur ini terkenal sering membuat perangkat mobile kewalahan. GPU dan CPU mobile beroperasi dalam envelope termal dan daya yang sangat terbatas, di mana bandwidth memori adalah sumber daya premium. Mengadaptasi fitur next-generation ini untuk deployment mobile bukan sekadar masalah mencentang kotak konfigurasi; ini memerlukan pemahaman yang mendalam dan sistematis tentang batasan bone skinning, struktur groom, workflow procedural baking, serta kompleksitas material shading.
Tantangan Limit Bone dan GPU Skinning
Bottleneck GPU Skinning pada Mobile
Skeletal mesh yang telah di-skin dibagi menjadi beberapa chunk vertex dan bone sebelum dikirim ke GPU. Setiap chunk diproses dalam satu draw call, dan GPU mobile memiliki batasan hardware yang ketat pada jumlah bone matrix yang dapat di-skin secara bersamaan. Limitasi ini ditentukan oleh jumlah uniform vector yang tersedia untuk vertex shader. Skeleton karakter default dari MetaHuman memiliki lebih dari 600 bone, yang dengan mudah melampaui limit mobile dan menyebabkan error rendering, vertex tearing, atau GPU hang sepenuhnya.
Untuk mengatasi batasan hardware ini, Anda harus memaksa engine untuk membagi skeletal mesh chunk sedemikian rupa sehingga tidak ada satu draw call pun yang mereferensikan lebih dari jumlah bone tertentu. Hal ini dicapai dengan menyesuaikan pengaturan kompatibilitas skinning. Jika Anda tidak menerapkan konfigurasi ini, model karakter Anda akan gagal melakukan skinning dengan benar di perangkat Android dan iOS, menampilkan mesh yang statis atau sangat terdistorsi.
Mengonfigurasi DefaultEngine.ini
Untuk mengatasi batasan bone skinning, Anda harus memodifikasi file konfigurasi DefaultEngine.ini proyek Anda. Temukan file ini di folder Config di root proyek Anda. Di bawah bagian [ConsoleVariables], tambahkan baris berikut:
[ConsoleVariables]
Compat.MAX_GPUSKIN_BONES=75
Console variable ini menginstruksikan shader compiler untuk membatasi jumlah maksimum bone per skinning chunk menjadi 75. Ini adalah batasan hardware yang ketat untuk GPU mobile lama atau kelas menengah. Perlu diingat bahwa menetapkan nilai ini lebih rendah akan memaksa skeletal mesh compiler untuk membagi mesh menjadi jumlah chunk yang lebih banyak. Meskipun ini menyelesaikan kompatibilitas rendering, lebih banyak chunk berarti lebih banyak draw call, yang dapat menggeser bottleneck performa ke thread render CPU Anda.
Mengurangi Bone Count dan Component Stripping
Untuk karakter latar belakang atau non-player character (NPC) yang tidak memerlukan artikulasi wajah penuh, Anda sebaiknya memangkas skeleton tersebut. Sebagai contoh, menghapus jari tangan, jari kaki, dan bone ekspresi wajah dapat mengurangi total bone count karakter dari 600+ menjadi di bawah 75. Ini memungkinkan mesh karakter dirender sebagai satu chunk tanpa adanya inflasi draw call.
Jika Anda juga men-deploy dedicated server untuk game multiplayer Anda, optimisasi di sisi client barulah setengah jalan. Anda juga perlu mengoptimalkan performa di sisi server dengan menghapus asset rendering sepenuhnya. Lihat panduan langkah demi langkah kami tentang cara menguasai asset stripping dedicated server Unreal Engine untuk mengurangi memory overhead server dan mengoptimalkan performa CPU.
Mengoptimalkan Rambut MetaHuman: Groom Strands vs. Hair Cards
Biaya Strand Rendering
Teknologi groom strand rendering dari Epic menggambar setiap helai rambut secara dinamis. Meskipun menghasilkan rambut yang sangat detail pada GPU desktop high-end, proses ini sangatlah berat. Strand rendering bergantung pada proses compute shader untuk pengurutan kedalaman (depth sorting) dan pembuatan shadow map, yang menghabiskan pixel fill rate dan bandwidth memori dalam jumlah besar.
Pada perangkat mobile, strand rendering tidak didukung sama sekali atau berjalan dengan performa yang tidak dapat diterima—sering kali menghabiskan lebih dari 15ms waktu GPU hanya untuk rambut satu karakter. GPU mobile tidak memiliki bandwidth memori mentah yang cukup untuk mengurutkan dan mewarnai ratusan ribu helai rambut individu per frame.
Menerapkan Hair Cards
Solusinya adalah mengganti groom berbasis strand dengan hair cards. Hair cards merepresentasikan rambut menggunakan polygon mesh datar yang disederhanakan dan dipetakan dengan tekstur rambut yang telah dirender sebelumnya. Pendekatan ini sangat kompatibel dengan forward render path pada perangkat mobile.
Untuk menerapkan hair cards, buka MetaHuman Creator dan pastikan Anda membuat LOD groom berbasis card untuk karakter Anda. Mengganti rambut berbasis strand dengan groom berbasis card mengurangi waktu rendering rambut untuk satu karakter dari sekitar 18,2ms menjadi 0,9ms pada chip mobile modern seperti Apple A15 atau Snapdragon 8 Gen 1. Penghematan besar ini memungkinkan Anda mengalokasikan anggaran rendering ke elemen gameplay atau detail lingkungan (environment).
Menonaktifkan Post-Process Anim Blueprint
MetaHumans menggunakan post-process animation blueprint untuk menggerakkan gerakan bone sekunder, bentuk otot korektif, dan dinamika sendi. Meskipun ini menambahkan gerakan kulit yang realistis di PC, proses ini menjalankan kalkulasi skeletal yang kompleks pada CPU setiap frame. Pada mobile, overhead CPU ini dapat dengan mudah menjadi bottleneck pada game thread.
Anda dapat menonaktifkan post-process animation blueprint pada perangkat mobile untuk menghemat resource CPU. Ini dilakukan dengan menetapkan bDisablePostProcessAnims = true pada komponen skeletal mesh. Menonaktifkan post-process ini menghemat hingga 4,5ms waktu frame CPU pada hardware mobile standar.
Mengoptimalkan PCG untuk Lingkungan Mobile
Overhead dari Eksekusi PCG di Runtime
Framework Procedural Content Generation (PCG) memungkinkan Anda mengisi lingkungan Anda secara dinamis dengan menyebarkan static mesh, foliage, dan actor berdasarkan aturan dan volume. Namun, mengeksekusi graph PCG pada runtime di CPU mobile menyebabkan penurunan performa (hitch) yang parah. Pembuatan graph saat runtime biasanya dapat membekukan game thread selama 1,5 hingga 3 detik selama pemuatan level atau saat player melakukan spawning.
Dalam game multiplayer, hitch semacam itu berbahaya karena dapat menyebabkan packet loss dan memicu desinkronisasi state client-server. Untuk menjaga performa tetap tinggi, Anda harus melakukan pre-bake graph PCG Anda di editor. Langkah ini mengonversi instance prosedural menjadi geometri statis sebelum memaketkan game Anda.
Alur Kerja Baking PCG Langkah demi Langkah
- Pilih PCG Volume: Di viewport Unreal Editor, pilih volume PCG yang berisi elemen lingkungan Anda.
- Generate dan Inspeksi: Di panel detail volume, klik Generate untuk melihat pratinjau penempatan prosedural dari aset Anda.
- Export ke Actor: Temukan opsi Export to Actor di dalam menu utilitas PCG.
- Pilih Instanced Mesh: Pilih Hierarchical Instanced Static Mesh (HISM) sebagai format target. Kelompok instance ini sangat dioptimalkan untuk GPU mobile, karena ia merender semua mesh yang identik dalam satu draw call GPU.
- Bersihkan Graph: Setelah diekspor, atur trigger pembuatan volume PCG menjadi Editor Only atau bersihkan volume tersebut. Ini mencegah engine saat runtime mencoba membuat ulang graph.
Culling dan Streaming HISM secara Dinamis
Setelah Anda melakukan baking instance PCG ke dalam HISM, Anda harus mengonfigurasi culling distance-nya. HISM mendukung culling per-instance, yang berarti instance di luar jarak tertentu dari kamera tidak akan dirender. Atur Start Cull Distance dan End Cull Distance di panel detail komponen HISM Anda. Untuk perangkat mobile, direkomendasikan jarak culling sebesar 5000 hingga 8000 unit agar jumlah poligon terlihat yang total tetap berada dalam batas GPU mobile.
Script Optimisasi C++ untuk Tahap Produksi
Untuk mengotomatiskan optimisasi ini saat runtime, Anda dapat menulis kelas helper kustom. Kode C++ berikut menunjukkan cara memeriksa platform target, memaksa LOD rendah secara programatis, menonaktifkan post-process animation blueprint, dan memaksa komponen groom untuk menggunakan rendering berbasis card saat men-spawn MetaHuman di perangkat mobile. Anda dapat mengimplementasikan ini di kelas seperti UMetaHumanMobileOptimizer:
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "Components/SkeletalMeshComponent.h"
#include "GroomComponent.h"
#include "MetaHumanMobileOptimizer.generated.h"
UCLASS()
class MYPROJECT_API UMetaHumanMobileOptimizer : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category = "Optimization")
static void OptimizeMetaHumanForMobile(AActor* MetaHumanActor)
{
if (!MetaHumanActor)
{
return;
}
// Apply optimizations exclusively on Android and iOS platforms
#if PLATFORM_ANDROID || PLATFORM_IOS
TArray<USkeletalMeshComponent*> SkeletalComponents;
MetaHumanActor->GetComponents<USkeletalMeshComponent>(SkeletalComponents);
for (USkeletalMeshComponent* MeshComp : SkeletalComponents)
{
if (MeshComp)
{
// Force a low LOD (LOD 3 or 4) to bypass dense meshes
MeshComp->SetMinLOD(3);
MeshComp->SetForcedLOD(3);
// Disable expensive post-process animation blueprints
MeshComp->bDisablePostProcessAnims = true;
// Adjust animation tick rate to only calculate when visible
MeshComp->VisibilityBasedAnimTickOption = EVisibilityBasedAnimTickOption::OnlyTickPoseWhenRendered;
// Strip physics asset to avoid CPU collision overhead on cosmetic joints
MeshComp->SetPhysicsAsset(nullptr);
}
}
TArray<UGroomComponent*> GroomComponents;
MetaHumanActor->GetComponents<UGroomComponent>(GroomComponents);
for (UGroomComponent* GroomComp : GroomComponents)
{
if (GroomComp)
{
// Force the groom to use card rendering instead of strands
GroomComp->SetUseCards(true);
}
}
#endif
}
};
Fungsi helper ini dapat dipanggil dari event BeginPlay karakter Anda atau segera setelah men-spawn actor MetaHuman. Dengan menggunakan makro kompilasi kondisional (PLATFORM_ANDROID || PLATFORM_IOS), compiler akan menghapus override ini dari build PC dan konsol, memungkinkan Anda untuk mempertahankan kesetiaan visual (visual fidelity) lintas platform secara otomatis.
Mengadaptasi Material Substrate untuk GPU Mobile
Apa itu Substrate?
Substrate menggantikan shading model Unreal Engine tradisional dengan framework material multi-layer yang modular. Substrate memungkinkan developer untuk menumpuk beberapa shading slab (misalnya, menempatkan layer clear coat glossy langsung di atas layer logam kasar). Meskipun Substrate sangat bagus untuk aset sinematik high-end, ini menghadirkan hambatan performa yang serius bagi mobile renderer.
GPU mobile sangat bergantung pada arsitektur tiled rendering di mana bus memori antara inti GPU dan on-chip frame buffer adalah bottleneck utama. Material Substrate yang kompleks meningkatkan jumlah byte per pixel (BPP) yang ditulis ke frame buffer, menyebabkan thermal throttling dan penurunan frame rate.
Mengelola Kompleksitas Material via Quality Level Switch
Untuk menjaga material Substrate tetap berperforma tinggi di mobile, Anda sebaiknya menggunakan node Material Quality Level Switch dan Feature Level Switch di dalam Material Editor. Node ini memungkinkan Anda untuk menyederhanakan material graph berdasarkan platform target.
Untuk platform mobile, sederhanakan graph dengan melewati blend Substrate yang multi-layer. Sebagai gantinya, gunakan fallback ke single slab yang mendekati gaya visual aset Anda. Dengan mengarahkan node material Anda melalui quality switch, Anda dapat mengurangi bandwidth tulis dari 32 byte per piksel ke standar 8 byte per piksel, menghasilkan perangkat yang berjalan lebih dingin dan frame rate yang stabil.
5 Best Practice Praktis untuk Optimisasi Mobile
- Pre-bake semua graph PCG ke HISM: Jangan mengeksekusi graph PCG pada client saat runtime. Lakukan pre-bake graph ke Hierarchical Instanced Static Mesh (HISM) selama pengembangan di editor dan konfigurasi jarak culling awal/akhir (start/end cull distance) yang sesuai.
- Batasi bone count secara global: Tambahkan
Compat.MAX_GPUSKIN_BONES=75ke file DefaultEngine.ini proyek Anda untuk memastikan skeletal mesh dirender dengan benar pada GPU mobile tanpa memicu buffer overflow. - Gunakan card-based groom secara eksklusif: Nonaktifkan groom berbasis strand untuk profil mobile. Rendering rambut berbasis card mengurangi waktu frame GPU dari 18ms menjadi kurang dari 1ms per karakter.
- Manfaatkan Material Quality Switch: Terapkan node Material Quality Level Switch dalam material Substrate Anda untuk menyederhanakan shading layer yang kompleks menjadi single slab pada platform mobile, mengurangi bandwidth GPU.
- Nonaktifkan post-process animation blueprint: Atur
bDisablePostProcessAnims = truepada komponen skeletal karakter Anda di mobile untuk menghemat cycle CPU yang berharga pada game thread.
Persamaan Multiplayer dan Backend
Lebih dari Sekadar Rendering: Optimisasi Jaringan Mobile
Saat mengembangkan game multiplayer lintas platform, optimisasi di sisi client hanyalah satu bagian dari persamaan. Perangkat mobile sering kali mengalami fluktuasi jaringan, berpindah antara data seluler (5G/4G) dan Wi-Fi. Fluktuasi ini menyebabkan packet loss, jitter, dan lonjakan latency yang tinggi.
Jika kode sinkronisasi jaringan Anda tidak tangguh, lonjakan latency ini dapat memicu bug sinkronisasi multiplayer Unreal Engine, di mana replikasi actor menjadi tidak sinkron dan merusak world state. Mengelola state multiplayer di bawah batasan jaringan mobile adalah masalah kompleks yang membutuhkan driver jaringan yang tangguh, kompresi delta, dan rekonsiliasi yang otoritatif di sisi server (server-authoritative reconciliation).
Mengalihkan Beban Infrastruktur dengan horizOn
Membangun dan memelihara backend multiplayer yang tangguh sendiri adalah upaya rekayasa yang sangat besar. Anda harus menyediakan load balancer, mengelola replikasi database global, menerapkan logika matchmaking, dan menangani penagihan mobile. Pekerjaan infrastruktur ini dapat memakan waktu berbulan-bulan pengembangan dan membutuhkan pemeliharaan berkelanjutan.
Dengan horizOn, layanan backend ini sudah terkonfigurasi sebelumnya. horizOn menyediakan session matchmaking, sinkronisasi state berlatency rendah, persistensi database, dan autentikasi lintas platform langsung pakai untuk para game developer. Ini memungkinkan Anda fokus pada mengoptimalkan client dan memoles game loop Anda, alih-alih mengelola cluster server dan skalabilitas database.
Kesimpulan dan Langkah Selanjutnya
Mengoptimalkan fitur next-generation seperti MetaHumans dan PCG untuk perangkat mobile memerlukan kontrol ketat terhadap anggaran rendering, kompilasi skeletal mesh, dan kompleksitas material shading. Dengan melakukan pre-baking pada aset prosedural Anda, membatasi limit bone count, dan menggunakan rendering rambut berbasis card, Anda dapat menghadirkan pengalaman lintas platform dengan kesetiaan grafis tinggi di perangkat genggam (handheld).
Siap untuk meningkatkan skala backend multiplayer Anda? Coba horizOn secara gratis atau lihat dokumen API untuk mengetahui bagaimana Anda dapat menyederhanakan infrastruktur dan menjaga pemain tetap sinkron di PC, konsol, dan mobile.
Sumber: Tutorial: Optimizing Next Gen Features for Mobile Game Development