| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 | using System.Collections.Generic;using UnityEngine;namespace HQFPSWeapons{    public class ObjectPool    {        public string Id { get => m_Id; }        private GameObject m_Template;        private Transform m_Parent;        private string m_Id;        private List<PoolableObject> m_AvailableObjects;        private List<PoolableObject> m_InUseObjects;        private int m_MinSize;        private int m_MaxSize;        private int m_CurrentSize;        private bool m_Initialized;        private float m_LastObjectGetTime;        private bool m_AutoShrink;        private float m_NextShrinkTime;        private float m_AutoReleaseDelay;        public ObjectPool(string id, GameObject template, int minSize, int maxSize, bool autoShrink, float autoReleaseDelay, Transform parent)        {            if(template == null)            {                Debug.LogError("You want to create an object pool for an object that is null!!");                return;            }            // Create and store a new template, and it's hash code            m_Template = Object.Instantiate(template, parent);            m_Template.SetActive(false);            m_Parent = parent;            m_Id = id;            // Store the min & max sizes for this pool            m_MinSize = minSize;            m_MaxSize = Mathf.Clamp(maxSize, m_MinSize, int.MaxValue);            m_CurrentSize = m_MinSize;            // Initialize the lists            m_AvailableObjects = new List<PoolableObject>(m_MaxSize);            m_InUseObjects = new List<PoolableObject>(m_MaxSize);                     // Spawn the default objects (more will be spawned if needed, according to minSize & maxSize)            for(int i = 0;i < m_CurrentSize;i++)            {                PoolableObject obj = CreateNewObject(m_Template, m_Parent, m_Id);                obj.gameObject.SetActive(false);                m_AvailableObjects.Add(obj);            }            m_AutoShrink = autoShrink;            m_AutoReleaseDelay = autoReleaseDelay;            // Mark this pool as initialized. Means it can now be used.            m_Initialized = true;        }        public void Update()        {            if(m_AutoShrink && m_AvailableObjects.Count > m_MinSize && Time.time > m_LastObjectGetTime + 60f && Time.time > m_NextShrinkTime)            {                PoolableObject objToDestroy = m_AvailableObjects[m_AvailableObjects.Count - 1];                m_AvailableObjects.RemoveAt(m_AvailableObjects.Count - 1);                Object.Destroy(objToDestroy);                m_NextShrinkTime = Time.time + 0.5f;                m_CurrentSize--;            }        }        public PoolableObject GetObject()        {            if(!m_Initialized)            {                Debug.LogError("This pool can not be used, it's not initialized properly!");                return null;            }            PoolableObject obj = null;            if(m_AvailableObjects.Count > 0)            {                obj = m_AvailableObjects[m_AvailableObjects.Count - 1];                // Move the object into the "in use list".                m_AvailableObjects.RemoveAt(m_AvailableObjects.Count - 1);                m_InUseObjects.Add(obj);            }            // Grow the pool.            else if(m_CurrentSize < m_MaxSize)            {                m_CurrentSize++;                obj = CreateNewObject(m_Template, m_Parent, m_Id);                m_InUseObjects.Add(obj);            }            // The pool has reached it's max size, use the oldest in-use object.            else            {                obj = m_InUseObjects[0];                m_InUseObjects[0] = m_InUseObjects[m_InUseObjects.Count - 1];                m_InUseObjects[m_InUseObjects.Count - 1] = obj;            }            m_LastObjectGetTime = Time.time;            obj.gameObject.SetActive(true);            obj.OnUse();            if(m_AutoReleaseDelay != Mathf.Infinity)                PoolingManager.Instance.QueueObjectRelease(obj, m_AutoReleaseDelay);            return obj;        }        public bool TryPoolObject(PoolableObject obj)        {            if(!m_Initialized)            {                Debug.LogError("This pool can not be used, it's not initialized properly!");                return false;            }            if(obj == null)            {                Debug.LogError("The object you want to pool is null!!");                return false;            }            if(m_Id != obj.PoolId)            {                Debug.LogError("You want to put an object back in this pool, but it doesn't belong here!!");                return false;            }            m_InUseObjects.Remove(obj);            m_AvailableObjects.Add(obj);            obj.OnReleased();            obj.transform.SetParent(m_Parent);            obj.gameObject.SetActive(false);            return true;        }        private PoolableObject CreateNewObject(GameObject template, Transform parent, string poolId)        {            if(template == null)                return null;            GameObject obj = Object.Instantiate(template, parent);            PoolableObject poolableObj = obj.GetComponent<PoolableObject>();            if(poolableObj == null)                poolableObj = obj.AddComponent<PoolableObject>();            poolableObj.Init(poolId);            return poolableObj;        }    }}
 |