編輯器裡的影格時間改善了,玩家裝置上的遊戲卻未必更快。比較數字前,先確認它們來自什麼建置、什麼工作負載。
判斷發佈效能,應在目標硬體上執行接近正式發佈的建置。需要找出耗時原因時,改用具備診斷功能的建置;修正後,再回到接近發佈的條件驗證。本文把這種保留少量量測程式碼的建置稱為量測建置。這是專案可採用的約定,並非三個引擎共有的建置組態名稱。
根據問題選擇建置
編輯器效能分析適合在開發中找出耗時的腳本、資源處理和記憶體配置。具備診斷功能的獨立建置(如 Unity 或 Unreal Engine 的 Development 建置)能排除編輯器處理程序的負載,並在目標裝置上深入分析。但這些結果不能直接當作發佈建置的效能。
記錄結果時附上建置組態。組態改變時,額外負擔與被測行為都可能改變。
編輯器視窗、資源處理及其他工具會共用裝置資源。診斷建置也可能包含額外程式碼和效能分析的負擔。差異取決於引擎、後端、平台與啟用的選項,沒有固定數值可以直接扣除。診斷建置中找到的高成本函式仍值得調查,只是需要回到玩家實際執行的建置確認影響。
改程式前,先固定執行條件
單靠建置設定無法保證比較可重現。先選一個情境,例如讀取存檔後沿固定路線移動攝影機,並為每次結果記錄以下條件:
- 建置 ID、提交、引擎版本、腳本後端與建置組態
- 裝置、GPU 驅動程式、解析度、畫質設定、VSync 與影格率上限
- 場景、初始狀態、輸入或路線、量測時間或影格數
- 暖機規則和快取狀態,尤其是著色器編譯與首次載入的處理方式
- 啟用的量測程式碼、取樣間隔,以及缺漏或丟棄的樣本
先把未修改的基準多跑幾次,再測候選建置。如果基準之間的波動已接近預期改善幅度,應先檢查測試條件。重複執行有助於發現波動,但僅靠重複執行還無法證明結果在統計上可靠。手機與筆記型電腦還要保持相近的供電及溫度條件。
首次載入與暖機後的遊戲過程應分開測試。量測穩定狀態時,排除著色器編譯可能合理;若要調查首次啟動的卡頓,同樣的處理卻會把問題本身排除掉。
設定量測建置
Unreal Engine:引擎支援時使用 Test
Epic 將 Test 定義為保留部分主控台命令、統計與效能分析工具的 Shipping 組態。需要發佈等級的最佳化與這些診斷工具時,可以從 Test 開始。Development 也啟用了大部分最佳化,不能把它等同於未最佳化的 Debug 建置。
先檢查引擎安裝。Installed Build 預設包含 Shipping、Development 與 DebugGame。Test 通常需要從原始碼建置的引擎,或包含 Test 的自訂 Installed Build。在命令中選擇 Test,不會補上缺少的二進位檔。
支援 Test 的引擎可參考以下 Windows 封裝命令。替換專案路徑,並使用安裝目錄中的 Automation Tool 啟動腳本:
RunUAT.bat BuildCookRun -project="C:/Path/MyGame.uproject" -platform=Win64 -clientconfig=Test -cook -stage -pak -package -build
在實際產生的套件中確認所需命令和計數器是否可用。不要假設 UE_LOG 一定存在:Test 和 Shipping 預設會在編譯時移除日誌,變更該設定可能需要重新建置引擎。量測程式碼應限於專案中必要的位置。如果只能用 Development 調查,最後仍應使用專案支援的量測方式在 Shipping 中驗證。
Unity:後端與編譯設定和發佈版本一致
在 Unity 6 建立專用的建置設定檔,進行接近發佈環境的比較時關閉 Development Build。產品使用 IL2CPP,就測 IL2CPP;使用 Mono,就保留 Mono。IL2CPP 的 Release 或 Master 組態也應與產品一致。比較程式修改時同時更換後端,會引入另一個變因。
為 Unity Profiler 保留獨立的 Development 設定檔。連接 Profiler 與 Deep Profiling 是診斷選項,不應無意間留在發佈效能比較中。Unity 6 之前的版本可用 BuildPipeline 腳本維持同樣的區分。
可使用設定檔專屬的腳本定義符號,讓診斷標記只在量測建置中生效:
using System.Diagnostics;
public static class Measure
{
[Conditional("MEASUREMENT")]
public static void Mark(string label)
{
UnityEngine.Debug.Log($"[measure] {label} @ {UnityEngine.Time.frameCount}");
}
}
在設定檔的 Scripting Defines 中加入 MEASUREMENT,再於測試情境的開始、結束等位置呼叫 Measure.Mark。這是日誌標記,不是影格時間收集器。不要每個影格都呼叫:字串格式化和日誌寫入也有成本。沒有該符號時,[Conditional] 會移除呼叫位置,但不會從組件中移除方法本體。
Godot:發佈匯出加量測功能標籤
複製匯出預設,關閉 Export With Debug。算繪器、平台與匯出範本應和預計發佈的版本一致。僅為建立量測預設,無需編譯自訂引擎範本。
在預設中加入 measurement 等自訂功能:
custom_features="measurement"
C# 專案可在測試情境開始處讀取標籤:
if (OS.HasFeature("measurement"))
{
GD.Print($"[measure] scenario-start frame={Engine.GetFramesDrawn()}");
}
自訂功能標籤只對匯出的專案生效,一般的編輯器執行不會使用它們。請檢查匯出的執行檔。和 Unity 範例一樣,這段程式碼僅標記情境中的位置,指標需要另外收集;收集成本與設定也應在各次執行中保持一致。
依實際取樣粒度判讀指標
60 FPS 的影格預算約為 16.67 ms,30 FPS 約為 33.33 ms。除了平均 FPS,也要檢查影格時間分布。P95 是 95% 的觀測值不超過的數值。更罕見的嚴重卡頓仍可能被隱藏,因此還應視需要查看更高百分位、超出影格預算的次數與時間軸。
先確認統計對象。定期上傳的遙測樣本算出的 P95,是這些樣本的 P95,不一定代表每一個算繪影格。比較兩份報告前,應記錄取樣方式。
若問題與位置有關,附上場景、座標及攝影機方向。「站在門口、朝向物件密集的房間時出現慢影格」比整段工作階段的平均值更有助於重現,但還不能確定是哪個物件或系統造成了成本。
找到原因後,重跑原來的測試
依記錄的條件重現問題,再用 Unity Profiler、Memory Profiler、Unreal Insights 或 Godot 的效能分析器調查。Godot 內建腳本效能分析器適用於 GDScript;深入分析 C# 程式碼時,需要合適的 .NET 效能分析器。
修改一個疑似成本來源後,在量測建置中重跑原來的情境。確認多次執行仍有改善,並檢查記憶體、載入或影格內的其他工作是否惡化。診斷追蹤變快只是中間結果。
同樣的資料也能協助判斷是否增加特效或物件。但算繪執行緒有餘裕,不代表 GPU 時間和記憶體也有餘裕。加入內容後,仍需在相同的目標裝置條件下量測。
用 Framedash 保留可檢查的比較結果
Framedash 的儀表板熱圖可在地圖上查看已收集的效能樣本,並依建置、平台和已記錄的屬性篩選。各引擎的 SDK 設定與可用收集器不同,請參閱 Unity、UE5 及 Godot C#。使用圖表前,先確認目標建置實際傳送了哪些指標。
Unity 使用者可從效能執行比較試行功能開始:在自己的 PC 上收集基準、未修改的重複執行與候選執行,再檢查條件和影格間隔摘要,不需要地圖。這些間隔量的是 SDK Update 回呼之間的時間,不是 GPU 完成或畫面呈現時間。試行功能會說明證據是否可比較,不會自動判定效能回歸合格與否。
先選一個可重現的情境與一個待驗證的修改。把基準結果、執行條件和候選結果放在一起,下次才能繼續回答同一個問題。