using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using UnityEngine; public class ObjectPool : IEnumerable where T : MonoBehaviour { public int Capacity { get; private set; } private Func actionOnCreate; private Action actionOnGet; private Action actionOnRelease; private Action actionOnDestroy; private readonly List activePoolElements; private readonly Queue inactivePoolElements; private readonly Dictionary componentCache; public ObjectPool(Func actionOnCreate, Action actionOnGet, Action actionOnRelease, Action actionOnDestroy, int initialCapacity) { Capacity = initialCapacity; this.actionOnCreate = actionOnCreate; this.actionOnGet = actionOnGet; this.actionOnRelease = actionOnRelease; this.actionOnDestroy = actionOnDestroy; activePoolElements = new List(); inactivePoolElements = new Queue(); componentCache = new Dictionary(); for (uint i = 0; i < Capacity; i++) { var obj = actionOnCreate(); inactivePoolElements.Enqueue(obj); obj.gameObject.SetActive(false); } } public bool ContainsElement(T element) { return ContainsElement(element, true) || ContainsElement(element, false); } public bool ContainsElement(T element,bool isActive) { if (isActive) { return activePoolElements.Contains(element); } else { return inactivePoolElements.Contains(element); } } public bool TryGetFromPos(in Vector3 pos,out T element) { element = null; foreach (var obj in activePoolElements) { if (pos == obj.gameObject.transform.position) { actionOnGet.Invoke(obj); element = obj; return true; } } return false; } public T Get() { if (TryGet(out var element)) { return element; } T instance = ExpandPool(); return instance; } // (int id, Type type) key = (obj.GetInstanceID(), typeof(T)); // T component; // if (_componentCache.ContainsKey(key)) // { // component = _componentCache[key] as T; // if (component == null) { _componentCache.Remove(key); } // else { return component; } // } // component = obj.GetComponent(); //if (component != null) { _componentCache[key] = component; } //return component; public C GetComponentFromPool() where C : Component { C component = null; if (TryGet(out var element)) { int key = element.GetInstanceID(); if (componentCache.ContainsKey(key)) { component = componentCache[key] as C; if (component == null) componentCache.Remove(key); else return component; } component = element.GetComponent(); if (component) { componentCache[key] = component; } return component; } T instance = ExpandPool(); int key1 = instance.GetInstanceID(); component = instance.GetComponent(); if (component) { componentCache[key1] = component; } return component; } public C GetComponentFromPool(T obj) where C : Component { C component = null; int key = obj.GetHashCode(); if (componentCache.TryGetValue(key, out var value)) { return value as C; } else { componentCache.Remove(key); } component = obj.GetComponent(); if (component) { componentCache[key] = component; } return component; } private T ExpandPool() { var obj = actionOnCreate(); Capacity++; obj.gameObject.SetActive(true); activePoolElements.Add(obj); return obj; } private bool TryGet(out T element) { element = null; if (inactivePoolElements.Count > 0) { var obj = inactivePoolElements.Dequeue(); if (obj == null) { return false; } element = obj; actionOnGet.Invoke(element); activePoolElements.Add(obj); return true; } return false; } public void Destroy(T obj) { activePoolElements.Remove(obj); actionOnDestroy.Invoke(obj); } public void DestroyAllElements() { DestroyAllElements(true); DestroyAllElements(false); } public void DestroyAllElements(bool isActive) { if (isActive) { foreach (var obj in activePoolElements) { Destroy(obj); } activePoolElements.Clear(); } else { foreach (var obj in inactivePoolElements) { Destroy(obj); } inactivePoolElements.Clear(); } } public void ReturnAllElementsToPool() { foreach (var obj in activePoolElements) { ReturnToPool(obj); } activePoolElements.Clear(); } public int GetInactiveElementsCount() { return inactivePoolElements.Count(); } public int GetActiveElementsCount() { return activePoolElements.Count(); } public void ReturnToPool(T obj) { if (obj == null) { activePoolElements.RemoveAll(o => o == null); return; } if (activePoolElements.Remove(obj)) { actionOnRelease.Invoke(obj); inactivePoolElements.Enqueue(obj); } } public IEnumerator GetEnumerator() { return activePoolElements.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } }