using System; using System.Collections.Generic; using UnityEngine; public interface IMonoObjectPool where T : MonoBehaviour { IReadOnlyCollection Instances { get; } void Initialize(Func creator, Action disposer, Action onEnterPool, Action onExitPool, int count); T Get(); void Return(T obj); void Dispose(); } public class FixedMonoObjectPool : IMonoObjectPool where T : MonoBehaviour { Action disposer; HashSet instances = new(); Queue pool = new(); Action onEnterPool; Action onExitPool; public IReadOnlyCollection Instances => instances; public void Initialize(Func creator, Action disposer, Action onEnterPool, Action onExitPool, int count) { this.disposer = disposer; this.onEnterPool = onEnterPool; this.onExitPool = onExitPool; for (int i = 0; i < count; ++i) { T obj = creator.Invoke(); onEnterPool.Invoke(obj); instances.Add(obj); pool.Enqueue(obj); } } public T Get() { Debug.Assert(pool.Count > 0, "pool is empty"); var result = pool.Dequeue(); onExitPool.Invoke(result); return result; } public void Return(T obj) { if(instances.Contains(obj)) { onEnterPool.Invoke(obj); pool.Enqueue(obj); } } public void Dispose() { pool.Clear(); foreach (var obj in instances) { disposer.Invoke(obj); } instances.Clear(); } } public class DynamicMonoObjectPool : IMonoObjectPool where T : MonoBehaviour { Func creator; Action disposer; HashSet instances = new(); Queue pool = new(); Action onEnterPool; Action onExitPool; public IReadOnlyCollection Instances => instances; public void Initialize(Func creator, Action disposer, Action onEnterPool, Action onExitPool, int count = 0) { this.creator = creator; this.disposer = disposer; this.onEnterPool = onEnterPool; this.onExitPool = onExitPool; for (int i = 0; i < count; ++i) { T obj = creator.Invoke(); onEnterPool.Invoke(obj); instances.Add(obj); pool.Enqueue(obj); } } public T Get() { if (pool.Count == 0) { T obj = creator.Invoke(); instances.Add(obj); pool.Enqueue(obj); } var result = pool.Dequeue(); onExitPool.Invoke(result); return result; } public void Return(T obj) { if(instances.Contains(obj)) { onEnterPool.Invoke(obj); pool.Enqueue(obj); } } public void Dispose() { pool.Clear(); foreach (var obj in instances) { disposer.Invoke(obj); } instances.Clear(); } }