unity 对象池

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//对象类
public class Poolable:MonoBehaviour
{
    public string key = string.Empty;//
    public bool isPooled = false;//判断创建的预制体对象是否存在对象池
    public GameObject gameObject;//游戏对象
}

对象池管理类

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

public class GameObjectPoolController : MonoBehaviour
{
    private static GameObjectPoolController m_instance;//单例
    private static Dictionary<string, PoolData> pools = new Dictionary<string, PoolData>();//保存key到PoolData类的映射关系
    public static GameObjectPoolController m_Instance {
        get
        {
            if(m_instance==null)
            {
                CreateSharedInstance();
            }
            return m_instance;
        }
    }

    void Awake()
    {
        if(m_instance!=null&&m_instance!=this)
        {
            Destroy(m_instance);
        }
        else
        {
           m_instance = this;
        }
    }
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    /// <summary>
    /// 设置内存中对象可存储最大数目
    /// </summary>
    /// <param name="key"></param>
    /// <param name="maxCount"></param>
    public static void SetMaxCount(string key,int maxCount)
    {
        if (!pools.ContainsKey(key))//对象池没有该对象
        {
            return;
        }
        PoolData data = pools[key];
        data.maxCount = maxCount;
    }
    /// <summary>
    /// 指定key映射到预制体
    /// 预创建多少对象
    /// </summary>
    /// <param name="key"></param>
    /// <param name="prefab"></param>
    /// <param name="prepopulateNum"></param>
    /// <param name="maxCount"></param>
    /// <returns></returns>
    public static bool AddEntry(string key,GameObject prefab,int prepopulateNum,int maxCount)
    {
        if (pools.ContainsKey(key))//对象池已存在该对象
        {
            return false;
        }
        PoolData data = new PoolData();
        data.prefab = prefab;
        data.maxCount = maxCount;
        data.pool = new Queue<Poolable>();
        pools.Add(key, data);//加入到对象池
        for(int i = 0; i < prepopulateNum; i++)
        {
            Enqueue(CreateInstance(key, prefab));//入队
        }
        return true;
    }
    /// <summary>
    /// 根据键值清除对象池中的对象
    /// </summary>
    /// <param name="key"></param>
    public static void ClearEntry(string key)
    {
        if (!pools.ContainsKey(key))//无对象
        {
            return;
        }
        PoolData data = pools[key];
        while (data.pool.Count > 0)
        {
            Poolable poolable = data.pool.Dequeue();
            if (poolable != null)
            {
                Destroy(poolable.gameObject);
            }
        }
        pools.Remove(key);
    }
    /// <summary>
    /// 将创建对象存储到对象池中
    /// </summary>
    /// <param name="sender"></param>
    public static void Enqueue(Poolable sender)
    {
        if(sender==null||sender.isPooled||!pools.ContainsKey(sender.key))
        {
            return;
        }
        PoolData data = pools[sender.key];
        if (data.pool.Count >= data.maxCount)
        {
            GameObject.Destroy(sender.gameObject);
            return;
        }
        data.pool.Enqueue(sender);
        sender.isPooled = true;
        sender.gameObject.transform.SetParent(m_Instance.transform);//把父节点设为对象池
        sender.gameObject.SetActive(false);//不可见
    }
    /// <summary>
    /// 从对象池中取对象
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public static Poolable Dequeue(string key)
    {
        if(!pools.ContainsKey(key))//不存在
        {
            return null;
        }
        PoolData data = pools[key];
        if (data.pool.Count == 0)
        {
            return CreateInstance(key, data.prefab);
        }
        Poolable poolable = data.pool.Dequeue();
        poolable.isPooled = false;
        return poolable;
    }
    /// <summary>
    /// 创建游戏对象实例,为游戏对象实例添加Poolable脚本
    /// 设置游戏对象属性
    /// </summary>
    /// <param name="key"></param>
    /// <param name="prefab"></param>
    /// <returns></returns>
    public static Poolable CreateInstance(string key,GameObject prefab)
    {
        GameObject gameObject = Instantiate(prefab) as GameObject;
        Poolable poolable = gameObject.AddComponent<Poolable>();
        poolable.key = key;
        poolable.gameObject = gameObject;
        return poolable;
    }
    /// <summary>
    /// 
    /// </summary>
    public static void CreateSharedInstance()
    {
        GameObject gameObject = new GameObject("GameObjectPoolController");
        m_instance = gameObject.AddComponent<GameObjectPoolController>();
        DontDestroyOnLoad(gameObject);//页面切换不被销毁
    }
}

对象池中的对象管理类

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

public class PoolData : MonoBehaviour
{
    public GameObject prefab = null;//新建对象实例的预制体
    public int maxCount = 0;//内存中可以存储的对象最大数目
    public Queue<Poolable> pool;//存储可重用对象实例
}
posted @ 2019-10-08 15:12  电竞毒奶  阅读(308)  评论(0编辑  收藏  举报