在Unity 5中優化SkinnedMeshRenderer


 

過早優化是萬惡之源”——Donald Knuth
        不少開發者在前期開發過程中對算法等類似的開銷都甚少關心,而是更傾向於盡可能簡單的解決某個問題,后面必要時再進行優化。這能極大加速開發進度,並保證代碼簡潔。但開發后期通常會出現的瓶頸就是圖形資源,而優化圖形渲染這一塊比較有難度。
        本文將分享作者Lamebait在使用Unity5制作沙盤游戲過程中優化SkinnedMeshRenderers的相關步驟提供給大家參考。

        第一次迭代——使用不帶動畫的網格

        每個城市街區約有15個網格,首先最顯著的問題就是不斷被加載到游戲中Mesh數量。當街區數量增長到數百之后,DrawCall數量也飆升到大多硬件所不能承受之高。Unity支持網格批處理,能減少一部分DrawCall。但所有網格都是有動畫的,所以這些網格用的是SkinnedMeshRenderer組件而非MeshRenderer,Unity不支持對SkinnedMeshRenderer進行批處理。

       第二次迭代——SkinnedMeshRenderer.BakeMesh()

        所有的建築和樹木都只在它們出現和消失的時候有漸入和漸出的動畫,一旦穩定下來之后就是完全靜止的了,那可否在此期間將它們變為MeshRenderer呢?
        如果使用帶有MeshRenderer的無動畫網格,通過開關選擇使用MeshRenderer還是SkinnedMeshRenderer,結果可能會發現有幾個網格與其SkinnedMeshRenderer的最終狀態不太匹配,所以這條路不通。
        下圖展示了SkinnedMeshRenderer的最終狀態與靜態網格本身的差別。

        SkinnedMeshRenderer中有個BakeMesh()函數,功能是按照網格當前的動畫狀態創建網格數據快照,並輸出這個網格數據用於其它地方。這樣就可以將輸出的新網格傳給MeshRenderer然后享受自動批處理的功能。但事情並非如此簡單。
        下面創建包含各種網格類型的字典,以便多個MeshRenderer可以共享同一個網格,然后讓Unity進行批處理。不論何時增加了新的網格,它都會被烘焙出來並加到字典中。但這樣會愛導致進行網格類型切換后網格的高度略微有點拉伸。這是因為建築的縮放值不是0,以致SkinnedMeshRenderer輸出的網格本身被縮放了一次,而這個網格在應用到GameObject上的時候由於GameObject本身的縮放值又被縮放了一次。解決這種矛盾的辦法就是先將建築的縮放值設為1,烘焙后再設回原始值。
        到此整個切換看起來完全無縫。但這是有代價的,因為Unity也不支持對使用了陰影的MeshRenderer進行批處理。而關閉陰影又會對游戲效果大打折扣,所以必須想想其它辦法。

        第三次迭代——網格合並

        還可以手動批處理,因為網格是可以合並成一張大網格的。當然也有些限制,如網格材質必須相同,單個網格的三角形數量有限等。還好這個游戲的建築和樹木總共才用到了三種不同的材質,所以可以將整個街區合並成最多三張大網格。
        基本上,創建CombineInstance后將BakeMesh()輸出的網格傳給它並加上Transform。最重要的是確保Transform的變換矩陣中GameObject本身的縮放值都是無效的,否則網格會像上文提到那樣錯誤變形。合並后網格的最終結果會應用到網格之前所在的GameObject,然后在街區狀態變為靜止后移除。
        整個過程比較棘手。游戲中很多因素都會導致奇怪的效果,對於每個因素及每個可能的組合都要單獨測試。但結果證明這是值得的,現在游戲在有陰影的情況下幀率也非常可觀!
        合並的紅色網格如下圖:

       第四次迭代——更高一級

        這游戲設計的特色之一就是每個陣營最終的街區都會在生成之后被保留,所以如果街區從未改變過,可以將它們合並到一起。一個個合並會遭遇前面提過的網格大小限制。而將城市分為幾個格子可以將幾個街區的網格合並為單個,從而進一步降低DrawCall。效果如下圖:

        總結

        本文最重要的三點:

  • 不要過早優化,可以適當晚一點。
  • 善於發現漏洞!如果某個東西不適用於X,那能否暫時將它變為Y呢?
  • 用創造性的技巧換取性能。


       內容下載鏈接:
       https://github.com/Ryxali/StateCapital


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM