Unity性能優化——資源優化(一)

實際項目中發現的許多問題都是源自無心之過:臨時的“測試”更改和疲憊不堪的開發人員的誤點擊可能會暗地裏添加性能不良的資源或更改現有資源的導入設置。

對於任何大規模的項目,最好是將防止人爲錯誤作爲第一道防線。編寫一小段代碼來禁止將 4K 未壓縮紋理添加到項目中,是相對簡單的事情。

但是,這種錯誤操作卻是十分常見的。一個 4K 的未壓縮紋理會佔用 60 MB 的內存。在低端移動設備(如 iPhone 4S)上,佔用的內存超過大約 180–200 MB 是十分危險的。如果誤添加此類紋理,就會無意中佔用應用程序內存預算的三分之一到四分之一,並導致難以診斷的內存不足錯誤。

雖然現在可以使用內存性能分析器來跟蹤這些問題,但最好在最初就確保這些錯誤不可能發生。

使用 AssetPostprocessor

Unity Editor 中的 AssetPostprocessor 類可用於在 Unity 項目上強制執行某些最低標準。導入資源時將回調此類。要使用此類,應繼承 AssetPostprocessor 並實現一個或多個 OnPreprocess 方法。重要的方法包括:

  • OnPreprocessTexture

  • OnPreprocessModel

  • OnPreprocessAnimation

  • OnPreprocessAudio

請參閱 AssetPostprocessor 的腳本參考,瞭解更多可能的 OnPreprocess 方法。

public class ReadOnlyModelPostprocessor : AssetPostprocessor {

   public void OnPreprocessModel() {

        ModelImporter modelImporter =

 (ModelImporter)assetImporter;

        if(modelImporter.isReadable) {

            modelImporter.isReadable = false;

            modelImporter.SaveAndReimport();

        }

    }

} 

 

這是一個在項目中 AssetPostprocessor 強制執行規則的簡單示例:

每次將模型導入項目時,或者模型的導入設置發生更改時,都會調用此類。該代碼只是檢查 Read/Write enabled 標誌(由 isReadable 屬性表示)是否設置爲 true。如果是,則強制將標誌位更改爲 false,然後保存並重新導入資源。

請注意,調用 SaveAndReimport 會導致再次調用此代碼片段!但是,因爲現在已確保 isReadable 爲 false,所以此代碼不會產生無限的重新導入循環。

此變更的原因將在下面的“模型”部分討論。

通用資源規則

紋理

禁用 read/write enabled 標誌

Read/Write enabled 標誌使紋理在內存中保留兩次:一次保存在 GPU 中,一次保存在 CPU 可尋址內存中(1)(注意: 這是因爲大多數平臺上從 GPU 內存回讀的速度極慢。將紋理從 GPU 內存讀入臨時緩衝區以供 CPU 代碼(例如 Texture.GetPixel)使用將是非常低效的)。在 Unity 中,默認情況下禁用此設置,但可能會無意中將其打開。

只有在着色器之外操作紋理數據時(例如使用 Texture.GetPixel 和 Texture.SetPixel API 時)才需要 Read/Write Enabled,否則應儘可能避免使用它。

儘可能禁用 Mipmap

如果對象相對於攝像機具有相對不變的 Z 深度,則可禁用 Mipmap,這樣將大約節省加載紋理所需的內存的三分之一。如果對象的 Z 深度會發生變更,則禁用 Mipmap 可能導致 GPU 上的紋理採樣性能變差。

通常情況下,這對於 UI 紋理以及在屏幕上以恆定大小顯示的其他紋理非常有用。

壓縮所有紋理

使用適合項目目標平臺的紋理壓縮格式對於節省內存至關重要。

如果所選的紋理壓縮格式不適合目標平臺,Unity 會在加載紋理時解壓縮紋理,這將消耗 CPU 時間和額外的內存。此問題在 Android 設備上最常見,因爲此類平臺通常因芯片組不同而支持截然不同的紋理壓縮格式。

實施合理的紋理大小限制

雖然很簡單,但也很容易忘記調整紋理大小或無意中更改紋理大小導入設置。應確定不同類型紋理的合理最大值,並通過代碼強制執行這些限制規則。

對於許多移動應用程序,2048x2048 或 1024x1024 足以滿足紋理圖集的要求,而 512x512 足以滿足應用於 3D 模型的紋理的要求。

模型

禁用 Read/Write enabled 標誌

模型的 Read/Write enabled 標誌與紋理的上述相應標誌具有相同的工作原理。但是,模型在默認情況下會啓用該標誌。

如果項目在運行時通過腳本修改網格 (Mesh),或者如果網格用作 MeshCollider 組件的基礎,則 Unity 會要求啓用此標誌。如果模型未在 MeshCollider 中使用並且未被腳本操縱,請禁用此標誌以節省一半模型內存。

在非角色模型上禁用骨架

默認情況下,Unity 會爲非角色模型導入通用骨架。如果模型在運行時實例化,則會導致添加 Animator 組件。如果模型沒有通過動畫系統進行動畫處理,則會給動畫系統增加不必要的開銷,因爲每幀都必須運行一次所有激活的 Animator。

在非動畫模型上禁用骨架可以避免自動添加 Animator 組件,並防止可能無意中向場景添加不需要的 Animator。

在動畫模型上啓用 Optimize Game Objects 選項

Optimize Game Objects 選項對動畫模型有着顯著的性能影響。禁用該選項後,Unity 會在每次實例化模型時創建一個大型變換層級視圖來鏡像模型的骨骼結構。此變換層級視圖的更新成本很高,尤其是在附加了其他組件(如粒子系統或碰撞體)的情況下。它還限制了 Unity 通過多線程執行網格蒙皮和骨骼動畫計算的能力。

如果需要暴露模型骨骼結構上的特定位置(例如暴露模型的雙手以便動態附加武器模型),則可在 Extra Transforms 列表中將這些位置專門設爲允許狀態。

如需瞭解更多詳細信息,請參閱 Unity 手冊的 Model Importer 頁面。

儘可能使用網格壓縮

啓用網格壓縮可減少用於表示模型數據不同通道的浮點數的位數。這樣做可能導致精確度的輕微損失,在用於最終項目之前,美術師應評估這種不精確性的影響。

在給定壓縮級別中使用的具體位數在 ModelImporterMeshCompression 腳本參考中有詳細說明。

請注意,可對不同的通道使用不同級別的壓縮,因此項目可選擇僅壓縮切線和法線,同時保持 UV 和頂點位置不壓縮。

注意網格渲染器設置

將網格渲染器添加到預製件或遊戲對象時,請注意組件上的設置。默認情況下,Unity 會啓用陰影投射和接收、光照探針採樣、反射探針採樣和運動矢量計算。

如果項目不需要這些功能中的一個或多個,請確保通過自動腳本關閉它們。添加網格渲染器的任何運行時代碼也都需要處理這些設置。

對於 2D 遊戲,在啓用陰影選項的情況下意外地將網格渲染器添加到場景會爲渲染循環添加完整的陰影 pass。通常情況下,這是對性能的浪費。

音頻

適合平臺的壓縮設置

應爲音頻啓用與可用硬件匹配的壓縮格式。所有 iOS 設備都包含硬件 MP3 解壓器,而許多 Android 設備本身支持 Vorbis。

此外,應將未壓縮的音頻文件導入 Unity。Unity 在構建項目時總是會重新壓縮音頻。無需導入壓縮的音頻再重新壓縮,這隻會降低最終音頻剪輯的質量。

將音頻剪輯強制設置爲單聲道

很少有移動設備實際配備立體聲揚聲器。在移動平臺項目中,將導入的音頻剪輯強制設置爲單聲道會使其內存消耗減半。此設置也適用於沒有立體聲效果的任何音頻,例如大多數 UI 聲音效果。

降低音頻比特率

儘量降低音頻文件的比特率,以進一步節省內存消耗和構建的項目大小,但這種情況需要諮詢音頻設計師。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章