2017年3月6日 星期一

最佳實踐 - 了解Unity效能 - 記憶體

作者:Ian 原文

翻譯:Kelvin Lo / 海龜

Memory - 記憶體

記憶體的消耗是關鍵性的指標,尤其是在像低階手機這種記憶體有限的平台。

分析記憶體耗用

在 Unity 檢查記憶體的問題最好用 Unity 放在 Bitbucket 上開源的記憶體檢查工具。整合這個工具到 Unity 很簡單,只要下載解開之後把裡面的Editor目錄拉進專案即可。

這套工具適用於 Unity 5.3 之後到目前的版本(Unity 5.6),當它連到 IL2CPP 建置的專案時可以捕捉到原生跟非原生程式記憶體耗用的資訊。

裝好工具後確定專案設定是用 IL2CPP 編譯,把專案放到設備上執行後和 Unity 編輯器的 Profiler 視窗連接,然後打開 Memory Profiler 視窗(套件有裝好的話從 Window > MemoryProfilerWindow 開啟),並按一下 Take snapshot。

在數據收集並傳回 Unity 時,設備上的應用程式會暫停一段時間。然後 Unity 編輯器會開始解析接收的數據,這會需要一些時間。對於用了大量記憶體的專案有可能會花上 10-30 分鐘。

解析過程中請耐心等候


上圖是用 iOS 裝置執行 Standard Assets 裡的場景,顯示超過 ¾ 的記憶體用量來自於四張很大的貼圖,查出是飛機的機身相關貼圖。

這個圖表每一項都可以縮放,點進去能看更詳細的資訊。

找出重複的貼圖

一個比較常見的記憶體問題是資源重複載入,貼圖通常是占用記憶體最密集的資源,貼圖重複也是在 Unity 專案裡最常發生的問題之一。

要找出是否有貼圖重複載入可以透過比對記憶體裡是否有兩個相同類型和大小的物件並檢查是否是從同一個來源載入的,在新版的 Memory Profiler 的介面裡,可以比對看起來相同物件的 Name 和InstanceID 字串。

Name 欄位表示的是載入物件的素材檔案名稱,一般來說就是檔名(不含資料夾路徑跟副檔名)。InstanceID 表示的是由 Uinty 執行時分配的內部編號,這個編號會是每次執行產生的唯一編號。(註一) 




上圖是一個簡單的案例表示,圖的左右兩側是在 Unity 5.4 裡用 Memory Profiler 所抓取的資料,圖中顯示的資源分別是在記憶體載入的兩張貼圖。兩張貼圖具有相同名稱和大小,代表它們可能是重複的。檢查了 Assets 目錄和其子目錄之後,只找到一個名為 wood-floorboards-texture 的圖檔,因此這非常有可能就是重複載入資源的問題。

記憶體裡每個單獨的 UnityEngine.Object 都會在建立時分配一個唯一的 InstanceID,由於這兩張貼圖的 InstanceID 並不同,所以可以確定它們是兩份不同的載入記憶體的貼圖資料。

由於檔名和大小相同 InstanceID 卻不同,因此可以判定這是重複載入的貼圖。(註二)



AssetBundles 和資源重複載入的關係

一般來說造成貼圖和資源重複載入記憶體最有可能的元兇是不正確的 AssetBundle 卸載,關於這部分可以參考官網的 AssetBundles 最佳實踐系列文章,關鍵在於管理載入的資源這個章節。 


檢查 Image Buffer、Image Effect 和渲染貼圖記憶體的使用情況

用 Memory Visualizer 你還能看到從渲染暫存區(Render buffers )提供給 Image effect 和 RenderTexture 物件的記憶體使用情況。

上圖是一個單純帶有一些 Image Effects 的場景所擷取的資料,Image Effects 為了要計算在記憶體配置了暫用的渲染暫存區,比較特別的是 Bloom 效果配置了一系列的暫存區。由於 Retina iOS 設備解析度很高,造成這些臨時暫存區消耗的記憶體比專案其他部分加總還多。

設想 iPad Air 2 的原生解析度是 2048x1536,這已經超出新一代的遊戲機和 PC 標準的 1080p,但卻要在平板上執行。取決於暫存區的位元深度不同,一個全螢幕的 Render buffer 可能會用掉整整 24mb甚至 36mb 的記憶體空間。想要降低這個值可以把 Render buffer 的解析度減半,可以降低約 75% 的記憶體耗用,通常視覺上來看差別也不會太大。

要改善 Image Effects 占用太多 Render buffer 和 GPU 資源的方法,可以採用 Unity 5.5 或以上版本支援的 “uber” Image Effect,官方提供一個名為 UberFX 的套件可以把許多不同層的 Image Effect 疊加在一起成單一一個效果後才送去運算, 能減少更多的開銷。

註一:請注意,編號是執行週期產生分配,同專案不同執行週期編號也不會相同。
註二:注意:如果在專案中有相同名字的貼圖,那這裡就要小心是否判斷錯誤,但相同名稱又相同大小的機率不高,仍可作為依據。


Unity最佳化 - 目錄


  1. 分析
  2. 記憶體
  3. 協同
  4. 資源審查
  5. GC和Managed Heap
  6. 字串和Text
  7. Resources目錄和一般最佳化
  8. 特別最佳化

沒有留言:

張貼留言

關於我自己

我的相片
Unity台灣官方部落格 請上Facebook搜尋Unity Taiwan取得Unity中文的最新資訊