unity---对象池

目录

1、Queue定义

2、优点

3.注释

4、Queue的属性

5. Queue的方法

6、Queue的使用示例

7.备注

8.进击的管理类

8.1管理类

8.2工具类

8.3工具类面板

8.4 对象池预制体基类



1、Queue定义

System.Collections.Queue类表示对象的先进先出集合,存储在 Queue(队列) 中的对象在一端插入,从另一端移除。

2、优点

1、能对集合进行顺序处理(先进先出)。

2、能接受null值,并且允许重复的元素。

3、 Queue的构造器  构造器函数

3.注释

Queue ()

初始化 Queue 类的新实例,该实例为空,具有默认初始容量(32)并使用默认增长因子(2.0)。

Queue (ICollection)

初始化 Queue 类的新实例,该实例包含从指定集合复制的元素,具有与所复制的元素数相同的初始容量并使用默认增长因子。

Queue (Int32)

初始化 Queue 类的新实例,该实例为空,具有指定的初始容量并使用默认增长因子。

Queue (Int32, Single)

初始化 Queue 类的新实例,该实例为空,具有指定的初始容量并使用指定的增长因子。

4、Queue的属性

Count     获取 Queue 中包含的元素数。

5. Queue的方法

Void Clear()   从 Queue 中移除所有对象。

Bool Contains(object obj)    确定某元素是否在 Queue 中。

Object Clone()     创建 Queue 的浅表副本。

Void CopyTo(Array array,int index)

从指定数组索引开始将 Queue 元素复制到现有一维 Array 中。

Object Dequeue()    移除并返回位于 Queue 开始处的对象。

Void Enqueue(object obj)    将对象添加到 Queue 的结尾处。

Object Peek()       返回位于 Queue 开始处的对象但不将其移除。

Object[]ToArray()   将 Queue 元素复制到新数组。

Void TrimToSize()   将容量设置为 Queue 中元素的实际数目。

6、Queue的使用示例

using System.Collections.Generic;
using UnityEngine;

public class Pool_foodTip : MonoBehaviour
{
    [SerializeField]
    private Transform pare;
    [SerializeField]
    private FoodTip fab;

    private static Pool_foodTip _ins;
    public static Pool_foodTip ins
    {
        get
        {
            return _ins;
        }
    }

    private int poolCount = 30;

    private Queue<FoodTip> foodPool = new Queue<FoodTip>();

    void Awake()
    {
        _ins = this;
    }

    public FoodTip GetFoodTip()
    {
        if (foodPool.Count > 0)
        {
            return foodPool.Dequeue();
        }
        else
        {
            return CreateFoodTip();
        }
    }

    private FoodTip CreateFoodTip()
    {
        FoodTip ft = Instantiate(foodTip, pare);
        return ft;
    }

    public void CheckTip(FoodTip ft)
    {
        if (foodPool.Count > poolCount)
        {
            Destroy(ft.gameObject);
        }
        else
        {
            foodPool.Enqueue(ft);
        }
    }
}



7.备注

1、Queue 的容量是 Queue 可以保存的元素数。Queue 的默认初始容量为 32。向 Queue 添加元素时,将通过重新分配来根据需要自动增大容量。可通过调用 TrimToSize 来减少容量。等比因子是当需要更大容量时当前容量要乘以的数字。在构造 Queue 时确定增长因子。默认增长因子为 2.0。

2、Queue 能接受空引用作为有效值,并且允许重复的元素。

3、空引用可以作为值添加到 Queue。若要区分空值和 Queue 结尾,请检查 Count 属性或捕捉 Queue 为空时引发的 InvalidOperationException异常。

8.进击的管理类

8.1管理类

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;

public class PoolManager
{
    private static Vector3 OutOfRange = new Vector3(9000, 9000, 9000);//超出边界的值 在回收的时候直接设置位置

    private static Dictionary<string, Dictionary<int, GameObject>> createPools = new Dictionary<string, Dictionary<int, GameObject>>();
    private static Dictionary<string, Dictionary<int, GameObject>> recyclePools = new Dictionary<string, Dictionary<int, GameObject>>();

    private static Transform s_poolParent;


    //对象池 父对象  也是回收的父对象  防止回收的对象被意外删除
    public static Transform PoolParent
    {
        get
        {
            if (s_poolParent == null)
            {
                GameObject instancePool = new GameObject("ObjectPool");
                s_poolParent = instancePool.transform;
                if (Application.isPlaying) UnityEngine.Object.DontDestroyOnLoad(s_poolParent);
            }

            return s_poolParent;
        }
    }

    public static Dictionary<string, Dictionary<int, GameObject>> GetCreatePool()
    {
        return createPools;
    }

    public static Dictionary<string, Dictionary<int, GameObject>> GetRecyclePool()
    {
        return recyclePools;
    }

    #region 创建

    //通过创建对象名字 直接实例化
    public static GameObject CreateGameObject(string name, GameObject parent = null, bool isActive = true)
    {
        return GetNewObject(true, name, null, parent, isActive);
    }

    //通过预制体 直接实例化
    public static GameObject CreateGameObject(GameObject prefab, GameObject parent = null, bool isActive = true)
    {
        return GetNewObject(true, null, prefab, parent, isActive);
    }

    //通过名字 对象池实例化
    public static GameObject CreateGameObjectByPool(string name, GameObject parent = null, bool isActive = true)
    {
        return GetNewObject(false, name, null, parent, isActive);
    }

    //通过预制体 直接实例化
    public static GameObject CreateGameObjectByPool(GameObject prefab, GameObject parent = null, bool isActive = true)
    {
        return GetNewObject(false, null, prefab, parent, isActive);
    }

    //通过创建对象名字 直接实例化
    public static T CreateGameObject<T>(string name, GameObject parent = null, bool isActive = true)
    {
        return GetNewObject(true, name, null, parent, isActive).GetComponent<T>();
    }

    //通过预制体 直接实例化
    public static T CreateGameObject<T>(GameObject prefab, GameObject parent = null, bool isActive = true)
    {
        return GetNewObject(true, null, prefab, parent, isActive).GetComponent<T>(); ;
    }

    //通过名字 对象池实例化
    public static T CreateGameObjectByPool<T>(string name, GameObject parent = null, bool isActive = true)
    {
        return GetNewObject(false, name, null, parent, isActive).GetComponent<T>(); ;
    }

    //通过预制体 直接实例化
    public static T CreateGameObjectByPool<T>(GameObject prefab, GameObject parent = null, bool isActive = true)
    {
        return GetNewObject(false, null, prefab, parent, isActive).GetComponent<T>(); ;
    }


    /// <summary>
    /// 获取一个新的对象
    /// </summary>
    /// <param name="isNew">是否创建新的对象</param>
    /// <param name="objName">实例化对象的名字</param>
    /// <param name="prefab">实例化预制体</param>
    /// <param name="parent">实例化父对象</param>
    /// <param name="isActive"></param>
    /// <returns></returns>
    private static GameObject GetNewObject(bool isNew, string objName, GameObject prefab, GameObject parent = null, bool isActive = true)
    {
        GameObject go = null;

        //获取对象名字
        string name = objName;
        if (string.IsNullOrEmpty(name))
        {
            name = prefab.name;
        }

        if (!isNew && IsExist(name))
        {
            if (!recyclePools.ContainsKey(name))
            {
                //创建新的对象
                if (prefab != null)
                {
                    go = InstantiateObject(prefab, parent);
                }
                else
                {
                    go = NewGameObject(name, parent);
                }
            }
            else
            {
                //从回收池中加载
                List<int> ids = new List<int>(recyclePools[name].Keys);
                int id = ids[0];
                go = recyclePools[name][id];
                recyclePools[name].Remove(id);
                if (recyclePools[name].Count == 0) recyclePools.Remove(name);
            }
        }
        else
        {
            //直接创建新的对象
            if (prefab == null && !string.IsNullOrEmpty(objName))
            {
                go = NewGameObject(name, parent);

            }
            else if (prefab != null && string.IsNullOrEmpty(objName))
            {
                go = InstantiateObject(prefab, parent);
            }
        }

        if (go == null)
        {
            Debug.LogError("PoolManager 加载失败:" + name);
            return go;
        }

        //记录保存到createPool
        if (!createPools.ContainsKey(name)) createPools.Add(name, new Dictionary<int, GameObject>());
        createPools[name].Add(go.GetInstanceID(), go);

        //初始化
        PoolObject obj = go.GetComponent<PoolObject>();
        if (obj) obj.OnFetch();

        go.SetActive(isActive);
        go.transform.SetParent(parent ? parent.transform : null);

        return go;
    }

    //实例化
    private static GameObject InstantiateObject(GameObject prefab, GameObject parent = null)
    {
        if (prefab == null)
        {
            throw new Exception("CreateGameObject error : prefab  is null");
        }
        Transform transform = parent == null ? null : parent.transform;
        GameObject instanceTmp = UnityEngine.Object.Instantiate(prefab, transform);
        instanceTmp.name = prefab.name;

        PoolObject p = instanceTmp.GetComponent<PoolObject>();
        if (p != null) p.OnCreate();

        return instanceTmp;
    }

    //加载一个对象并实例化
    private static GameObject NewGameObject(string gameObjectName, GameObject parent = null)
    {
        /****暂时从Resources读取****/
        GameObject goTmp = Resources.Load<GameObject>(ResPath.GetPath(gameObjectName));

        if (goTmp == null)
        {
            throw new Exception("CreateGameObject error dont find :" + gameObjectName);
        }

        return InstantiateObject(goTmp, parent);
    }

    #endregion

    #region 销毁

    //回收对象
    public static void DestoryByRecycle(GameObject gameObject, bool isSetInactive = true)
    {
        if (!gameObject) return;

        string key = gameObject.name.Replace("(Clone)", "");
        if (!recyclePools.ContainsKey(key)) recyclePools.Add(key, new Dictionary<int, GameObject>());

        if(recyclePools[key].ContainsKey(gameObject.GetInstanceID()))
        {
            Debug.LogError("Recycle repeat by Destory -> " + gameObject.name);
            return;
        }
        recyclePools[key].Add(gameObject.GetInstanceID(), gameObject);

        if (isSetInactive) gameObject.SetActive(false);
        else gameObject.transform.position = OutOfRange;

        gameObject.name = key;
        gameObject.transform.SetParent(PoolParent);
        PoolObject obj = gameObject.GetComponent<PoolObject>();
        if (obj) obj.OnRecycle();

        if (createPools.ContainsKey(key) && createPools[key].ContainsKey(gameObject.GetInstanceID()))
        {
            createPools[key].Remove(gameObject.GetInstanceID());
        }
        else Debug.LogError("对象池不存在GameObject:" + gameObject + " 不能回收!");
    }

    //延时多久 回收
    public static void DestoryByRecycle(GameObject gameObject, float time)
    {
        Timer.DelayCallBack(time, (o) =>
        {
            DestoryByRecycle(gameObject);
        });
    }

    //直接销毁
    public static void Destory(GameObject gameObject)
    {
        if (gameObject == null) return;

        string key = gameObject.name.Replace("(Clone)", "");

        PoolObject obj = gameObject.GetComponent<PoolObject>();
        if (obj) obj.OnDestory();

        //移除
        if(createPools.ContainsKey(key) && createPools[key].ContainsKey(gameObject.GetInstanceID()))
        {
            createPools[key].Remove(gameObject.GetInstanceID());
            if (createPools[key].Count == 0) createPools.Remove(key);
        }

        UnityEngine.Object.Destroy(gameObject);
    }

    //直接销毁
    public static void Destory(GameObject gameObject, float time)
    {
        if (gameObject == null) return;

        string key = gameObject.name.Replace("(Clone)", "");

        PoolObject obj = gameObject.GetComponent<PoolObject>();
        if (obj) obj.OnDestory();

        //移除
        if (createPools.ContainsKey(key) && createPools[key].ContainsKey(gameObject.GetInstanceID()))
        {
            createPools[key].Remove(gameObject.GetInstanceID());
            if (createPools[key].Count == 0) createPools.Remove(key);
        }

        UnityEngine.Object.Destroy(gameObject, time);
    }

    #endregion

    //判断是否存在改对象
    public static bool IsExist(string objName)
    {
        if(string.IsNullOrEmpty(objName))
        {
            Debug.LogError("PoolManager objName is null");
            return false;
        }

        if ((createPools.ContainsKey(objName) && createPools[objName].Count > 0)
            || recyclePools.ContainsKey(objName) && recyclePools[objName].Count > 0)
        {
            return true;
        }

        return false;
    }

    public static bool IsExist(GameObject gameObject)
    {
        if (gameObject == null) return false;

        return IsExist(gameObject.name.Replace("(Clone)", ""));
    }

    //对象池回收 已经创建的了的对象池  对没有元素的清空  销毁所有在回收对象池
    public static void PoolClean()
    {
        //清创创建了的对象池
        List<string> cleanPool = new List<string>();
        foreach (var item in createPools)
        {
            if (item.Value.Count == 0) cleanPool.Add(item.Key);
        }

        cleanPool.ForEach((s) => createPools.Remove(s));

        //清空回收对象池
        List<GameObject> cleanObj = new List<GameObject>();
        foreach (var item in recyclePools)
        {
            foreach (var v in item.Value)
            {
                cleanObj.Add(v.Value);
            }
        }
        cleanObj.ForEach((s) =>
        {
            PoolObject obj = s.GetComponent<PoolObject>();
            if (obj) obj.OnDestory();
            UnityEngine.Object.Destroy(s);
        });
        recyclePools.Clear();
    }

    //回收某一对象的池
    public static void PoolClean(string name)
    {
        if (recyclePools.ContainsKey(name))
        {
            foreach (var item in recyclePools[name])
            {
                PoolObject obj = item.Value.GetComponent<PoolObject>();

                if (obj) obj.OnDestory();
                UnityEngine.Object.Destroy(item.Value);

            }
            recyclePools.Remove(name);
        }

        if (createPools.ContainsKey(name) && createPools[name].Count == 0) createPools.Remove(name);
    }

}

8.2工具类

public class ResPath
{

    private static Dictionary<string, string> pathDic = new Dictionary<string, string>();
    const string pathFilePath = "PrefabPath";

    //初始化
    public static void Init()
    {
        LoadPath();
    }

    //加载本地路径
    static void LoadPath()
    {
        try
        {
            TextAsset pathFile = Resources.Load<TextAsset>(pathFilePath);
            string[] pathes = pathFile.text.Split("\r\n".ToCharArray());
            for (int i = 0; i < pathes.Length; i++)
            {
                if (string.IsNullOrEmpty(pathes[i])) continue;
                string[] path = pathes[i].Split('\t');
                //Debug.Log(path[0] + " " + path[1]);
                pathDic.Add(path[0], path[1]);
            }
        }
        catch (Exception e)
        {
            Debug.LogError("check filePath --->" + pathFilePath + "   " + e.ToString());
        }
    }

    /// <summary>
    /// 获取资源路径
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public static string GetPath(string name)
    {
        if(pathDic.ContainsKey(name))
        {
            return pathDic[name];
        }

        Debug.Log("get path name is not exist ->" + name);
        return null;
    }
}

8.3工具类面板

PrefabPath.txt

 

 

内容样式

 

8.4 对象池预制体基类

using UnityEngine;

//对象池对象
//预制体对象需继承
public class PoolObject : MonoBehaviour
{
    //对象初始化时调用
    public virtual void OnCreate()
    {

    }

    //从对象池中取出调用
    public virtual void OnFetch()
    {

    }

    //回收时调用
    public virtual void OnRecycle()
    {

    }

    //销毁时调用
    public virtual void OnDestory()
    {

    }
}

猜你喜欢

转载自blog.csdn.net/lalate/article/details/131323862