關於Unity動畫系統優化,你可能遇到這些問題

原文鏈接:blog.uwa4d.com/archives

周末晚上來個小小的充電!接之前的Unity性能優化大合集之渲染篇、載入篇後,我們再來談談Unity項目開發中動畫系統的優化方法。為什麼Animator的CPU耗時過高?為什麼我們推薦開啟Optimize GameObject選項?如何巧用SkinnedMeshRenderer.BakeMesh...雖然相較其他模塊,動畫系統模塊的性能瓶頸壓力普遍來說稍小,但蒼蠅腿也是肉啊,一起來普及一些動畫系統模塊的優化技巧,把性能做到極致吧:)

關鍵字

內存泄漏

資源製作

一、內存泄漏

Q1:我們測試發現,當Animator Controller掛載的動作比較多時,即使切換成另外一個動作很少的Animator Controller,任務的動作信息還是不會釋放。我們將英雄打成一個AssetBundle,然後又把定製的Runtime Animator Controller載入替換進去,英雄自帶的Runtime Animator Controller是掛了所有動作的。我們試了替換Runtime Animator Controller之後,把先前的Runtime Animator Controller Destroy掉,貌似內存也沒釋放。

銷毀Animator Controller並不會釋放其內所引用的AnimationClip資源的,所以內存沒有明顯下降是正常的。建議按照以下方式做個試驗:

1)銷毀Animator Controller 後,通過Unity Profiler立刻真機Take Sample,查看Animation Clip的Ref count是否為0;

2)如果不是,則需要進一步查看這些資源的索引出處;如果為0,則可以通過UnloadUnusedAssets或UnloadAsset來將其從內存> 中去除。

二、資源製作

Q1:Optimize Game Objects對於老版本的Animation系統有沒有作用呢?

沒有作用。Optimize Game Objects功能是Unity4.3版本推出的功能,且僅對Mecanim動畫系統起作用。如果可以的話,建議研發團隊儘可能使用Mecanim來作為項目動畫系統的解決方案。

Q2:在UWA性能報告中,你們建議我們選中Optimize GameObject來提升Mecanim動畫模塊的運行性能,但是這個功能會隱蔽角色骨骼,那麼要掛載該骨骼上的這個點就無法查詢了,有什麼辦法可以解決這個問題嗎?

是的,開啟Optimize GameObject默認情況下會將動畫網格下的所有骨骼結點隱藏,但是,你可以通過「Extra Transform to Expose」查看你想通過腳本獲取的骨骼結點,這樣既可以提升該角色的動畫模塊性能,又可以達到獲取某個關鍵結點的需求。

Q3:SkinnedMeshRenderer.BakeMesh這個函數一般是什麼時候調用呢?在Instantiate後調用么?

SkinnedMeshRenderer.BakeMesh 的作用在於:將一個蒙皮動畫的某個時間點上的動作,Bake成一個不帶蒙皮的Mesh,從而可以通過自定義的採樣間隔,將一段動畫轉成一組Mesh序列幀。而後在播放動畫時只需選擇最近的採樣點(即一個Mesh)進行賦值即可,從而省去了骨骼更新與蒙皮計算的時間。

該方法的優點是用內存換計算時間,在場景中大量出現同一個帶動畫的模型時,效果會非常明顯。該方法的缺點是內存的佔用極大地受到模型頂點數、動畫總時長及採樣間隔的限制。因此,該方法只適用於頂點數較少,且動畫總時長較短的模型。同時,Bake的時間較長,因此需要在載入場景時完成。

比較經典的適用場景為MOBA遊戲中的小兵。

Q4:在UWA給出的報告中,我們發現了Animator過高的情況,其中UI和角色各佔一半。我們之前一直選擇CullUpdateTransforms,通過閱讀Unity官方文檔發現CullCompletely更符合我們的現狀,想請教下如果我們選擇CullCompletely可能會有什麼隱患呢?

使用 CullCompletely 在開啟 RootMotion 時是需要注意的,比如人物有一個巡邏動畫是通過 RootMotion 製作的,那麼在人物走出屏幕後,其動畫就停止了,即不會再走回屏幕中。

Q5:我們在美術製作時做了40根骨骼,但在動作中僅用到了其中的30根。這種做法和30根骨骼用到了30根相比,在蒙皮計算上會明顯增加嗎?(Animation經過了壓縮處理)

理論上是有增加的,骨骼運算均是每個骨骼階段的Matrix乘起來的,所以理論上會有開銷。建議使用Optimize GameObejct選項,可以減少一些不必要的CPU開銷。

推薦閱讀:

一個關於渲染管線中坐標變換的簡單實例
Unity3D插件開發教程(四):獲取地址組件
從零開始學基於ARKit的Unity3d遊戲開發系列16
聊聊Unity里的嵌套Prefab
從零開始學基於ARKit的Unity3d遊戲開發系列10

TAG:Unity游戏引擎 | 性能优化 | 手机游戏开发 |