2012年2月2日 星期四

效能...效能...效能!!給我 Unity 效能



UnityIn這次整理了一些程式人員在UNITY開發上與“效能”相關,需要注意的“關鍵點”:
  1. 暫存常用的Component:
    根據官方文件的描述,每次GetComponent的呼叫,UNITY都會花點時間尋找所要求的object上。要省下這點時間,建議利用Private變數在Object Awake時,將常的用component暫存下來。
     
  2. 不要在任何Update的function內,使用Find:
    GameObject.Find這個函式用來搜尋全域、特定名稱之物件,效能上有一定的損耗,所以請盡量在Start或Awake裡使用,而非Update函式裡。若要每個Frame搜尋請改用GameObject.FindWithTag
     
  3. 多多使用BuildIn Array:
    如果物件數量是固定的,type[]的寫法是速度最快的選擇
     
  4. 運算少用“除”,多用“加、減、乘”, 根據UNITY官方數據 :
    “除法”,需要30 - 40 cycles來完成
    “加、減、乘”,只需要一兩個cycles
    “平方根、Sin、Cos” ,需要60 - 100 cycles來完成
     
  5. 單純比較向量距離,少用Normalize:
    Normalize = vec / sqrt( vec.x^2 +  vec. y^2 +  vec. z^2),所以盡量改用sqrMagnitude
     
  6. 少用Dynamic typing (JavaScript):
    使用static typing可以讓JavaScript的程式碼跑起來跟C#一樣快。依據官方數據,JavaScript在UNITY裡的執行速度是一般C++的50%、比Mozllia JavaScript快20倍。
     
  7. 只Update在畫面上或距離較近的物件,最好在需要時才開啟enable
  8. 多使用Trigger或Event delegeate來觸發或通知狀態的改變,而非每個每個Update作檢查
     
  9. 盡量避免每個Frame作Raycasting:
    對於Mesh物件作Raycasting有一定的Cost, 所以盡量避免每個Frame作Raycasting,可用Culling (Layer) mask先濾掉不必要的物件
     
  10. 別忽視SkinMesh與DrawCall的傷害:(Mobile Platform)
    目前iPhone 3GS與Nexus One以下的機種,對於SkinMesh與DrawCall的數量還是相當敏感。以手邊的測試數據來看,800面數的角色在NEXUS ONE同一畫面上,維持30FPS可撐7~9隻角色
  11. 少用Alpha testing,多用Alpha Blending:(Mobile Platform)
    依據PVR所公佈的數據,在iPhone 3GS以前的機種GPU的設計上,Alpha Testing是比Alpha Blending昂貴的

     
  12. 減少動態光照: (Mobile Platform)
    不管是Vertex或PerPixel Lighting,都會在DrawCall上增加數量,因此對於較低階的機種會有影響。PixleLight的部分,因為是對每個Pixel做光照計算,對GPU的影響會更勝Vertex Lighting。解決方法是將光bake到貼圖上。
     
  13. Mesh compress壓縮比調整到最高以降低容量:
    除非發現壓縮之後的Mesh出現,如:破洞、閃爍...等問題,不然盡量將這個選項設定的越高越好
     
  14. 手動呼叫gabage collection:
    在固定時間間隔下手動呼叫System.GC.Collect(),確保記憶體的回收,如下:

    if( Time.frameCount % m_frameFreq == 0 )
        System.GC.Collect();

    這個用法在Profiler下,可能會發現在CPU Cost上固定間隔的突波,但實際在手機上測試時,對於FPS並沒有顯著的影響。
如果各位先進覺得還有其他可以補中的點,也歡迎告訴我們,讓這篇文章更具指標性喔!!謝謝


[小編 碎碎念] 
如果你覺得這篇文章寫的不錯,請給我們一個 "贊",加油打氣吧! ^__^


作者:Bric Lin, Email: ericlin09@gmail.com
曾任職台灣某遊戲公司研發Game Engine,為書籍“OGRE 入門指南”的譯者之一,專攻Rendering技術與遊戲開發,目前為獨立開發團隊CocosPlay主程式

4 則留言:

  1. 想請問一下!
    關於第五點:
    向量正規化後長度都是1
    要怎麼用向量正規化來比較兩個向量長度??

    回覆刪除
    回覆
    1. 我想可能是Eric講錯吧(猜測)
      以下是官網解說sqrMagnitude:
      Calculating the squared magnitude instead of the magnitude is much faster. Often if you are comparing magnitudes of two vectors you can just compare their squared magnitudes.

      應該不是sqrMagnitude取代Normalize,而是取代magnitude

      刪除
    2. 哈哈哈~ 對啦!因該試M@RS講的那樣,這問題被很多朋友說了,但我一直沒有改文章內容,等等改!Thx~ MAN

      刪除
  2. 您好~看了這篇文章後,了解了很多,非常感謝! ^^
    想請問如果使用很多 靜態(全域)變數,
    會很吃資源嗎? 謝謝!!

    回覆刪除