| 教程链接11:00 一、大致思路: 1.创建一个字典保存所有对象池,并将对象池与对象池名称联系起来。 2.单例模式来储存数据。 3.一个方法调用对象池的对象,一个方法将弃用的对象放回对象池。 4.管理实例化的对象,让其在运行窗口上看起来不杂乱。 5.对象池的使用。 二、观前提示: 注意代码中的数据与游戏物体的关系 这里我们希望在窗口中通过“ObjectPool”来作为不同对象池的父物体。将每个对象池物体的名字都设置为相应预制体的名字+"Pool",并作为相应对象的父物体。效果如下。 
 实际对象池的数值储存情况如下 
 三、代码 using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectPool 
{
    private static ObjectPool instance;//储存当前实例
    //通过字典可以快速的根据名称查找到相应对象池,使用队列可以方便的删减元素(无需指定元素)
    private Dictionary<string, Queue<GameObject>> objectPool = new Dictionary<string, Queue<GameObject>>();
    
    private GameObject pool;//作为所有对象池的父物体,便于管理。
    //单例模式
    public static ObjectPool Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new ObjectPool();
            }
            
                return instance;
        }
    }
 先初步写一下调用方法 public GameObject GetObject(GameObject prefab)
    {
        GameObject _object;//稍后我们将所取出的对象绑定在该物体上返回
        /*现在已经知道了所需的游戏对象,我们要从对象池中获得这个对象。
   现在分为三种情况:
        ①相应对象池中有剩余对象
        ②相应对象池中没有剩余对象
        ③没有相应对象池
   对应的处理办法:
        ①取出相应对象池的对象,激活,并返回
        ②实例化一个对象,并将其放入对象池中,执行①
        ③实例化一个对象,(创建新的对象池)并将其放入对象池中,执行①
        使用if区分不同的处理方法,将共同的处理方法放在外面
        这里在PushObject中创建新的对象池,可能是为了精简下代码(也有可能有其他理由,望指出)
       */
       
        if (objectPool.ContainsKey(prefab.name)==false||objectPool[prefab.name].Count == 0)//③
        {
            _object = GameObject.Instantiate(prefab);//实例化一个所需对象
            //稍后向此处插入代码设置新对象的父子关系,维持unity中游戏对象的整洁性
            PushObject(_object);//将对象放入对象池中
        }
        
        _object = objectPool[prefab.name].Dequeue();//取出相应对象并激活
        _object.SetActive(true);
        return _object;
        
    }
 再编写"PushObject"   /*我们得到了需要放入对象池的对象,
现存在两种情况
    ①存在对应对象池
    ②不存在对应对象池
 对应的处理办法
    ①将对象放入相应对象池中并使其失效
    ②向字典中添加新的对象池元素,执行①*/
    public void PushObject(GameObject prefab)
    {
        string _name = prefab.name.Replace("(Clone)", string.Empty);//实例化的物体后都会带有“(Clone)”
        if (objectPool.ContainsKey(_name) == false)//②
        {
            objectPool.Add(_name, new Queue<GameObject>());//向字典中添加新的对象池元素
        }
       //将对象放入相应对象池中并使其失效
        objectPool[_name].Enqueue(prefab);
        prefab.SetActive(false);
       
    }
 现在一个基本的对象池就已经成型了,但我们还需要让编辑窗口看起来没那么杂乱,所以要分配不同对象之间的关系。因为物体实例化发生在GetObject方法中,所以我选择在这个方法中进行分配,分配位置上面已经标明。  if (pool == null)
            {
                pool = new GameObject("ObjectPool");//创建一个物体管理所有对象池
            }
            //寻找并绑定相应对象池物体,如果对象物体不存在则创建一个对象池物体
            GameObject childPool = GameObject.Find(prefab.name + "pool");
            if (!childPool)
            {
                childPool = new GameObject(prefab.name + "pool");
            }
            //设置好他们的关系
            childPool.transform.SetParent(pool.transform);
            _object.transform.SetParent(childPool.transform);
 这是全部的代码,可以再阅读试试是否已经理解 using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectPool 
{
   
    private Dictionary<string, Queue<GameObject>> objectPool = new Dictionary<string, Queue<GameObject>>();
    private GameObject pool;
    private static ObjectPool instance;
    public static ObjectPool Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new ObjectPool();
            }
            
                return instance;
        }
    }
    
    public GameObject GetObject(GameObject prefab)
    {
        GameObject _object;
        if (!objectPool.ContainsKey(prefab.name)|| objectPool[prefab.name].Count == 0)//③
        {
            _object = GameObject.Instantiate(prefab);
            if (pool == null)
            {
                pool = new GameObject("ObjectPool");
            }
            GameObject childPool = GameObject.Find(prefab.name + "pool");
            if (!childPool)
            {
                childPool = new GameObject(prefab.name + "pool");
            }
            childPool.transform.SetParent(pool.transform);
            _object.transform.SetParent(childPool.transform);
            PushObject(_object);
           
        }
        _object = objectPool[prefab.name].Dequeue();
        _object.SetActive(true);
        return _object;
    }
    public void PushObject(GameObject prefab)
    {
        string _name = prefab.name.Replace("(Clone)", string.Empty);
        if (objectPool.ContainsKey(_name) == false)
        {
            objectPool.Add(_name, new Queue<GameObject>());
        }
        objectPool[_name].Enqueue(prefab);
        prefab.SetActive(false);
    }
}
 最后,我们需要调用该类中的方法,使用单例调用 ObjectPool.Instance.GetObject(bulletPrefab);
 四、感想: 好爽!!!!!!!!!!!! |