標籤:style class blog code tar color
池管理類有啥用?
在遊戲情境中,我們有時候會需要複用一些遊戲物體,比如常見的子彈、子彈碰撞類,某些情況下,怪物也可以使用池管理,UI部分比如:血條、文字等等
這些元素共同的特性是:存在固定生命週期,使用比較頻繁,情境中大量使用。
所以,我們就通過池管理思路,在遊戲初始化的時候,產生一個初始的池,存放我們要複用的元素,
當要用到時,從池中取出;生命週期結束,放回到池中。
代碼
這個池的參數有兩個:1池中存放的元素 2 池的初始容量(如果池不夠了,則會按照這個容量進行擴充)
代碼如下
using System.Collections;using System.Collections.Generic;using UnityEngine;/// <summary>/// 通用的池管理類/// </summary>public class ObjectPoolManager : MonoBehaviour{ #region 公用屬性 /// <summary> /// 池中所使用的元素Prefab /// </summary> public GameObject ObjPrefab; /// <summary> /// 初始容量 /// </summary> public int InitialCapacity; #endregion #region 私人屬性 /// <summary> /// 初始下標 /// </summary> private int _startCapacityIndex; /// <summary> /// 可用下標 /// </summary> private List<int> _avaliableIndex; /// <summary> /// 池中全部元素 /// </summary> private Dictionary<int, GameObject> _totalObjList; #endregion #region 事件/重寫方法 void Start() { _avaliableIndex = new List<int>(InitialCapacity); _totalObjList = new Dictionary<int, GameObject>(InitialCapacity); expandPool(); } #endregion #region 公用方法 /// <summary> /// 取得一個物體,傳回值 1,obj代表,ID是1的物體被取到,ID可以用來歸還物體的時候用到 /// </summary> /// <returns></returns> public KeyValuePair<int, GameObject> PickObj() { if (_avaliableIndex.Count == 0) expandPool(); int id = _avaliableIndex[0]; _avaliableIndex.Remove(id); _totalObjList[id].SetActive(true); return new KeyValuePair<int, GameObject>(id, _totalObjList[id]); } /// <summary> /// 從池中取出元素,在制定時間後回收 /// </summary> /// <param name="existSecond"></param> /// <returns></returns> public KeyValuePair<int, GameObject> PickObjWithDelayRecyle(float existSecond) { KeyValuePair<int, GameObject> obj = PickObj(); StartCoroutine(startRecycleExplosion(obj.Key, existSecond)); return obj; } /// <summary> /// 回收一個物體 /// </summary> /// <param name="id"></param> public void RecyleObj(int id) { _totalObjList[id].SetActive(false); _totalObjList[id].transform.parent = transform; _avaliableIndex.Add(id); } #endregion #region 私人方法 IEnumerator startRecycleExplosion(int id, float waitTime) { yield return new WaitForSeconds(waitTime); RecyleObj(id); } /// <summary> /// 擴充池 /// </summary> private void expandPool() { int start = _startCapacityIndex; int end = _startCapacityIndex + InitialCapacity; for (int i = start; i < end; i++) { //加入驗證判斷,避免在多個請求同時觸發擴充池需求 if (_totalObjList.ContainsKey(i)) continue; GameObject newObj = Instantiate(ObjPrefab) as GameObject; newObj.SetActive(false); _avaliableIndex.Add(i); _totalObjList.Add(i, newObj); } _startCapacityIndex = end; } #endregion}
值得注意的是:放回池中的時候,我們把元素的父節點也設定為池元素,這樣做是避免當元素掛載的對象在記憶體中被刪除的時候,元素也被刪除的問題。
調用
將本類掛載到情境中的某個GameObject上,在U3D編輯介面進行參數的賦值,就可以再遊戲中訪問了。
聲明方式:
ObjectPoolManager _bulletPool = GameObject.Find("你掛載的物體名稱").GetComponent<ObjectPoolManager>();
取出元素:
KeyValuePair<int, GameObject> bulletKV = _bulletPool.PickObj();
放回:
_bulletPool.RecyleObj(bulletID);
在本人的實際使用中,用這個類管理了
- 子彈
- 子彈碰撞特效
- 攻擊特效
- 被攻擊特效
- 怪物血條(基於NGUI製作)
- 情境部分文字(施法時、怪物被攻擊時,基於NGUI製作)
- 等等。。
歡迎各位進行討論