using System; using System.Collections.Generic; using UniRx; using UniRx.Triggers; using UnityEngine; namespace RND { public class ObjectPoolManager : LazySingleton { private readonly Dictionary _poolsDict = new Dictionary(); private readonly List _poolsList = new List(); private readonly CompositeDisposable _poolsDestroySubs = new CompositeDisposable(); public ObjectPool CreatePool(GameObject template) { ObjectPool pool = CreateLocalPool(template); pool.gameObject.OnDestroyAsObservable().Subscribe(x => { UnregisterPool(pool); }).AddTo(_poolsDestroySubs); RegisterPool(pool); return pool; } public ObjectPool CreateLocalPool(GameObject template) { var pool = new GameObject($"{template.name} Pool"); return pool.AddComponent().Init(template); } public ObjectPool EnsurePoolByTemplate(GameObject template) { return _poolsDict.ContainsKey(template) ? _poolsDict[template] : CreatePool(template); } public ObjectPool EnsurePoolByInstance(GameObject instance) { return EnsurePoolByTemplate(ExtractTemplate(instance)); } private GameObject ExtractTemplate(GameObject instance) { if (instance.TryGetComponent(out TemplateReference reference) && reference.Template != null) { return reference.Template; } else { throw new Exception($"{instance.name} doesn't belong to any pool"); } } private void OnDestroy() { DestroyAllPools(); } public void DestroyAllPools() { _poolsDestroySubs.Clear(); _poolsList.ForEach(x => x.Destroy()); _poolsDict.Clear(); _poolsList.Clear(); } public void DestroyPoolByInstance(GameObject instance) { DestroyPoolByTemplate(ExtractTemplate(instance)); } private void DestroyPoolByTemplate(GameObject template) { if (_poolsDict.TryGetValue(template, out ObjectPool pool)) { pool.Destroy(); UnregisterPool(pool); } } public void RegisterPool(ObjectPool pool) { _poolsDict.Add(pool.Template, pool); _poolsList.Add(pool); } public void UnregisterPool(ObjectPool pool) { _poolsList.Remove(pool); _poolsDict.Remove(pool.Template); } } }