一個沒有深入結論的小測試,所以標題是問號。先直接給結果:
- 測試版本:Unity 5.5.0f3,PC Editor 環境
- 測試的物件:Unity 內建的 Sphere
- 測試的數量:300 * 300 (即 90000 個)
詳細過程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| using System.Collections; using System.Collections.Generic; using UnityEngine;
public class GameObjectLoadTest : MonoBehaviour { public GameObject TestPrefab; public int TestAmountX = 100; public int TestAmountY = 100; public float ObjectGrid = 1f; public Vector3 Moving = new Vector3 (10, 10, 10); private List<GameObject> m_gameObjectList = new List<GameObject>();
void Start () { float timer; timer = Time.realtimeSinceStartup; InstantiatePrefab (); Debug.Log (string.Format ("InstantiatePrefab: {0}", Time.realtimeSinceStartup - timer)); timer = Time.realtimeSinceStartup;SetIntoGrid (); Debug.Log (string.Format ("SetIntoGrid: {0}", Time.realtimeSinceStartup - timer)); timer = Time.realtimeSinceStartup; SetAllActive (false); Debug.Log (string.Format ("SetAllActive(false): {0}", Time.realtimeSinceStartup - timer)); timer = Time.realtimeSinceStartup; SetAllActive (true); Debug.Log (string.Format ("SetAllActive(true): {0}", Time.realtimeSinceStartup - timer)); timer = Time.realtimeSinceStartup; MovingAll (); Debug.Log (string.Format ("MovingAll: {0}", Time.realtimeSinceStartup - timer)); } private void InstantiatePrefab () { for (int x = 0; x < TestAmountX; x++) { for (int y = 0; y < TestAmountY; y++) { m_gameObjectList.Add(GameObject.Instantiate<GameObject> (TestPrefab, this.transform)); } } } private void SetIntoGrid () { for (int x = 0; x < TestAmountX; x++) { for (int y = 0; y < TestAmountY; y++) { m_gameObjectList[x * TestAmountY + y].transform.localPosition = new Vector2(x * ObjectGrid, y * ObjectGrid); } } } private void SetAllActive (bool active) { for (int x = 0; x < TestAmountX; x++) { for (int y = 0; y < TestAmountY; y++) { m_gameObjectList[x * TestAmountY + y].gameObject.SetActive(active); } } } private void MovingAll () { for (int x = 0; x < TestAmountX; x++) { for (int y = 0; y < TestAmountY; y++) { Vector3 newPos = m_gameObjectList[x * TestAmountX + y].transform.localPosition + Moving; m_gameObjectList[x * TestAmountY + y].transform.localPosition = newPos; } } } }
|
沒有結論的說明
一般來說,提到物件的隱藏,會有三個效能不同的手段:
- 銷毀物件,需要時再建立
- 關閉物件,需要時再啟動 (SetActive)
- 移到鏡頭外
依照隱藏與顯示的切換頻率,以及硬體狀況,會針對不同物件採用不同的手段。
這次測試單純只是想知道運算效能上的差異比例,然後這次的測試結果:
很明顯,GameObject.Instantiate 創建物件最耗效能,SetActive 相對節省效能一點,移動物件則最節省效能。
不過三個方法中,物件是否在場景中,Component 是否運作中等因素,對於 CPU、GPU、記憶體所產生的負擔也各自不同,所以並不能單就這筆數據決定三種方法的優劣,一切還是要因事制宜為主。
不過 SetActive 一關一開的效能消耗比我想像中高,然後關閉物件比開啟物件更耗效能?真神秘啊 …
追加測試
這次測試總共進行了兩次物件的關閉與開啟 (SetActive),並加上 Destory 的測試。
結果第二輪的物件關閉就不再大幅消耗效能了?真是太神奇了 … 不知道隔了一段時間之後再關閉物件又是如何? 然後同為移動物件,物件之間的相對位置似乎也會影響效能? 感覺這個測試流程建立的太簡陋,這些測試都是在 Start 中一次完成,所以沒有進到畫面 render 的階段,也沒有把一些不定因素排除,所以這個結果僅供參考,跟實際遊戲運作時的狀況可能有落差。
** 額外的結論:從測試中可以看出來,SetActive 的相關工作基本上都是在行內直接進行,所以在一個 Update 之中因為邏輯判斷對一個物件重複開開關關,會有無謂的效能消耗。(雖然我知道,有時候這樣很方便)