using System; using System.Collections.Generic; namespace OM { /// /// Interface for objects that want to receive spawn/despawn lifecycle callbacks from the object pool. /// /// The type of object in the pool. public interface IOMObjectPool { /// /// Called when the object is spawned from the pool. /// /// The pool that spawned the object. void OnSpawn(OMObjectPool pool); /// /// Called when the object is returned (despawned) to the pool. /// void OnDespawn(); } /// /// A generic object pool system that supports optional spawn/despawn events and a maximum capacity. /// /// The type of objects managed by this pool. public class OMObjectPool { private readonly Func _createObjFunc; private readonly Action _onDespawnObj; private readonly Action _onSpawn; private readonly bool _useIPool; private readonly int _maxCapacity; private readonly List _list; private readonly List _spawned; /// /// Gets the number of currently spawned (active) objects. /// public int GetSpawnedCount => _spawned.Count; /// /// Creates a new object pool. /// /// Maximum allowed spawned objects. /// Number of objects to pre-create and add to the pool. /// Whether to call IOMObjectPool callbacks. /// Delegate for creating new instances. /// Optional callback when an object is spawned. /// Optional callback when an object is despawned. public OMObjectPool(int maxCapacity, int preload, bool useIPool, Func createObjFunc, Action onSpawn = null, Action onDespawn = null) { _createObjFunc = createObjFunc ?? throw new ArgumentNullException("Create Function is null" + nameof(createObjFunc)); _useIPool = useIPool; _onDespawnObj = onDespawn; _onSpawn = onSpawn; _maxCapacity = maxCapacity; _list = new List(); _spawned = new List(); for (var i = 0; i < preload; i++) { var obj = _createObjFunc(); _list.Add(obj); } } /// /// Spawns an object from the pool. Creates a new one if needed. /// Recycles old objects if max capacity is reached. /// /// The spawned object. public T Spawn() { T obj; if (_list.Count <= 0) { if (_spawned.Count >= _maxCapacity) { obj = _spawned[0]; _spawned.RemoveAt(0); if (_useIPool) { var pool = obj as IOMObjectPool; pool?.OnDespawn(); } } else { obj = _createObjFunc(); } } else { obj = _list[0]; _list.RemoveAt(0); } _onSpawn?.Invoke(obj); if (_useIPool) { var pool = obj as IOMObjectPool; pool?.OnSpawn(this); } _spawned.Add(obj); return obj; } /// /// Returns an object back to the pool. /// /// The object to despawn. public void Despawn(T obj) { _onDespawnObj?.Invoke(obj); if (_useIPool) { var pool = obj as IOMObjectPool; pool?.OnDespawn(); } _list.Add(obj); _spawned.Remove(obj); } } }