Unity中的物件池
阿新 • • 發佈:2018-11-26
什麼是物件池?
為了方便物件的產生和回收,我們使用一個集合來儲存不使用物件,當需要使用該物件時,從集合中取出來,不用時不進行銷燬,而是將其取消啟用,重新存入物件池中。
為什麼要使用物件池?
當一個遊戲需要頻繁的建立和銷燬物件時,為了不增加GC的效能消耗,可以考慮使用回收物件來達到複用的目的。(適用於頻繁建立和銷燬的物件)
物件池的實現
Pool(物件池):對儲存物件的集合進行了適當的封裝,用於單個遊戲物件(預製體)的回收和複用。
程式碼:
public class Pool{ public string name = ""; public GameObject prefab; Queue<GameObject> poolQueue = new Queue<GameObject>(); //使用佇列儲存物件池中的資料 //立即回收 public void Recycle(GameObject go) { go.GetComponent<IReset>().Reset(); go.SetActive(false); poolQueue.Enqueue(go); } //延遲迴收 public IEnumerator AutoRecycle(GameObject go, float delay) { //使用寫成,延時回收 yield return new WaitForSeconds(delay); Recycle(go); } //建立物件 public GameObject Create() { GameObject go = null; if (poolQueue.Count > 0) { //物件池中有需要建立的物件,從物件池中取 go = poolQueue.Dequeue(); go.SetActive(true); } else { //當物件池中沒有需要建立的物件時,建立物件 go = GameObject.Instantiate(prefab); } return go; } }
PoolMgr(物件池管理器):對物件池進行了進一步的封裝,可以用於建立多個物件(預製體)的回收和服用,可以更加方便的使用物件池。(物件池模組化)。
程式碼:
public class PoolMgr : MonoBehaviour { public Pool[] pools; //物件池管理器使用單例 private static PoolMgr _instance; public static PoolMgr Instance { get { return _instance; } } void Awake() { if (_instance == null) { _instance = this; } else { Destroy(this.gameObject); } } //將物件池註冊進字典 Dictionary<string, Pool> poolDir = new Dictionary<string, Pool>(); void Start () { foreach (var item in pools) { poolDir.Add(item.name.ToLower(), item); } } public GameObject CreateObj(string poolName) { Pool pool; //TryGetValue獲取與鍵相關聯的值 if (poolDir.TryGetValue(poolName.ToLower(),out pool)) { return pool.Create(); } Debug.LogError(poolName + "不存在"); return null; } /// <summary> /// 立即回收 /// </summary> public void RecycleObjs(string poolName, GameObject go) { Pool pool; if (poolDir.TryGetValue(poolName.ToLower(),out pool)) { pool.Recycle(go); } } /// <summary> /// 延遲銷燬 /// </summary> /// <param name="poolName">物件池名字</param> /// <param name="go">需要回收的物件</param> /// <param name="delay">延遲時間</param> public void RecycleObjs(string poolName, GameObject go, float delay) { StartCoroutine(DelayRecycle(poolName, go, delay)); } IEnumerator DelayRecycle(string poolName, GameObject go, float delay) { //延遲呼叫的立即回收 yield return new WaitForSeconds(delay); Pool pool; if (poolDir.TryGetValue(poolName.ToLower(),out pool)) { pool.Recycle(go); } } }
注:物件池是一種用記憶體換運存的優化技術,只有大量頻繁建立和銷燬的物件使用物件池,才能起到優化作用,否則不具有優化效果。