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 : 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 objectQuene = new Queue(); 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); } } }