本文共 3852 字,大约阅读时间需要 12 分钟。
第一次创建的时候就将对象存储在一个池子中,当需要销毁的时候不直接销毁而是隐藏,当需要时在再次使用,就不需要再次实例化一个新的对象,直接把隐藏的对象显示并拿出来用。如果对象池中已经被隐藏的物体太久没有被重新使用,应该被真正的销毁。
1. 首先,使用一个数据结构直接存储对象,为了降低装箱、拆箱操作,使用List来存储。 2. 其次,使用字典Dictionary<string,List>来存储多个对象。 3. 然后,从对象池中提取对象,如果对象池中已经存在,则激活该对象,并且从List集合中移除,否则,创建新的对象(OutPool方法实现该功能)。 4. 最后,将不用的对象再加入到对象池,加入之前,先判断该对象对应的键是否已经存在,如果存在,就直接添加进对应键的值中,否则,创建新的键值对。一.创建Cube,创建一个Sphere(子弹)用于预制存储
创建对象池的脚本
public class GameObjectPool : MonoBehaviour{ const int number = 10;//子弹弹夹的容量 bool isin = true;//用来判断是否实例子弹对象 int n;//用来记录实例出子弹对象的个数 //集合里面的元素,相当于对象池里面的对象,这里的集合可看作为对象池。 static Listpools = new List (); //再声明一个集合,用来回收发射出去的子弹对象 List pb = new List (); //首先创建一个单例 private GameObjectPool() { } private static GameObjectPool instance; public static GameObjectPool GetInstance(GameObject name)//此处的Gameobject name就是需要放入对象池的对象--子弹 { if (instance == null) { print("实例池子"); //动态的生成一个名为“GameObjectPool”的对象并将单例脚本附加上去 instance = new GameObject("GameObjectPool").AddComponent (); for (int i = 0; i < number; i++)//先往对象池中放入十发子弹 { name.SetActive(false); pools.Add(name); } } return instance; } //从对象池中取对象 public GameObject MyInstantiate() { if (pools.Count == 0)//如果十发子弹打完 { print("没子弹了:" + pools.Count); return null; } else { // print(pools[0].name); //取出对象池里面的第一个元素 GameObject obj = pools[0]; if (isin)//判断是否已经实例了十发子弹 { //obj = pools[0]; Instantiate(obj);//实例出子弹 n++;//计数加加 if (n == number) { isin = false; } } //将对象设置为激活状态 obj.SetActive(true); //将被取出的元素,从对象池中移除 pools.Remove(obj); return obj; } } //回收子弹的方法 public void MyDisable(GameObject name) { //将传进来的对象隐藏(处于非激活状态) name.SetActive(false); //回收子弹添加到pb集合中 pb.Add(name); } public void ResetBullet()//换弹夹的方法 { if (pb.Count != 0)//判断回收子弹的集合是否是空 { print("pb不是空"); for (int i = 0; i < pb.Count; i++) { pools.Add(pb[i]); //把回收的子弹重新加到弹夹中去 } pb.Clear(); } }}
创建预制子弹的脚本(脚本挂载于Shpere预制上)
public class Bullet : MonoBehaviour{ //public Transform target; void OnEnable() { //脚本可用的时候,重置子弹的位置。 //如果不加这句代码,从对象池中取出的子弹就会从上一次消失的位置开始运动。而不是你设定的子弹生成位置 //transform.position = Vector3.zero; //开启协程方法 StartCoroutine(DelayDisable(3f)); } void Update() { //子弹生成,自动向前运动 transform.Translate(Vector3.forward * Time.deltaTime * 20); } void OnDisable() { Debug.Log("I'm over"); } //子弹消失的方法 IEnumerator DelayDisable(float time) { //等待三秒 yield return new WaitForSeconds(time); //调用单例中向对象池里面存对象的方法 GameObjectPool.GetInstance(gameObject).MyDisable(gameObject); }}
创建Cube的脚本,用于发射子弹(挂载于Cube上)
public class GameManerge : MonoBehaviour{ //创建子弹的预设体 public GameObject mBulletPrefab; void Update() { //如果按下鼠标左键,发射子弹 if (Input.GetMouseButtonDown(0)) { //调用单例脚本里面的从对象池中取对象的方法 GameObject go = GameObjectPool.GetInstance(mBulletPrefab).MyInstantiate(); if (go != null) { go.transform.position = transform.position; //设置子弹生成的位置是Cube的位置 } } //按下鼠标右键,换弹夹 if (Input.GetMouseButtonDown(1)) { print("换子弹:"); GameObjectPool.GetInstance(mBulletPrefab).ResetBullet(); } }}
转载地址:http://tcrxo.baihongyu.com/