我要加入

UNITY3D聖殿-自由的遊戲設計天堂

會長:stormcorn / stormcorn開設日:2013-03-21 18:05:22

  • EXP

  • 資金24183  
  • 招募制度:自由加入制
  • 成員:1740 人
  • 昨日人氣:0

物件池Object Pool

推上精選編輯

近期編輯:ADSL1234567B ...看更多

目的
降低需要經常性初始化的情況,改善效能。

時機
  • 經常性的產生、銷毀動作,且初始化成本過高。
  • 有效能需求。

物件池是一個很重要的概念,每次產生GameObject時,均需要配置一塊記憶體來放這個GameObject,而不使用時再銷毀該GameObject,當這種動作非常頻繁時,效能會非常地糟。因此需要將不再使用的物件回收再利用,特別是那些初始化成本很高的。雖然Unity native核心已經有對自己的物件做object pool的設計,但其Managed的部分並沒有實作這樣的機制(例如每次new GameObject均會去呼叫Unity native的CreateGameObject()方法,別忘了P/Invoke本身就有一點成本,尤其是CreateGameObject()並不是傳遞primitive type),所以在Script中使用,還是得需要自行管理。

在.NET、許多近代程式庫裡,object pool的設計是非常常見的。.NET中的Container都是這種設計,例如List<T>, Dictionary<TKey, TValue>

範例一
public static class GameObjectPool
{
    static int _capacity = 10;
    static Queue<GameObject> _pool = new Queue<GameObject>();
    
    public static int Capacity
    {
        get { return _capacity; }
        set { if (value > 0) _capacity = value; }
    }

    static GameObjectPool()
    {
        Allocate();
    }

    static void Allocate()
    {
        GameObject go;
        for (int i = 0; i != _capacity; ++i)
        {
            go = new GameObject();
            go.SetActive(false);
            _pool.Enqueue(go);
        }
    }

    public static GameObject Create()
    {
        if (_pool.Count == 0) Allocate();
        return _pool.Dequeue();
    }
    
    public static void Recycle(GameObject go)
    {
        if (go == null) return;
        _pool.Enqueue(go);
    }
}

一開始會產生100個GameObject,需要使用時,調用GameObjectPool.Create()即可,當數量不夠時,會再配置100個GameObject
而回收的部分,這裡只是個很簡單的範例,回收是需要再處理的,當有個GameObject不再使用時,指示該GameObject不再使用,將其回收。

參考

公會首頁

主選單
關聯資料