游戏对象池模式(Unity)

(说明部分后面会写,这里先展示实现)

代码实现(Unity)

三个类

  • Pool (管理 PoolObject,针对单个预制体)
  • PoolObject(池对象)
  • PoolManager(管理 Pool)

PoolObject

namespace GameObjectPool
{
    
    
    /// <summary>
    /// 池中对象
    /// </summary>
    public class PoolObject : MonoBehaviour
    {
    
    
        //名字
        public string poolName;
        //是否在池中
        public bool isPool;
    }
}

Pool

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

namespace GameObjectPool
{
    
    
    public class Pool
    {
    
    
        //池中可用对象
        private Queue<PoolObject> _availableObjects = new Queue<PoolObject>();
        //池的名字
        private string _poolName;
        //对象的预制体
        private GameObject _prefab;
        //池的大小(不是池中有多少对象,是池的大小)
        private int _poolSize;

        public Pool(string poolName, GameObject prefab, int poolSize)
        {
    
    
            _poolName = poolName;
            _prefab = prefab;
            _poolSize = poolSize;
            
            //填充对应数目的对象
            for (int i = 0; i < poolSize; i++)
                AddObjectToPool(CreatePoolObject());    
        }

        private void AddObjectToPool(PoolObject po)
        {
    
    
            //进入队列
            _availableObjects.Enqueue(po);
            po.gameObject.SetActive(false);
            po.isPool = true;
        }

        private PoolObject CreatePoolObject()
        {
    
    
            GameObject go = Object.Instantiate(_prefab);
            if (!go.TryGetComponent(out PoolObject po))
                po = go.AddComponent<PoolObject>();
            po.poolName = _poolName;
            return po;
        }
        
        /// <summary>
        /// 获得一个池对象(队列有则返回,没有则创建并返回)
        /// </summary>
        /// <returns></returns>
        public PoolObject GetAvailableObject(Vec3 pos, Quat rot)
        {
    
    
            PoolObject po = null;
            if (_availableObjects.Count > 0)
                po = _availableObjects.Dequeue();
            else
            {
    
    
                po = CreatePoolObject();
                _poolSize++;
            }

            GameObject go = null;
            if (po != null)
            {
    
    
                po.isPool = false;
                go = po.gameObject;
                go.SetActive(true);
                go.transform.SetPositionAndRotation(pos.ToVector3, rot.ToQuaternion);
            }

            return po;
        }
        
        /// <summary>
        /// 回收池对象
        /// </summary>
        /// <param name="po"></param>
        public void RecyclePoolObject(PoolObject po)
        {
    
    
            if (_poolName.Equals(po.poolName))
            {
    
    
                if (po.isPool) 
                    Debug.LogWarning(po.gameObject.name + " is already in pool.");
                else
                    AddObjectToPool(po);
            }
            else
                Debug.LogError($"Trying to add object to incorrect pool {
      
      po.poolName} {
      
      _poolName}");
        }
    }
}

PoolManager

using System;
using System.Collections.Generic;
using MyMath;
using Other;
using UnityEngine;

namespace GameObjectPool
{
    
    
    [System.Serializable]
    public class PoolInfo
    {
    
    
        public string name;
        public GameObject prefab;
        public int count;
    }
    
    /// <summary>
    /// 池管理类(单例)
    /// </summary>
    public class PoolManager : Singleton<PoolManager>
    {
    
    
        [SerializeField] private PoolInfo[] _poolInfos;

        private Dictionary<string, Pool> _poolMap = new Dictionary<string, Pool>();

        private void Start()
        {
    
    
            CheckPoolName();
            CreatePool();
        }
        
        /// <summary>
        /// 检测池的名称是否重复
        /// </summary>
        private void CheckPoolName()
        {
    
    
            for (int i = 0; i < _poolInfos.Length; i++)
                for (int j = i + 1; j < _poolInfos.Length; j++)
                    if (_poolInfos[i].name.Equals(_poolInfos[j].name))
                        Debug.LogError($"Pool {
      
      i} & {
      
      j} have the same name. Assign different names.");
        }

        private void CreatePool()
        {
    
    
            foreach (var info in _poolInfos)
            {
    
    
                _poolMap.Add(info.name, new Pool(info.name, info.prefab, info.count));
            }
        }

        public PoolObject GetPoolObject(string poolName, Vec3 pos, Quat rot)
        {
    
    
            PoolObject po = null;
            if (_poolMap.ContainsKey(poolName))
                po = _poolMap[poolName].GetAvailableObject(pos, rot);
            else
                Debug.LogError("Invalid pool name specified : " + poolName);

            return po;
        }

        public void RecyclePoolObject(PoolObject po)
        {
    
    
            if (po == null)
                Debug.LogWarning("Specified object is not a pooled instance: " + po.poolName);
            else
            {
    
    
                if (_poolMap.ContainsKey(po.poolName))
                    _poolMap[po.poolName].RecyclePoolObject(po);
                else
                    Debug.LogError("No pool available with name : " + po.poolName);
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/m0_52361859/article/details/127327266