using System; using System.Collections.Generic; using UniRx; using UniRx.Triggers; using UnityEngine; using Object = UnityEngine.Object; namespace RND { public class ObjectPool : MonoBehaviour { public GameObject Template { get; private set; } private readonly List _buffer = new List(); private readonly List _inactive = new List(); private readonly CompositeDisposable _destroySub = new CompositeDisposable(); public ObjectPool Init(GameObject template) { Template = template; return this; } public GameObject Reuse() { GameObject result; if (_inactive.Count > 0) { int lastIndex = _inactive.Count - 1; result = _inactive[lastIndex]; _inactive.RemoveAt(lastIndex); } else { result = InstantiateObject(); } result.SetActive(true); result.SendMessage("OnReused", SendMessageOptions.DontRequireReceiver); return result; } private GameObject InstantiateObject() { GameObject result = Instantiate(Template, transform); result.AddComponentOnce().Template = Template; result.OnDestroyAsObservable().Subscribe(_ => { _buffer.Remove(result); _inactive.Remove(result); }).AddTo(_destroySub); // TODO - убрать зависимость от UniRx _buffer.Add(result); return result; } public void Release(GameObject instance) { if(instance == null) return; if (!_buffer.Contains(instance)) throw new Exception($"{instance.name} doesn't belong to this pool"); instance.SetActive(false); instance.SendMessage("OnReleased", SendMessageOptions.DontRequireReceiver); _inactive.Add(instance); } private void OnDestroy() { _destroySub.Dispose(); _buffer.ForEach(Destroy); _buffer.Clear(); _inactive.Clear(); } public void Destroy() { Object.Destroy(gameObject); } } }