分享一个看到的有意思的对象池(灵活对象池)

分享一个看到的有意思的对象池(灵活对象池)

相比于传统的对象池中的对象是拿到对象之后在另外的脚本中书写逻辑,能不能给对象池中的对象都创建一个基类,创建回收或者销毁都在该池子中实现呢,并且一般的对象池不能去使用Unity常规API进行销毁其中的对象只有回收和释放,能不能有一种更自由的方式呢,根据不同的项目进行取舍即可没有最优只有最适合的方式。

1.ObjectPool

这个是对象池的总管理,里面记录着子对象池,有着创建和回收的功能

public class ObjectPool
{
    private static ObjectPool _instance;
    public static ObjectPool Instance
    {
        get { return _instance ?? (_instance = new ObjectPool()); }
    }
    
    private Dictionary<string, SubPool> poolDict = new Dictionary<string, SubPool>();

    public GameObject Create(GameObject prefab, string path)
    {
        if (!poolDict.ContainsKey(path))
        {
            SubPool subPool = new SubPool(prefab,path);
            poolDict.Add(path,subPool);
        }

        return poolDict[path].Create();
    }
    
    public void Recycle(GameObject obj)
    {
        if (obj.GetComponent<RecoverableObject>() == null)
        {
            Debug.LogError("回收失败,物体" + obj.name + "需要挂载 RecoverableObject 脚本");
        }
        obj.GetComponent<RecoverableObject>().OnRecycle();
        obj.SetActive(false);
    }
    
    public void Clear() {

        foreach (KeyValuePair<string,SubPool> pool in poolDict)
        {
            pool.Value.ClearAll();
        }
    } 
    
    internal void Remove(RecoverableObject recoverableObject)
    {
        SubPool subPool = poolDict[recoverableObject.poolID];
        subPool.Remove(recoverableObject);
    }
}

2.SubPool

子对象池,里面记录着某个预制体的对象池集合

public class SubPool
{
    private List<GameObject> m_ObjectList = new List<GameObject>();
    private GameObject m_Prefab;
    private string poolID;

    public SubPool(GameObject prefab,string poolID)
    {
        m_Prefab = prefab;
        this.poolID = poolID;
    }

    public GameObject Create()
    {
        GameObject target = null;
        foreach (GameObject go in m_ObjectList)
        {
            if (!go.activeInHierarchy)
            {
                target = go;
                break;
            }
        }

        if (target == null)
        {
            target = GameObject.Instantiate(m_Prefab);
            m_ObjectList.Add(target);
        }

        if (target.GetComponent<RecoverableObject>() == null)
        {
            Debug.LogError("生成失败,物体" + m_Prefab.name + "需要挂载 RecoverableObject 脚本");
        }

        target.GetComponent<RecoverableObject>().poolID = poolID;
        target.SetActive(true);
        target.GetComponent<RecoverableObject>().OnGenerate();
        return target;
    }

    public void RecycleAll()
    {
        foreach (GameObject obj in m_ObjectList) {
            if (!obj.activeInHierarchy) continue;
            if (obj.GetComponent<RecoverableObject>() == null)
            {
                Debug.LogError("回收失败,物体" + m_Prefab.name + "需要挂载 RecoverableObject 脚本");
            }   
            obj.GetComponent<RecoverableObject>().OnRecycle();
            obj.SetActive(false);
        }
    }
    
    public void Remove(RecoverableObject recoverableObject)
    {
        m_ObjectList.Remove(recoverableObject.gameObject);
    }
    
    public void ClearAll() {
        foreach (GameObject obj in m_ObjectList)
        {
            GameObject.Destroy(obj);
        }
        m_ObjectList.Clear();
    }
}

3.RecoverableObject

可回收的基类,所有对象池中的对象都应该挂载此类

public class RecoverableObject : MonoBehaviour
{
    public string poolID;
    
    public virtual void OnGenerate() { }

    public virtual void OnRecycle() { }

    public void OnDestroy()
    {
        ObjectPool.Instance.Remove(this);
    }
}

4.测试

public class Test : MonoBehaviour
{
    [SerializeField] private GameObject prefab;
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.K))
        {
            StartCoroutine(Delay());
        }
    }

    private IEnumerator Delay()
    {
        GameObject cube = ObjectPool.Instance.Create(prefab, "Cube");
        yield return new WaitForSeconds(2f);
        ObjectPool.Instance.Recycle(cube);
    }
}

这种对象池非常自由,我甚至可以手动用Unity的销毁对象方式销毁池中物体。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值