为什么使用对象池
当一个游戏需要频繁的创建和销毁对象时,为了不增加GC的性能消耗,可以考虑使用回收对象来打到复用的目的。(适用于飞机大战类,消除类,射击类,moba类等游戏)
什么是对象池
为了回收和复用对象,我们使用一个集合来存储不使用的对象,当需要使用该对象时,再从集合中取出,这样一个工具类称之为对象池。
对象池的实现
ObjectPool:对存储对象的集合进行了适当的封装,用于单个游戏对象(预制体)的回收和复用。
PoolManager:对ObjectPool单个游戏对象的进一步封装,可以用于创建多个对象(预制体)的回收和复用,可以更方便的使用对象池。(对象池模块化)
IPoolRelease:对象池回收对象时的还原接口,继承后对象自动还原初始值。
代码
using UnityEngine; using System.Collections.Generic; /// <summary> /// 二十四种设计模式 /// 对象池 /// </summary> public class ObjectPool//子弹对象池//可以不继承 MonoBehaviour { public GameObject prefab;//预制体 private Stack<GameObject> pool = new Stack<GameObject>();//开辟占 public ObjectPool(GameObject _prefab) { prefab = _prefab; } //取对象 public GameObject Get() { if (pool.Count > 0)//判断是否有对象 { GameObject go = pool.Pop(); go.SetActive(true);//取得时候激活对象 return go; } else { GameObject go = GameObject.Instantiate(prefab);//如果没有则克隆一个对象 return go; } } //回收存对象 public void Save(GameObject go) { go.SetActive(false);//收回的时候不激活对象 pool.Push(go); } }
对象池管理器
using UnityEngine; using System.Collections.Generic; public class PoolManager : MonoBehaviour//对象池管理器脚本 { /// <summary> /// 二十四种设计模式 /// 单例模式 /// </summary> public static PoolManager _instance = null;//对象池该为静态,//私有的静态实例 public static PoolManager Instance//共有的唯一的,全局访问点 { get { if (_instance == null) { _instance = GameObject.FindObjectOfType<PoolManager>(); } if (_instance == null)//如果为空的话 { GameObject go = new GameObject("PoolManager");//创造一个对象池 _instance = go.AddComponent<PoolManager>(); } return _instance; } } public GameObject[] prePrefabs; void Awake() { if (_instance == null) _instance = this; else Destroy(gameObject); InitPool(); } private Dictionary<string, ObjectPool> dic = new Dictionary<string, ObjectPool>(); void InitPool() { //提前初始化的对象池 foreach (var prefab in prePrefabs) { CreatPool(prefab.name, prefab); } } /// <summary> /// 创建对象池 /// </summary> /// <param name="poolName">对象池名字</param> /// <param name="prefab">对象池对应的预制体</param> public void CreatPool(string poolName, GameObject prefab) { if (!dic.ContainsKey(poolName)) { dic[poolName] = new ObjectPool(prefab); } } /// <summary> /// 获取对象池对象 /// </summary> /// <param name="poolName">对象池名字</param> /// <returns></returns> public GameObject Get(string poolName)//取对象 { ObjectPool pool; if (dic.TryGetValue(poolName, out pool))//如果对象池中有的话 { return pool.Get();//取这个对象 } else { Debug.LogError("对象池:" + poolName + "不存在!!!"); return null; } } /// <summary> /// 回收对象 /// </summary> /// <param name="poolName">对象池的名字</param> /// <param name="go">对象</param> public void Save(string poolName, GameObject go) { ObjectPool pool; if (dic.TryGetValue(poolName, out pool))//如果对象池中有的话 { pool.Save(go); } else { Debug.Log("对象池:" + poolName + "不存在!!!"); } } }