SamsonGame/Assets/Scripts/Core/ObjectPool/ObjectPool.cs

83 lines
2.3 KiB
C#

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<GameObject> _buffer = new List<GameObject>();
private readonly List<GameObject> _inactive = new List<GameObject>();
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<TemplateReference>().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);
}
}
}