Unity简单的对象池实例

using System.Collections.Generic;
using UnityEngine;

public class SimplePool : MonoBehavior
{
    // 物体的池子,用字典表示。键为种类 ID,值是同类物体的队列
    // 以预制体的 ID 作为每个种类的标识 ID
    private Dictionary<int, Queue<GameObject>> m_Pool = new Dictionary<int, Queue<GameObject>>{};

    // 记录所有离开对象池的物体。键是物体引用,值是种类 ID
    // 离开对象池的物体会从 m_Pool 中离开,但是要记录在 m_OutObjs 字典里
    private Dictionary<GameObject, int> m_OutObjs = new Dictionary<GameObject, int>{};

    // 创建物体,预制体由调用者自备
    public GameObject Create(GameObject prefab)
    {
        // 以预制体的物体 ID,作为该类型物体的 ID
        int id = prefab.GetInstanceID();
        // 尝试从对象池中获取这个物体
        GameObject go = _GetFromPool(id);
        if(go == null)
        {
            // 取不到物体,就根据预制体创建物体
            go = Instantiate<GameObject>(prefab);
            // 如果初次遇到这类物体,需要添加一个新的类型
            if(!m_Pool.ContainsKey(id))
            {
                m_Pool.Add(id, new Queue<GameObject>());
            }
        }

        // 标记新创建的物体离开了对象池
        m_OutObjs.Add(go, id);
        return go;
    }

    // 销毁(回收)物体
    public void Destroy(GameObject go)
    {
        // 判断物体是不是由对象池创建
        if(!m_OutObjs.ContainsKey(go))
        {
            Debug.LogWarning("回收的物体并不是对象池创建的!" + go);
            return;
        }

        // 该物体属于哪个种类
        int id = m_OutObjs[go];

        go.transform.parent = transform;
        go.SetActive(false);

        // 加入队列,并且去掉离开的标记
        m_Pool[id].Enqueue(go);
        m_OutObjs.Remove(go);
    }

    // 从对象池中根据类型 ID 取出物体。如果类型不存在或者物体暂时用完了,返回 null
    private GameObject _GetFromPool(int id)
    {
        if(!m_Pool.ContainsKey(id) || m_Pool[id].Count == 0)
        {
            return null;
        }
        GameObject obj = m_Pool[id].Dequeue();
        obj.SetActive(true);
        return obj;
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容