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


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

    相比于传统的对象池中的对象是拿到对象之后在另外的脚本中书写逻辑,能不能给对象池中的对象都创建一个基类,创建回收或者销毁都在该池子中实现呢,并且一般的对象池不能去使用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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    3.RecoverableObject

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

    public class RecoverableObject : MonoBehaviour
    {
        public string poolID;
        
        public virtual void OnGenerate() { }
    
        public virtual void OnRecycle() { }
    
        public void OnDestroy()
        {
            ObjectPool.Instance.Remove(this);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

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

  • 相关阅读:
    RHCE之WEB服务器作业
    【尚硅谷React】——React全家桶笔记
    阿里云服务器公网带宽如何修改?
    AI推介-多模态视觉语言模型VLMs论文速览(arXiv方向):2024.05.01-2024.05.10
    python及第三方库交叉编译
    爬虫在金融领域的应用:股票数据收集
    阿里云ASK试用心得(避坑贴)
    12. Java异常及异常处理处理
    kubenates的傻瓜式部署教程(K8S部署教程)
    使用PowerShell脚本来一键开启、关闭FTP服务
  • 原文地址:https://blog.csdn.net/zzzsss123333/article/details/133753523