Unity遊戲項目常見性能問題
Unity技術支持團隊經常會對有需求的客戶公司項目進行遊戲項目性能審查與優化,在我們碰到過的各種項目相關的問題中也有很多比較共同的方面,這裏我們羅列了一些常見的問題並進行了歸類,開發者朋友們可以參考下。
資源導入
- 紋理沒有壓縮
在很多情況下,美術會覺得紋理壓縮後效果不理想。我們建議的是:可以把原圖的分辨率長寬都擴大一倍,保持原有壓縮格式。這樣壓縮過後的文件還是比不壓縮的文件要小,並且視覺效果可以得到較大的改善。
- 紋理導入設置中的 Read/Write Enabled 處於勾選狀態
開啟紋理導入設置中 Read/Write Enabled,紋理在傳到GPU之後,CPU端的數據也會一直保留在內存中。因為在移動端顯存共享內存,會導致內存占用加倍。因此需要註意是否有需要在CPU端訪問的紋理,比如:需要通過腳本獲取紋理像素的情況下,就要開啟紋理導入設置中的 Read/Write Enabled。
- 模型文件導入設置中 Read/Write Enabled 處於勾選狀態
除了需要腳本中訪問的網格,作為網格碰撞器中的網格,腳本中用StaticBatchingUtility.Combine靜態合批的網格,以及粒子系統發射的網格之外,其它模型建議不要勾選此項 ,否則會在內存也保留一份網格實例占用內存。
- 模型導入設置[Rig]選項頁中Optimize GameObject沒有勾選
建議開啟Optimize GameObject,這個選項可以把SceneManager中用於skinning的節點都去除,節省了場景節點樹更新以及查詢的CPU消耗,對於需要做掛點的節點可以添加到例外列表中。
- 使用第三方音頻插件時沒有禁用Unity內置音頻
不需要使用Unity內置音頻模塊的時候,建議Editor中通過勾選Edit->Project Settings->Audio->Disable Unity Audio來完全禁用FMOD模塊,避免不必要的CPU消耗
CPU常見性能問題
- 頻繁調用的Camera.main
建議腳本做好Main Camera的Cache。Camera.main實際為GameObject.FindGameObjectsWithTag(“MainCamera”)調用,主要因為引擎無法得知用戶通過腳本設置的MainCamera,CPU消耗較高。
- 腳本中大量UnityEngine.Object的判等操作
建議改為用InstanceID來判斷即Object. GetInstanceID,運行期間保證唯一。 因為Object的判等還有額外的耗時操作,而Int類型的判等就非常快速了。同理,使用Object作為key的數據結構也建議改用InstanceID做key。
- 用於查詢操作的數據使用list數據結構
List線性結構Contains的耗時非常高,建議改為hashset,hashtable之類的查詢操作效率高的數據結構。
- 加載資源時每幀從Assetbundle加載的Asset數量沒有限制
在場景內每幀從Assetbundle加載的Asset數建議限制在2到5個,數量高時耗時過長容易造成卡頓。
內存常見問題
- 加載場景的時候有 一段內存尖峰
常見的情況是有無索引的資源被加載進來,然後因為UnloadUnusedAssets被卸載掉。內存尖峰基本都是對遊戲本身無用的內存,但是可能會因此造成遊戲在內存緊張的機器上被強制關閉。
- 靜態索引導致的內存泄漏
一些內存占用較大的資源如紋理,因為有靜態索引而無法在切換場景或者調用UnloadUnusedAssets時被卸載掉,因此內存的泄漏量會隨著用戶切換場景的次數而增加。
- Mono內存池總大小與當前使用大小的差值較大
這個值越大說明有越多的不必要內存池擴展,比如說在同一幀內有加載大量資源,實例化大量對象等,可能讓內存池瞬間膨脹的操作。
- GC分配量較大
項目Review過程中,除了CPU時間占用和內存分配量,我們還會留意腳本函數的GC分配。GC分配越頻繁,量越大,由於Mono內存池可用內存不足導致的GC.Collect(造成卡頓原因之一)調用就越頻繁,並且可能引起mono內存池不必要的擴展,因此腳本函數的GC分配量是既影響CPU也影響內存的重要參數。對於GC分配量。
我們建議的參考數值為:
對於基本每幀都會分配GC的函數,GC分配量大於2KB的建議都確認下是否有可能把臨時變量抽取出來。
對於偶爾分配GC的函數,GC分配量大於10KB的建議都確認下分配的數據結構是否有優化空間。
GPU常見性能問題
- 特效渲染的Pass數量較多
一些特效的渲染可以合並到同一個Pass以節省GPU開銷,另外RenderTexture在可以共用的情況下盡量共用
- 同屏面數過多
同屏面數建議在20W以下,較優情況是控制在10W以內
- UI元素在需要隱藏的時候使用了設置Alpha為0的方式
實際上GPU依然需要對UI mesh進行渲染,建議不要通過設置Alpha為0的方式來隱藏UI。
- 當使用網格作為地形時,適當切分地形網格
在網格頂點數很高情況下需要依靠硬件裁剪來剔除頂點,比較消耗GPU性能,建議按照大概的同屏可見範圍來切分地形網格。
- UI元素過多依賴多層元素的混合來達到美術效果
這樣會造成較多的Overdraw,建議盡量通過預制紋理來做到想要的效果。
Unity遊戲項目常見性能問題