using Convention.Experimental.PublicType; using System; using System.Linq; using System.Collections.Generic; using UnityEngine; namespace Convention.Experimental.Modules { public class GameObjectPoolManager : GameModule { /// /// 继承该接口的Component将在回收到对象池时调用 /// 中禁止调用 /// public interface IPoolPawn { void Release(); } private readonly Dictionary> GameObjectPools = new(); private readonly Dictionary LeaveGameObjectPoolObjects = new(); private bool GameObjectPoolStatus = true; /// /// 检查是否存在指定的游戏对象池 /// /// 用做键的预制体 /// public bool Contains(GameObject prefab) { return GameObjectPools.ContainsKey(prefab); } /// /// 确保不会嵌套调用 /// /// private void EnsureSafeStatus() { if (GameObjectPoolStatus == false) { throw new GameException("GameObjectPool is busy now."); } } /// /// 生成游戏对象 /// /// /// public GameObject Spawn(GameObject prefab) { EnsureSafeStatus(); lock (GameObjectPools) { if (!GameObjectPools.ContainsKey(prefab)) { GameObjectPools[prefab] = new(); } var pool = GameObjectPools[prefab]; GameObject instance; if (pool.Count > 0) { instance = pool.Pop(); instance.SetActive(true); instance.transform.SetParent(null); } else { instance = GameObject.Instantiate(prefab); } lock (LeaveGameObjectPoolObjects) { LeaveGameObjectPoolObjects[instance] = prefab; } return instance; } } /// /// 回收游戏对象 /// /// /// public void Unspawn(GameObject instance) { EnsureSafeStatus(); lock (LeaveGameObjectPoolObjects) { if (LeaveGameObjectPoolObjects.TryGetValue(instance, out var prefab)) { var releaser = instance.GetComponents(); GameObjectPoolStatus = false; foreach (var r in releaser) { r.Release(); } GameObjectPoolStatus = true; instance.SetActive(false); instance.transform.SetParent(ConventionUtility.Singleton.transform); lock (GameObjectPools) { GameObjectPools[prefab].Push(instance); LeaveGameObjectPoolObjects.Remove(instance); } } else { throw new PublicType.GameException("This object does not belong to any pool."); } } } public void Clear(GameObject prefab) { EnsureSafeStatus(); lock (GameObjectPools) { lock (LeaveGameObjectPoolObjects) { // 销毁池中对象 if (GameObjectPools.TryGetValue(prefab, out var pool)) { while (pool.Count > 0) { var instance = pool.Pop(); GameObject.Destroy(instance); } } else { throw new PublicType.GameException("This pool does not exist."); } // 销毁未回收对象 var unbackInstances = from item in LeaveGameObjectPoolObjects where item.Value == prefab select item.Key; foreach (var instance in unbackInstances) { LeaveGameObjectPoolObjects.Remove(instance); } foreach (var instance in unbackInstances) { GameObject.Destroy(instance); } } } } } public class ObjectPoolManager { /// /// 继承该接口的Component将在回收到对象池时调用 /// 中禁止调用 /// public interface IPoolPawn { void Release(); } private readonly Dictionary ObjectPools = new(); private readonly Dictionary LeaveObjectPoolObjects = new(); private bool GameObjectPoolStatus = true; private void EnsureSafeStatus() { if (GameObjectPoolStatus == false) { throw new GameException("ObjectPool is busy now."); } } public bool Contains(Type type) { return ObjectPools.ContainsKey(type); } public bool Contains() where T : class, new() { return ObjectPools.ContainsKey(typeof(T)); } /// /// 插入自行创建的对象到对象池 /// /// 期望类型 /// 实例 /// /// public object Insert(Type type, object value) { if(LeaveObjectPoolObjects.ContainsKey(value)) { throw new PublicType.GameException("This object is already registered in pool"); } if (!ObjectPools.ContainsKey(type)) { ObjectPools[type] = Utility.CreateStack(type); } var pool = ObjectPools[type]; var methodInfo = pool.GetType().GetMethod("Push"); methodInfo.Invoke(pool, new object[] { value }); return value; } /// /// 自行创建对象并插入对象池 /// /// 期望类型 /// 实例 /// /// public T Insert(T value) where T : class { if(LeaveObjectPoolObjects.ContainsKey(value)) { throw new PublicType.GameException("This object is already registered in pool"); } var type = typeof(T); if (!ObjectPools.ContainsKey(type)) { ObjectPools[type] = new Stack(); } var pool = (Stack)ObjectPools[type]; pool.Push(value); return value; } /// /// 捕获一般对象并返回实例 /// /// 期望类型 /// public object Summon(Type type) { if (!ObjectPools.ContainsKey(type)) { ObjectPools[type] = Utility.CreateStack(type); } var pool = ObjectPools[type]; var methodInfo = pool.GetType().GetMethod("Pop"); object instance; var countProperty = pool.GetType().GetProperty("Count"); var count = (int)countProperty.GetValue(pool); if (count > 0) { instance = methodInfo.Invoke(pool, null); } else { instance = Activator.CreateInstance(type); } LeaveObjectPoolObjects[instance] = type; return instance; } /// /// 捕获一般对象并返回实例 /// /// 期望类型 /// public T Summon() where T : class, new() { var type = typeof(T); if (!ObjectPools.ContainsKey(type)) { ObjectPools[type] = new Stack(); } var pool = (Stack)ObjectPools[type]; T instance; if (pool.Count > 0) { instance = pool.Pop(); } else { instance = new T(); } LeaveObjectPoolObjects[instance] = type; return instance; } /// /// 回收对象 /// /// 实例 /// public void Reclaim(object instance) { if (LeaveObjectPoolObjects.TryGetValue(instance, out var objType)) { var pool = ObjectPools[objType]; var methodInfo = pool.GetType().GetMethod("Push"); if(instance is IPoolPawn pawn) { pawn.Release(); } methodInfo.Invoke(pool, new object[] { instance }); LeaveObjectPoolObjects.Remove(instance); } else { throw new GameException("This object does not belong to any pool."); } } public void Clear(Type type) { if (ObjectPools.TryGetValue(type, out var pool)) { var clearMethod = pool.GetType().GetMethod("Clear"); clearMethod.Invoke(pool, null); } else { throw new PublicType.GameException("This pool does not exist."); } } public void Clear() where T : class, new() { var type = typeof(T); if (ObjectPools.TryGetValue(type, out var pool)) { var clearMethod = pool.GetType().GetMethod("Clear"); clearMethod.Invoke(pool, null); } else { throw new PublicType.GameException("This pool does not exist."); } } } }