标签: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);
在本人的实际使用中,用这个类管理了
欢迎各位进行讨论
《Unity3D》通过对象池模式,管理场景中的元素,布布扣,bubuko.com
标签:style class blog code tar color
原文地址:http://www.cnblogs.com/kimmy/p/3808007.html