目的
降低需要經常性初始化的情況,改善效能。
時機
- 經常性的產生、銷毀動作,且初始化成本過高。
- 有效能需求。
物件池是一個很重要的概念,每次產生
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不再使用,將其回收。
參考