using System; using System.Collections; using System.Collections.Generic; 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 List activePoolElements; private Queue inactivePoolElements; 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(); 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; } 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(); } }