2017年9月9日 星期六

[Unity]物件 顯示/隱藏 之簡易效能評比

我們要在Unity控制物件於畫面中的顯示/隱藏時, 主要方法有:
  • 使用GameObject.SetActive直接開關整個GameObject
  • 開關GameObject上的Render
  • 將GameObject移進/移出畫面
  • 改變GameObject的Layer
  • 改變GameObject的Scale, 設0為隱藏

對此我做了一個簡單的範例來測試這些方法的效能差異

測試專案: https://github.com/GooKu/Unity2017Test.git
測試碼: https://github.com/GooKu/Unity2017Test/blob/master/Assets/ShowHideTest/ShowHideTest.cs
測試scene: ShowHideTest.unity
環境資訊
CPU: i5-4460(3.2GHz)
VGA: AMD R7770-PMD1GD5
OS: Windows 10
Unity版本: 2017.1.0f3 Personal
Platform: PC Standalone
----------
此測試中使用的測試物件為裝有3個Sprite Render的GameObject物件, 其3個Sprite Render使用的是同一張128x128的JPG貼圖, 但用的是不同子sprite

此測試物件的模型設計概念為:我們視覺上想控制顯示的物件單位, 常常是由許多render單位組成(可能是為動畫控制, avatar需求, 或其他因素), 因此使用一個GameObject乘載多個render的結構來做測試

擊點對應按鈕同時操作10000個測試物件的顯示/隱藏, 得到的結果如下

操作方法 \ 時間(ms) 顯示 隱藏
隱藏後fps
GameObject.SetActive 76 27
60
Render.enabled 22 22
60
Move position 9 9
60
GameObject.layer 19 19
25
transform.localScale 9 9
13

GameObject.SetActive: 效能開銷為最高, 尤其是在開啟GameObject時所花的時間是其他人的數倍

Render.enabled: 效能開銷其次, 開銷有部分為Dictionary的索引開銷, 但實在無法細分因此還是算在一起, 不過通Dictionary的索引開銷是相對可以忽略的

GameObject.layer: 效能開銷接近但低於Render.enabled, 但值得一提的是, 在設到隱藏layer後, Profiler仍顯示有很高的Gfx.WaitForPresent開銷, 這個是CPU在等GPU的時間, 也應此隱藏後的fps仍不高
但照理來說, 沒有camera要畫隱藏layer時應該不會有這個開銷, 這有可能是Unity的bug?


移動GameObject的位置: 最省效能的作法, 幾乎沒什麼開銷

transform.localScale: 雖然起停開銷和移位置一樣, 但隱藏後的fps和隱藏前幾乎一樣;
Profiler來看, 既使scale 0 Camera.Render仍會對測試物件做處理




以上, 如果要控制的為純顯示物件, 也就是不需要顧慮其上GameObject的生命週期運行以及其位置資訊時, 建議直接控制其位置來達到顯示/隱藏的效果

沒有留言:

張貼留言