[測試] Unity Instantiate 與 SetAcive 的效能差異? – Unity Instantiate v.s. SetAcive?

一個沒有深入結論的小測試,所以標題是問號。先直接給結果:

1492069298795

1492071078733

  • 測試版本:Unity 5.5.0f3,PC Editor 環境
  • 測試的物件:Unity 內建的 Sphere
  • 測試的數量:300 * 300 (即 90000 個)

詳細過程:

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)
  • 移到鏡頭外

依照隱藏與顯示的切換頻率,以及硬體狀況,會針對不同物件採用不同的手段。

這次測試單純只是想知道運算效能上的差異比例,然後這次的測試結果:

1492069298795

很明顯,GameObject.Instantiate 創建物件最耗效能,SetActive 相對節省效能一點,移動物件則最節省效能。

不過三個方法中,物件是否在場景中,Component 是否運作中等因素,對於 CPU、GPU、記憶體所產生的負擔也各自不同,所以並不能單就這筆數據決定三種方法的優劣,一切還是要因事制宜為主。

不過 SetActive 一關一開的效能消耗比我想像中高,然後關閉物件比開啟物件更耗效能?真神秘啊 …

追加測試

1492071078733

這次測試總共進行了兩次物件的關閉與開啟 (SetActive),並加上 Destory 的測試。

結果第二輪的物件關閉就不再大幅消耗效能了???真是太神奇了 … 不知道隔了一段時間之後再關閉物件又是如何?

然後同為移動物件,物件之間的相對位置似乎也會影響效能?

感覺這個測試流程建立的太簡陋,這些測試都是在 Start 中一次完成,所以沒有進到畫面 render 的階段,也沒有把一些不定因素排除,所以這個結果僅供參考,跟實際遊戲運作時的狀況可能有落差。

** 額外的結論:從測試中可以看出來,SetActive 的相關工作基本上都是在行內直接進行,所以在一個 Update 之中因為邏輯判斷對一個物件重複開開關關,會有無謂的效能消耗。(雖然我知道,有時候這樣很方便)

Advertisements

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s