Files
2026-05-26 16:15:54 +08:00

227 lines
5.6 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
namespace asap.core.common
{
public interface IObjectPool
{
// string PoolId { get; }
Type ObjectType { get; }
int PoolObjectNum { get; }
object SpawnObject();
bool DespawnObject(object obj, float delay = 0f);
void Initialize();
void Release();
}
// public interface IObjectPool<T> : IObjectPool where T : class
// {
// new T SpawnObject();
// void DespawnObject(T obj);
// }
public interface IPoolableObject
{
void OnSpawn();
void OnDespawn();
void OnPoolCreate(IObjectPool objectPool);
//void Destroy();
void OnPoolDestroy();
void ReturnPool();
}
public abstract class AObjectPool : IObjectPool
{
protected Queue<object> objectQuene = new Queue<object>();
protected Type objType;
protected int maxSize;
protected int preloadNum;
public Type ObjectType { get { return objType; } }
public int PoolObjectNum { get { return (null == objectQuene) ? 0 : objectQuene.Count; } }
protected string poolId;
public string PoolId => poolId;
public AObjectPool(Type objType, int preloadNum, int maxSize)
{
this.objType = objType;
this.maxSize = maxSize;
this.preloadNum = preloadNum;
//Initialize();
}
public virtual void Initialize()
{
if (objType == null)
{
throw (new ArgumentNullException("objType"));
}
if (preloadNum > 0)
{
generateObjects(preloadNum);
}
}
public virtual void Release()
{
foreach (var obj in objectQuene)
{
destroyObject(obj);
}
objectQuene.Clear();
objectQuene = null;
}
protected void generateObjects(int num)
{
object obj;
for (int i = 0; i < num; i++)
{
obj = newObject();
addObject(obj);
}
}
protected abstract object newObject();
protected abstract void destroyObject(object obj);
public virtual object SpawnObject()
{
object obj = getObject();
onSpawnObject(obj);
return obj;
}
public virtual bool DespawnObject(object obj, float delay = 0f)
{
addObject(obj);
onDespawnObject(obj);
return true;
}
protected virtual void onCreateObject(object obj)
{
if (obj is IPoolableObject)
{
var poolableObj = obj as IPoolableObject;
poolableObj.OnPoolCreate(this);
}
}
protected virtual void onSpawnObject(object obj)
{
if (obj is IPoolableObject)
{
var poolableObj = obj as IPoolableObject;
poolableObj.OnSpawn();
}
}
protected virtual void onDespawnObject(object obj)
{
if (obj is IList list)
{
list.Clear();
}
else if (obj is IDictionary dict)
{
dict.Clear();
}
else if (obj is ICollection collection)
{
var type = obj.GetType();
var methodInfo = type.GetMethod("Clear");
if (methodInfo != null)
{
// Debug.Log($"onDespawnObject: {collection.Count}, {methodInfo}");
methodInfo.Invoke(obj, null);
// Debug.Log($"onDespawnObject: {collection.Count}");
}
}
else if (obj is IPoolableObject poolableObj)
{
poolableObj.OnDespawn();
}
}
protected virtual void onDestroyObject(object obj)
{
if (obj is IPoolableObject)
{
var poolableObj = obj as IPoolableObject;
poolableObj.OnPoolDestroy();
}
if (obj is IDisposable)
{
(obj as IDisposable).Dispose();
}
}
protected virtual object getObject()
{
object obj;
if (objectQuene.Count > 0)
{
obj = objectQuene.Dequeue();
// onSpawnObject(obj);
}
else
{
obj = newObject();
}
return obj;
}
protected virtual void addObject(object obj)
{
if(!objType.IsAssignableFrom(obj.GetType()))
return;
#if UNITY_EDITOR
if (objectQuene.Contains(obj))
{
UnityEngine.Debug.LogError($"Return obj {obj.GetType().FullName} is already in pool");
}
#endif
objectQuene.Enqueue(obj);
// onDespawnObject(obj);
}
}
public class ObjectPool : AObjectPool
{
public ObjectPool(Type objType, int preloadNum, int maxSize) : base(objType, preloadNum, maxSize)
{
}
protected override object newObject()
{
object obj = Activator.CreateInstance(objType);
onCreateObject(obj);
return obj;
}
protected override void destroyObject(object obj)
{
onDestroyObject(obj);
}
}
}