Unity 对象池

参考 https://blog.csdn.net/wangjiangrong/article/details/80196676
如果是loading用的话,所谓的对象池只是把卡一下的操作给集中起来了而已,并没有省空间,相当于是做了个预加载。

在这里插入图片描述
代码结构

在这里插入图片描述
在这里插入图片描述

ObjcetPool用来新建和回收游戏里的对象(prefab) 如 setActive(false)啥的
ObjcetPool.cs

public class ObjectPool
{
    private Queue<GameObject> m_PoolQueue;


    private string m_PoolName;

    protected Transform m_Parent;

    // 需要缓存的对象
    private GameObject prefab;

    // 最大容量
    private int m_MaxCount;

    protected const int m_DefaultMaxCount = 10;

    public GameObject Prefab { get => prefab; set => prefab = value; }

    public ObjectPool()
    {
        m_MaxCount = m_DefaultMaxCount;
        m_PoolQueue = new Queue<GameObject>();
    }

    public virtual void Init(string poolName, Transform transform)
    {
        m_PoolName = poolName;
        m_Parent = transform;
    }

    public virtual GameObject Get(Vector3 pos, float lifetime)
    {
        if (lifetime < 0)
        {
            return null;
        }
        GameObject returnObj;
        if (m_PoolQueue.Count > 0)
        {
            returnObj = m_PoolQueue.Dequeue();
        }
        else
        {
            // 池中没有可分配对象了,新生成一个
            returnObj = GameObject.Instantiate<GameObject>(prefab);
            returnObj.transform.SetParent(m_Parent);
            returnObj.SetActive(false);
        }
        // 使用PrefabInfo脚本保存returnObj的一些信息
        ObjectInfo info = returnObj.GetComponent<ObjectInfo>();
        if (info == null)
        {
            info = returnObj.AddComponent<ObjectInfo>();
        }

        info.PoolName = m_PoolName;
        if (lifetime > 0)
        {
            info.Lifetime = lifetime;
        }

        returnObj.transform.position = pos;
        returnObj.SetActive(true);

        return returnObj;
    }

    // "销毁对象" 其实是回收对象
    public virtual void Remove(GameObject obj)
    {
        if (m_PoolQueue.Contains(obj))
        {
            return;
        }

        if (m_PoolQueue.Count > m_MaxCount)
        {
            // 对象池已满 直接销毁
            GameObject.Destroy(obj);
        }
        else
        {
            // 放入对象池
            m_PoolQueue.Enqueue(obj);
            obj.SetActive(false);
        }
    }

    public virtual void Destroy()
    {
        m_PoolQueue.Clear();
    }


}

CubePool 用来对游戏里的对象进行特殊处理 (这里是改变颜色)

CubePool.cs

public class CubePool : ObjectPool
{
    public override GameObject Get(Vector3 pos, float lifetime)
    {
        GameObject obj;
        obj  =  base.Get(pos, lifetime);

        obj.GetComponent<Renderer>().material.color = Random.ColorHSV();

        return obj;
    }
}

ObjcetPoolManager 用来管理多个对象池
ObjcetPoolManager.cs

public class ObjectPoolManager : Singleton<ObjectPoolManager>
{
    private Dictionary<string, ObjectPool> m_PoolDic;

    private Transform m_RootPoolTrans;

    public ObjectPoolManager()
    {
        m_PoolDic = new Dictionary<string, ObjectPool>();

        // 根对象池
        GameObject go = new GameObject("ObjcetPoolManager");
        m_RootPoolTrans = go.transform;
    }

    // 创建一个新的对象池
    public T CreateObjectPool<T>(string poolName) where T : ObjectPool, new()
    {
        if (m_PoolDic.ContainsKey(poolName))
        {
            return m_PoolDic[poolName] as T;
        }

        GameObject obj = new GameObject(poolName);
        obj.transform.SetParent(m_RootPoolTrans);
        T pool = new T();
        pool.Init(poolName, obj.transform);
        m_PoolDic.Add(poolName, pool);
        return pool;
    }

    public GameObject GetGameObject(string poolName, Vector3 position, float lifetTime)
    {
        if (m_PoolDic.ContainsKey(poolName))
        {
            return m_PoolDic[poolName].Get(position, lifetTime);
        }
        return null;
    }

    public void RemoveGameObject(string poolName, GameObject go)
    {
        if (m_PoolDic.ContainsKey(poolName))
        {
            m_PoolDic[poolName].Remove(go);
        }
    }
    
    // 销毁所有对象池
    public void Destroy()
    {
        m_PoolDic.Clear();
        GameObject.Destroy(m_RootPoolTrans);

    }
}

MoveUp.cs 就一个向上运动的脚本

void Update()
 {
     transform.position += Vector3.up * Time.deltaTime * 2;
 }

ObjcetInfo.cs 用来记录对象信息 并且 定时回收对象(可根据需要自己看着办修改)

public class ObjectInfo : MonoBehaviour
{
    public float Lifetime = 0;
    public string PoolName;

    private WaitForSeconds m_WaitTime;

    private void Awake()
    {
        if (Lifetime > 0)
        {
            m_WaitTime = new WaitForSeconds(Lifetime);
        }
    }

    private void OnEnable()
    {
        if (Lifetime > 0)
        {
            StartCoroutine(CountDown(Lifetime));
        }
    }

    IEnumerator CountDown(float lifetime)
    {
        yield return m_WaitTime;
        ObjectPoolManager.Instance.RemoveGameObject(PoolName, gameObject);
    }
}

测试主程序

public class PoolDemo : MonoBehaviour
{
    private ObjectPool m_TestPool;
    public GameObject Prefab;

    public Button TestButton;

    // Start is called before the first frame update
    void Start()
    {
        m_TestPool = ObjectPoolManager.Instance.CreateObjectPool<CubePool>("CubePool");
        m_TestPool.Prefab = Prefab;


        TestButton.onClick.AddListener( () => {

            ObjectPoolManager.Instance.GetGameObject("CubePool", new Vector3(0, 0, 0), 2);
        });
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

  • 11
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值