LMQT/Assets/TouchScript/Scripts/Utils/ObjectPool.cs
2024-12-10 09:03:45 +08:00

128 lines
3.7 KiB
C#

/*
* @author Valentin Simonov / http://va.lent.in/
* Source code copied from UnityEngine.UI.ObjectPool:
* https://bitbucket.org/Unity-Technologies/ui/src/ccb946ecc23815d1a7099aee0ed77b0cde7ff278/UnityEngine.UI/UI/Core/Utility/ObjectPool.cs?at=5.1
*/
using System;
using System.Collections.Generic;
using UnityEngine.Events;
#if OBJECTPOOL_DEBUG
using UnityEngine;
#endif
namespace TouchScript.Utils
{
/// <exclude />
public class ObjectPool<T> where T : class
{
public delegate T0 UnityFunc<T0>();
private readonly Stack<T> stack;
private readonly UnityAction<T> onGet;
private readonly UnityAction<T> onRelease;
private readonly UnityFunc<T> onNew;
public string Name { get; set; }
public int CountAll { get; private set; }
public int CountActive
{
get { return CountAll - CountInactive; }
}
public int CountInactive
{
get { return stack.Count; }
}
public ObjectPool(int capacity, UnityFunc<T> actionNew, UnityAction<T> actionOnGet = null,
UnityAction<T> actionOnRelease = null, string name = null)
{
if (actionNew == null) throw new ArgumentException("New action can't be null!");
stack = new Stack<T>(capacity);
onNew = actionNew;
onGet = actionOnGet;
onRelease = actionOnRelease;
Name = name;
}
public void WarmUp(int count)
{
for (var i = 0; i < count; i++)
{
var element = onNew();
CountAll++;
stack.Push(element);
}
}
public T Get()
{
#if OBJECTPOOL_DEBUG
var created = false;
#endif
T element;
if (stack.Count == 0)
{
#if OBJECTPOOL_DEBUG
created = true;
logWarning("Created an object.");
#endif
element = onNew();
CountAll++;
}
else
{
element = stack.Pop();
}
if (onGet != null) onGet(element);
#if OBJECTPOOL_DEBUG
log(string.Format("Getting object from pool. New: {0}, count: {1}, left: {2}", created, CountAll, stack.Count));
#endif
return element;
}
public void Release(T element)
{
#if OBJECTPOOL_DEBUG
if (stack.Count > 0 && ReferenceEquals(stack.Peek(), element))
logError("Internal error. Trying to destroy object that is already released to pool.");
#endif
if (onRelease != null) onRelease(element);
stack.Push(element);
#if OBJECTPOOL_DEBUG
log(string.Format("Returned object to pool. Left: {0}", stack.Count));
#endif
}
public void Release(object element)
{
var obj = (T) element;
if (obj == null) return;
Release(obj);
}
#if OBJECTPOOL_DEBUG
private void log(string message)
{
if (string.IsNullOrEmpty(Name)) return;
UnityEngine.Debug.LogFormat("[{0}] ObjectPool ({1}): {2}", DateTime.Now.ToString("hh:mm:ss.fff"), Name, message);
}
private void logWarning(string message)
{
if (string.IsNullOrEmpty(Name)) return;
UnityEngine.Debug.LogWarningFormat("[{0}] ObjectPool ({1}): {2}", DateTime.Now.ToString("hh:mm:ss.fff"), Name, message);
}
private void logError(string message)
{
if (string.IsNullOrEmpty(Name)) return;
UnityEngine.Debug.LogErrorFormat("[{0}] ObjectPool ({1}): {2}", DateTime.Now.ToString("hh:mm:ss.fff"), Name, message);
}
#endif
}
}