复杂嵌套的对象池(5)——对象池的统一管理和拓展

【统一管理对象池】

统一管理对象池,需要提供初始化、借出对象、回收对象、增加对象池、减少对象池、清空对象池的方法,比较简单。

【代码实现】

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

namespace Cache
{
    public class ObjectPoolManager
    {
        private static ObjectPoolManager _instance;
        public static ObjectPoolManager Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new ObjectPoolManager();
                return _instance;
            }
        }

        public Dictionary<string, ObjectPoolBase> pools = new Dictionary<string, ObjectPoolBase>();
        private Dictionary<int, string> lentInstance2Object = new Dictionary<int, string>();

        private ObjectPoolAsset objectPoolAsset;

        private string assetPath = "Assets/Resources/ObjectPoolAsset.asset";
#if UNITY_EDITOR
        public void Awake()
        {
            objectPoolAsset = Resources.Load<ObjectPoolAsset>(assetPath);
            if (objectPoolAsset == null)
            {
                objectPoolAsset = ScriptableObject.CreateInstance<ObjectPoolAsset>();
                AssetDatabase.CreateAsset(objectPoolAsset, assetPath);
                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();
            }
        }
#endif
        public void InitPool()
        {
#if !UNITY_EDITOR
        objectPoolAsset = Resources.Load<ObjectPoolAsset>(assetPath);//不是Editor的情况下如何载入配置,这个可以根据需要自己写
#endif
            foreach (PoolInfo poolInfo in objectPoolAsset.poolInfos)
            {
                AddPool(poolInfo);
            }
        }

        public GameObject LendObjectOut(string poolName, string objectName, Transform parent = null, object[] extradata = null)
        {
            GameObject go = null;
            if(!pools.ContainsKey(poolName))
            {
                Debug.LogWarning("该对象池不存在:" + poolName);
                return null;
            }
            go = pools[poolName].LendObjectOut(objectName, parent, extradata);  
            if(go)
            {
                lentInstance2Object[go.GetInstanceID()] = poolName;
            }
            return go;
        }

        public bool RecycleObject(GameObject go)
        {
            if (go == null)
                return false;

            if (!lentInstance2Object.ContainsKey(go.GetInstanceID()))//表示不是从该对象池中借出的
                return false;
            
            return pools[lentInstance2Object[go.GetInstanceID()]].RecycleObject(go);
        }

        public bool AddPool(PoolInfo poolInfo)
        {
            if (pools.ContainsKey(poolInfo.poolName))
            {
                Debug.LogWarning("已包含该对象池:" + poolInfo.poolName);
                return false;
            }
            switch (poolInfo.poolType)
            {
                case PoolType.Single:
                    pools.Add(poolInfo.poolName, new SingleObjectPool(poolInfo.capacity, poolInfo.poolName, poolInfo.expansionStrategy));
                    break;
                case PoolType.Multi:
                    pools.Add(poolInfo.poolName, new MultiObjectPool(poolInfo));
                    break;
                case PoolType.ObjectType:
                    pools.Add(poolInfo.poolName, new ObjectTypePool(poolInfo));
                    break;
                case PoolType.StageType:
                    pools.Add(poolInfo.poolName, new StageObjectPool(poolInfo));
                    break;
                case PoolType.NONE:
                    Debug.LogWarning("无效的对象池类型:" + poolInfo.poolName);
                    break;
            }
            return true;    
        }

        public bool RemovePool(string poolName)
        {
            if (!pools.ContainsKey(poolName))
            {
                Debug.LogWarning("不存在该对象池:" + poolName);
                return false;
            }

            ObjectPoolBase pool = pools[poolName];
            pools.Remove(poolName);
            pool.Dispose();
            return true;
        }

        public void ClearPool()
        {
            foreach (var item in pools.Values)
            {
                item.Dispose();
            }
            pools.Clear();
            lentInstance2Object.Clear();
        }

    }
}

【拓展】

1.扩展编辑器:保证在任意编辑ObjectPoolAsset.asset时,不会导致在InitPool()时报错,目前的代码里并没有控制。

2.减少内存:依靠lentInstance2Object来找到对象属于哪个池子,因为做了多层嵌套,会导致重复,可以给物体添加一个类来读取,就省去了lentInstance2Object。

3.全部用ObjectPoolBase来实现不同类型的对象池的自由组合

4.改用基于AA的加载方式来加载物体

5.添加异步加载的方法

猜你喜欢

转载自blog.csdn.net/enternalstar/article/details/125852981