Android 上的 Unreal 遊戲記憶體最佳化

記憶體用量在 Android 遊戲開發中至關重要。 使用 Unreal Engine 開發遊戲時,您必須持續分析及追蹤記憶體狀態,以符合這些記憶體限制,避免記憶體流失和過度分配記憶體。

透過減少著色器排列組合節省記憶體

移除 LightingMobile Shader Permutation Reduction 中未使用的選項,即可盡量減少著色器排列組合的數量。這項功能可大幅縮減應用程式封裝大小、減少管道狀態物件 (PSO) 數量,並防止建立未使用的算繪目標或虛擬紋理,進而減少執行階段記憶體用量,提升效能。

詳情請參閱「行動裝置效能指南」中的「行動裝置的雜項照明和著色器排列組合縮減設定」一節。

素材資源載入最佳化

使用硬式參照載入資產時,即使遊戲中未使用連結的內容,也會同時載入至記憶體,造成不必要的記憶體消耗。特別是當藍圖中誤用繼承時,系統會從父項分配不必要的 CDO (類別預設物件),浪費大量記憶體。在這種情況下,請套用下列技巧來最佳化記憶體用量。

  • C++ 程式碼定義和資料分隔:使用 C++ 程式碼中的 UCLASS(Abstract) 定義核心功能,並將這些功能與實際資料分隔。
  • 盡量減少繼承:只在葉節點藍圖中執行資料設定和資產載入作業。
  • 使用間接參照:使用 TSoftObjectPtr 套用間接屬性參照,避免硬式參照,並在執行階段嚴格按照需求非同步載入資產。
  • 注意事項:使用非同步資產載入時,請務必在載入完成回呼期間執行有效性檢查 (IsValid),以免指標懸空或發生當機。

詳情請參閱「參照資產」和「使用 UE5 建構行動遊戲」。

智慧指標和垃圾回收 (GC) 微調

在 C++ 開發期間使用智慧指標 (例如 TSharedPtrTWeakPtr),可避免懸空指標和記憶體流失。此外,使用 TWeakPtr 可避免建立物件的強烈參照,因此垃圾收集器在收集物件時不會遞增參照計數。這可避免不必要的物件存留,並降低 GC 需要遍歷的參照圖複雜度,大幅減少 GC 負擔。在行動環境中,您可以觸發ForceGarbageCollection,在層級轉換或閒置期間 (例如沒有使用者互動時) 有效管理垃圾收集作業。此外,當遊戲處於可感知狀態或背景狀態 (例如 onStop 回呼) 時,系統也會觸發此事件,確保垃圾回收作業不會影響進行中的遊戲體驗。

詳情請參閱「垃圾收集」和「智慧指標」。

使用重定位表壓縮進行最佳化

重定位表壓縮是一種最佳化方法,可壓縮 ELF 二進位檔中的重定位表大小,縮減 Android 二進位檔大小。當 Android minSDKVersion 為 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";
}

如要套用這項最佳化措施,請確認已在「Project Settings」中啟用「Enable compression of relocation tables」,或已啟用 bEnableAdvancedBinaryCompression 變數。

如要檢查是否已正確將 RELR 壓縮套用至二進位檔,請使用 Android NDK 的 llvm-readelf 工具。

llvm-readelf -d libUnreal.so | grep RELR

實務上,建構 Unreal Engine 的 ThirdPerson 範本並使用 dumpsys meminfo 進行測量,可確認 .so mmap 的 PSS 和 RSS 使用量減少。

類別 PSS 總用量 Private Dirty Private Clean Swap Dirty RSS 總用量
.so mmap 壓縮前 170,210 24,360 141,564 0 242,204
.so mmap 壓縮後 138,031 24,748 108,976 0 210,140

紋理壓縮

使用適當的材質壓縮功能,減少整體圖像資源的記憶體用量。使用Adaptive Scalable Texture Compression (ASTC) 行動標準,可提供比 ETC2 更優異的視覺品質,或是在相同的視覺品質目標下,以較低的記憶體用量達到更高的壓縮比。

紋理串流最佳化

在行動環境中,直接使用預設的 Unreal Engine 紋理串流集區大小,可能會預先分配相對於裝置規格過大的記憶體集區。因此,建議您定義行動裝置設定檔,並根據裝置記憶體限制選取適當的紋理串流集區大小。此外,您可以使用編輯器的「統計資料」功能,檢查紋理統計資料,並找出在執行階段佔用極高解析度的高記憶體消耗紋理。搭配必要紋理解析度功能,即可對耗用大量資源的紋理強制執行限制或降低解析度上限,將資源用量控制在分配的紋理記憶體緩衝區內。