我的Unity工具类---对象池

优点:

避免了Instantiate()和Destroy(), 减少GC

缺点:

占用内存, GC无法回收
池子里有50个, 实际可能只用到了3个, 会浪费内存

注意: 从池子里取出来的时候, 一定一定一定要把初始化写全


对象池有很多种写法, 有的人用栈, 有的用列表, 我这里用的是字典
思路很简单:
用的时候从池子里取, 如果池子里没有, 则创建一个
回收的时候扔到池子里

代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Pool : MonoBehaviour
{
    Dictionary<string, List<GameObject>> GoDic = new Dictionary<string, List<GameObject>>();
    Dictionary<string, GameObject> PrefabDic = new Dictionary<string, GameObject>();

    private static Pool instance;
    static Transform GoPool;
    public static Pool Instance
    {
        get
        {
            if (null == instance)
            {
                instance = FindObjectOfType<Pool>(); ;
                if (null == instance)
                {
                    GoPool = new GameObject("GoPool").transform;
                    instance = GoPool.gameObject.AddComponent<Pool>();
                }
            }
            return instance;
        }
    }

    public void Init()
    {
        //读取并保存,预制体字典和对象池
        GameObject[] prefabs = Resources.LoadAll<GameObject>("Prefabs");
        foreach (var item in prefabs)
        {
            if (!PrefabDic.ContainsKey(item.name))
            {
                PrefabDic.Add(item.name, item);
            }
            if (!GoDic.ContainsKey(item.name))
            {
                GoDic.Add(item.name, new List<GameObject>());
            }
        }
    }
    //从对象池中拿出一个
    GameObject PoolPopGO(string key)
    {
        GameObject go;
        if (GoDic.ContainsKey(key))
        {
            if (GoDic[key].Count > 0)
            {
                go = GoDic[key][0];
                if (go.activeInHierarchy)
                {
                    Debug.LogError("出错了哦, 为什么对象池里会有活物呢");
                }
                GoDic[key].Remove(go);
                if (go == null)
                {
                    Debug.LogError("出错了哦, 为什么对象池里会有空物体呢");
                }
                go.SetActive(true);
            }
            else
            {
                go = Instantiate(PrefabDic[key]);
                go.name = key;
            }
            return go;
        }
        else { Debug.LogError("对象池中找不到: " + key + ", 无法创建"); }
        return null;
    }
    /// <summary>
    /// 得到一个物体
    /// </summary>
    public GameObject GetGo(string name)
    {
        GameObject result = PoolPopGO(name);
        return result;
    }
    /// <summary>
    /// 得到一个物体,并设置爸爸
    /// </summary>
    public GameObject GetGo(string name, Transform trs)
    {
        GameObject result = PoolPopGO(name);
        result.transform.SetParent(trs);
        return result;
    }
    /// <summary>
    /// 得到一个物体,并设置位置
    /// </summary>
    public GameObject GetGo(string name, Vector3 pos)
    {
        GameObject result = PoolPopGO(name);
        result.transform.position = pos;
        return result;
    }
    /// <summary>
    /// 得到一个物体,并设置位置, 爸爸
    /// </summary>
    public GameObject GetGo(string name, Vector3 pos, Transform trs)
    {
        GameObject result = PoolPopGO(name);
        result.transform.SetParent(trs);
        result.transform.position = pos;
        return result;
    }
    /// <summary>
    /// 得到一个物体,并设置位置和角度
    /// </summary>
    public GameObject GetGo(string name, Vector3 pos, Quaternion ros)
    {
        GameObject result = PoolPopGO(name);
        result.transform.position = pos;
        result.transform.rotation = ros;
        return result;
    }
    /// <summary>
    /// 得到一个物体,并设置位置, 朝向
    /// </summary>
    public GameObject GetGo(string name, Vector3 pos, Vector3 tar)
    {
        GameObject result = PoolPopGO(name);
        result.transform.position = pos;
        result.transform.LookAt(tar);
        return result;
    }
    /// <summary>
    /// 得到一个物体,并设置位置, 朝向, 爸爸
    /// </summary>
    public GameObject GetGo(string name, Vector3 pos, Quaternion ros, Transform trs)
    {
        GameObject result = PoolPopGO(name);
        result.transform.position = pos;
        result.transform.rotation = ros;
        result.transform.parent = trs;
        return result;
    }
    /// <summary>
    /// 物体回收
    /// </summary>
    public void Recycle(Transform go)
    {
        if (GoDic.ContainsKey(go.name))
        {
            if (!GoDic[go.name].Contains(go.gameObject))
            {
                GoDic[go.name].Add(go.gameObject);
                go.gameObject.SetActive(false);
                go.position = Vector3.zero;
            }
            else//这里是个坑, 有时候会放进去2遍
            {
                Debug.LogError("出错了哦, 不能把一个东西往对象池里放2遍");
            }

        }
        else { Debug.LogError("对象池中找不到: " + go.name + ", 无法回收"); }
    }
}

改了一版, 用了泛型
移除了笨蛋Init()方法, 改为手动Add()


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

public class Pool : MonoBehaviour
{
    Dictionary<string, List<GameObject>> GoDic = new Dictionary<string, List<GameObject>>();
    Dictionary<string, GameObject> PrefabDic = new Dictionary<string, GameObject>();

    private static Pool instance;
    static Transform goPool;
    public static Pool Instance
    {
        get
        {
            if (null == instance)
            {
                instance = FindObjectOfType<Pool>();
                if (null == instance)
                {
                    goPool = new GameObject("GoPool").transform;
                    instance = goPool.gameObject.AddComponent<Pool>();
                    DontDestroyOnLoad(goPool);
                }
            }
            return instance;
        }
    }
    public void Add(string path)
    {
        //读取并保存,预制体字典和对象池
        GameObject prefab = Resources.Load<GameObject>(path);
        if (!PrefabDic.ContainsKey(prefab.name))
        {
            PrefabDic.Add(prefab.name, prefab);
        }
        if (!GoDic.ContainsKey(prefab.name))
        {
            GoDic.Add(prefab.name, new List<GameObject>());
        }
    }
    //从对象池中拿出一个
    GameObject PoolPopGO(string key)
    {
        if (GoDic.ContainsKey(key))
        {
            GameObject go;
            if (GoDic[key].Count > 0)
            {
                go = GoDic[key][0];
                if (go.activeInHierarchy)
                {
                    Debug.LogError("出错了哦, 为什么对象池里会有活物呢");
                }
                GoDic[key].Remove(go);
                if (null == go)
                {
                    Debug.LogError("出错了哦, 为什么对象池里会有空物体呢");
                }
                go.SetActive(true);
            }
            else
            {
                go = Instantiate(PrefabDic[key]);
                go.name = key;
            }
            return go;
        }
        else
        {
            Debug.LogError("对象池中找不到: " + key + ", 无法创建");
            return null;
        }
    }
    /// <summary>
    /// 得到一个物体
    /// </summary>
    public T GetGo<T>(string name) where T : Component
    {
        GameObject result = PoolPopGO(name);
        return result.GetComponent<T>();
    }
    /// <summary>
    /// 得到一个物体,并设置爸爸
    /// </summary>
    public T GetGo<T>(string name, Transform trs) where T : Component
    {
        GameObject result = PoolPopGO(name);
        result.transform.SetParent(trs);
        return result.GetComponent<T>();
    }
    /// <summary>
    /// 得到一个物体,并设置位置
    /// </summary>
    public T GetGo<T>(string name, Vector3 pos) where T : Component
    {
        GameObject result = PoolPopGO(name);
        result.transform.position = pos;
        return result.GetComponent<T>();
    }
    /// <summary>
    /// 得到一个物体,并设置位置, 爸爸
    /// </summary>
    public T GetGo<T>(string name, Vector3 pos, Transform trs) where T : Component
    {
        GameObject result = PoolPopGO(name);
        result.transform.SetParent(trs);
        result.transform.position = pos;
        return result.GetComponent<T>();
    }
    /// <summary>
    /// 得到一个物体,并设置位置和角度
    /// </summary>
    public T GetGo<T>(string name, Vector3 pos, Quaternion ros) where T : Component
    {
        GameObject result = PoolPopGO(name);
        result.transform.position = pos;
        result.transform.rotation = ros;
        return result.GetComponent<T>();
    }
    /// <summary>
    /// 得到一个物体,并设置位置, 朝向
    /// </summary>
    public T GetGo<T>(string name, Vector3 pos, Vector3 tar) where T : Component
    {
        GameObject result = PoolPopGO(name);
        result.transform.position = pos;
        result.transform.LookAt(tar);
        return result.GetComponent<T>();
    }
    /// <summary>
    /// 得到一个物体,并设置位置, 朝向, 爸爸
    /// </summary>
    public T GetGo<T>(string name, Vector3 pos, Quaternion ros, Transform trs) where T : Component
    {
        GameObject result = PoolPopGO(name);
        result.transform.position = pos;
        result.transform.rotation = ros;
        result.transform.parent = trs;
        return result.GetComponent<T>();
    }
    /// <summary>
    /// 物体回收
    /// </summary>
    public void Recycle<T>(T go) where T : Component
    {
        if (GoDic.ContainsKey(go.name))
        {
            if (!GoDic[go.name].Contains(go.gameObject))
            {
                GoDic[go.name].Add(go.gameObject);
                go.transform.SetParent(transform);
                go.gameObject.SetActive(false);
                go.transform.position = Vector3.zero;
            }
            else//这里是个坑, 有时候会放进去2遍
            {
                //Debug.Log("出错了哦, 不要把同一个对象往池里放2次: " + go.name);
            }

        }
        else
        {
            Debug.LogError("无法回收, 对象池中找不到: " + go.name);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值