You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
3.0 KiB
140 lines
3.0 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public interface IMonoObjectPool<T> where T : MonoBehaviour
|
|
{
|
|
IReadOnlyCollection<T> Instances { get; }
|
|
|
|
void Initialize(Func<T> creator, Action<T> disposer, Action<T> onEnterPool, Action<T> onExitPool, int count);
|
|
T Get();
|
|
void Return(T obj);
|
|
void Dispose();
|
|
}
|
|
|
|
public class FixedMonoObjectPool<T> : IMonoObjectPool<T> where T : MonoBehaviour
|
|
{
|
|
Action<T> disposer;
|
|
|
|
HashSet<T> instances = new();
|
|
Queue<T> pool = new();
|
|
|
|
Action<T> onEnterPool;
|
|
Action<T> onExitPool;
|
|
|
|
public IReadOnlyCollection<T> Instances => instances;
|
|
|
|
public void Initialize(Func<T> creator, Action<T> disposer, Action<T> onEnterPool, Action<T> 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<T> : IMonoObjectPool<T> where T : MonoBehaviour
|
|
{
|
|
Func<T> creator;
|
|
Action<T> disposer;
|
|
|
|
HashSet<T> instances = new();
|
|
Queue<T> pool = new();
|
|
|
|
Action<T> onEnterPool;
|
|
Action<T> onExitPool;
|
|
|
|
public IReadOnlyCollection<T> Instances => instances;
|
|
|
|
public void Initialize(Func<T> creator, Action<T> disposer, Action<T> onEnterPool, Action<T> 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();
|
|
}
|
|
}
|