using System; using System.Collections.Generic; using System.Reflection; using CombatLibrary.CombatLibrary.CombatCore.Utility; using Fort23.Core; #if !COMBAT_SERVER using Core.Pool.GPool; using UnityEngine; using Object = UnityEngine.Object; #endif namespace Fort23.UTool { public class GameObjectQueue { public string poolName { get { return _poolName; } } private bool _isDis; private string _poolName; private string _prefabName; private int maxCount = -1; #if !COMBAT_SERVER /// /// 池子的父亲 /// private AssetHandle _PoolObjectFather; public bool isOne; private readonly List _usePool = new List(); private readonly List _queue = new List(); private readonly List _destroyPool = new List(); private readonly List _delayHide = new List(); public int initCopunt; private bool _isSetMaxCount; public void Init(string poolName, string prefabName) { _poolName = poolName; _prefabName = prefabName; } public async CTask Enqueue(IGObjectPoolInterface poolInterface, bool isNotAwaitDelay = false) { if (poolInterface == null || poolInterface.own == null) { return; } if (_queue.Contains(poolInterface)) { return; } if (_delayHide.Contains(poolInterface)) { return; } _delayHide.Add(poolInterface); if (!isNotAwaitDelay) { await poolInterface.DelayHide(); } if (_isDis) { return; } _delayHide.Remove(poolInterface); poolInterface.isUse = false; _usePool.Remove(poolInterface); if (poolInterface.own != null) { poolInterface.DormancyObj(); this._queue.Add(poolInterface); } } public void AddDestroy(IGObjectPoolInterface poolInterface, bool immediately = false) { if (poolInterface.own == null) { return; } if (!_destroyPool.Contains(poolInterface)) { if (immediately) { poolInterface.DestroyTimer = null; GameObjectDestroyPool.Instance.DestroyObject(poolInterface.own); } else { TimerComponent.Instance.Remove(poolInterface.DestroyTimer); poolInterface.DestroyTimer = TimerComponent.Instance.AddTimer(6000, delegate { _destroyPool.Remove(poolInterface); poolInterface.DestroyTimer = null; GameObjectDestroyPool.Instance.DestroyObject(poolInterface.own); }); _destroyPool.Add(poolInterface); } } } public void DormancyPool() { List alliG = new List(); IGObjectPoolInterface[] all = _usePool.ToArray(); if (all != null) { alliG.AddRange(all); } for (int i = 0; i < alliG.Count; i++) { IGObjectPoolInterface poolInterface = alliG[i]; Enqueue(poolInterface); } // _usePool.Clear(); } public async CTask Preset(Clock clock, bool isUseSynchronous) where T : IGObjectPoolInterface { DormancyPool(); for (int i = 0; i < Count; i++) { IGObjectPoolInterface poolInterface = _queue[i]; DisposePoolEntity(poolInterface); poolInterface.Preset(); } for (int i = 0; i < _usePool.Count; i++) { IGObjectPoolInterface poolInterface = _usePool[i]; DisposePoolEntity(poolInterface); poolInterface.Preset(); } for (int i = 0; i < _destroyPool.Count; i++) { DisposePoolEntity(_destroyPool[i]); } _destroyPool.Clear(); T OBJ = await Dequeue(true, clock, isUseSynchronous); Enqueue(OBJ, true); } private async CTask LoadAsset(Clock clock, bool isUseSynchronous) { if (AssetBundleLoadManager.Instance != null) { CTask cTask = AssetBundleLoadManager.Instance.LoadAssetAsyncTask(_prefabName, clock: clock, isUseSynchronous: isUseSynchronous); AssetHandle assetHandle = await cTask; return assetHandle; } return null; } public T DequeuForSynchronize(GameObject gameObject, bool isActive) where T : IGObjectPoolInterface { if (_queue.Count <= 0) { return CreateInstance(isActive, gameObject); } if (_destroyPool.Count > 0) { for (int i = 0; i < _destroyPool.Count; i++) { DisposePoolEntity(_destroyPool[i]); } _destroyPool.Clear(); } for (int i = 0; i < _queue.Count; i++) { if (_queue[i].own == null) { _queue.RemoveAt(i); i--; continue; } else { IGObjectPoolInterface objectPoolInterface = this._queue[0]; _queue.RemoveAt(0); UseObject(objectPoolInterface, isActive); return (T)objectPoolInterface; } } return CreateInstance(isActive, gameObject); } public async CTask Dequeue(bool isActive, Clock clock, bool isUseSynchronous) where T : IGObjectPoolInterface { if (maxCount > 0 && _usePool.Count > maxCount) { return default; } for (int i = 0; i < _queue.Count; i++) { if (_queue[i].own == null) { _queue.RemoveAt(i); i--; continue; } else { IGObjectPoolInterface objectPoolInterface = this._queue[i]; if (objectPoolInterface.own == null) { continue; } _queue.RemoveAt(i); UseObject(objectPoolInterface, isActive); return (T)objectPoolInterface; } } bool isUsePoolObject = false; if ((_PoolObjectFather == null || _PoolObjectFather.IsNull()) && !string.IsNullOrEmpty(_prefabName)) { using (await CoroutineLockComponent.Instance.Wait(poolName, 20000)) { if (_PoolObjectFather == null) { _PoolObjectFather = await LoadAsset(clock, isUseSynchronous); isUsePoolObject = true; } } } // if (clock != null && clock.isBreak) // { // if (isUsePoolObject) // { // Debug.LogError("已打断,但是有初始化数据" + _PoolObjectFather); // } // // return default; // } if (_queue.Count <= 0) { AssetHandle assetHandle = _PoolObjectFather; if (!isUsePoolObject) { assetHandle = await _PoolObjectFather.InstantiateSync(isUseSynchronous); } // AssetHandle assetHandle = isUsePoolObject ? _PoolObjectFather : _PoolObjectFather; return CreateInstance(isActive, assetHandle); } if (_destroyPool.Count > 0) { for (int i = 0; i < _destroyPool.Count; i++) { DisposePoolEntity(_destroyPool[i]); } _destroyPool.Clear(); } AssetHandle assetHandle2 = _PoolObjectFather; if (!isUsePoolObject) { assetHandle2 = await _PoolObjectFather.InstantiateSync(isUseSynchronous); } assetHandle2 = await assetHandle2.InstantiateSync(isUseSynchronous); return CreateInstance(isActive, assetHandle2); } private T CreateInstance(bool isActive, AssetHandle assetHandle) where T : IGObjectPoolInterface { if (assetHandle == null) { return default; } T poolInerface = Activator.CreateInstance(); GameObject go = assetHandle.AssetObject(); GameObjectEntity objectEntity = go.GetComponent(); if (objectEntity == null) { objectEntity = go.AddComponent(); } objectEntity.IgObjectPoolInterface = poolInerface; objectEntity.OnDestroyCallBack = DestroyEntity; poolInerface.SetGameObject(go); poolInerface.poolObjName = _poolName; poolInerface.AssetHandle = assetHandle; UseObject(poolInerface, isActive); initCopunt++; return poolInerface; } private T CreateInstance(bool isActive, GameObject gameObject) where T : IGObjectPoolInterface { if (gameObject == null) { return default; } T poolInerface = Activator.CreateInstance(); GameObject go = GameObject.Instantiate(gameObject); GameObjectEntity objectEntity = go.GetComponent(); if (objectEntity == null) { objectEntity = go.AddComponent(); } objectEntity.IgObjectPoolInterface = poolInerface; objectEntity.OnDestroyCallBack = DestroyEntity; poolInerface.SetGameObject(go); poolInerface.poolObjName = _poolName; poolInerface.AssetHandle = null; UseObject(poolInerface, isActive); initCopunt++; return poolInerface; } private void DestroyEntity(IGObjectPoolInterface poolInterface) { if (poolInterface != null) { _queue.Remove(poolInterface); _usePool.Remove(poolInterface); } else { return; } DisposePoolEntity(poolInterface); // poolInterface.DormancyObj(); poolInterface.DestroyObj(); poolInterface.AssetHandle?.Release(); if (poolInterface.AssetHandle == _PoolObjectFather) { _PoolObjectFather = null; if (_queue.Count > 0) { _PoolObjectFather = _queue[0].AssetHandle; } } if (_queue.Count <= 0 && _usePool.Count <= 0) //池子已经被释放完,把父物体也释掉 { GObjectPool.Instance.DestroyPool(poolName); } } private void UseObject(IGObjectPoolInterface objectPoolInterface, bool isActive) { if (!_isSetMaxCount) { _isSetMaxCount = true; GObjectPoolMaxConfig gObjectPoolMaxConfig = objectPoolInterface.own.GetComponent(); if (gObjectPoolMaxConfig != null) { maxCount = gObjectPoolMaxConfig.maxCount; } } _usePool.Add(objectPoolInterface); DisposePoolEntity(objectPoolInterface); // TimerComponent.Instance.Remove(objectPoolInterface.DestroyTimer); // GameObjectDestroyPool.Instance.RomoveDestroyObject(objectPoolInterface.own); objectPoolInterface.isUse = true; objectPoolInterface.ResetData(); if (isActive) { objectPoolInterface.ActiveObj(); } } public int Count => this._queue.Count; public void Dispose() { _isDis = true; for (int i = 0; i < Count; i++) { IGObjectPoolInterface poolInterface = _queue[i]; DisposePoolEntity(poolInterface); if (poolInterface.own != null) { GameObjectEntity gameObjectEntity = poolInterface.own.GetComponent(); if (gameObjectEntity != null) { gameObjectEntity.IgObjectPoolInterface = null; gameObjectEntity.OnDestroyCallBack = null; } poolInterface.own.SetActive(false); poolInterface.DormancyObj(); poolInterface.DestroyObj(); poolInterface.AssetHandle?.Release(); GameObjectDestroyPool.Instance.DestroyObject(poolInterface.own); } } for (int i = 0; i < _delayHide.Count; i++) { IGObjectPoolInterface poolInterface = _delayHide[i]; DisposePoolEntity(poolInterface); if (poolInterface.own != null) { GameObjectEntity gameObjectEntity = poolInterface.own.GetComponent(); if (gameObjectEntity != null) { gameObjectEntity.IgObjectPoolInterface = null; gameObjectEntity.OnDestroyCallBack = null; } poolInterface.own.SetActive(false); poolInterface.DormancyObj(); poolInterface.DestroyObj(); poolInterface.AssetHandle?.Release(); GameObjectDestroyPool.Instance.DestroyObject(poolInterface.own); } } for (int i = 0; i < _usePool.Count; i++) { IGObjectPoolInterface poolInterface = _usePool[i]; DisposePoolEntity(poolInterface); if (poolInterface.own != null) { GameObjectEntity gameObjectEntity = poolInterface.own.GetComponent(); if (gameObjectEntity != null) { gameObjectEntity.IgObjectPoolInterface = null; gameObjectEntity.OnDestroyCallBack = null; } poolInterface.own.SetActive(false); poolInterface.DormancyObj(); poolInterface.DestroyObj(); GameObjectDestroyPool.Instance.DestroyObject(poolInterface.own); } } _PoolObjectFather = null; _delayHide.Clear(); _queue.Clear(); _destroyPool.Clear(); _usePool.Clear(); } private void DisposePoolEntity(IGObjectPoolInterface poolInterface) { _destroyPool.Remove(poolInterface); TimerComponent.Instance.Remove(poolInterface.DestroyTimer); GameObjectDestroyPool.Instance.RomoveDestroyObject(poolInterface.own); poolInterface.DestroyTimer = null; } #endif } public class GObjectPool { private static GObjectPool _instance; public static GObjectPool Instance { get { if (_instance == null) { _instance = new GObjectPool(); } return _instance; } } /// /// key是gameObject.name.GetHashCode(); /// private readonly Dictionary _dictionary = new Dictionary(); /// /// 在ab包里面的东西,都可以通过这个方法获取 /// /// /// /// /// /// /// /// public async CTask FetchAsync(string prefabName, System.Action callBack = null, Clock clock = null, bool Prestore = false, string poolName = null, bool isUseSynchronous = false) where T : IGObjectPoolInterface { if (!prefabName.Contains(".prefab")) { prefabName += ".prefab"; } T poolInerface = await FetchObjectAsync(prefabName, clock, Prestore, poolName, isUseSynchronous: isUseSynchronous); if (Prestore) { callBack?.Invoke(default); return default; } if (poolInerface == null) { callBack?.Invoke(default); return default; } if (clock != null && clock.isBreak) { Recycle(poolInerface); callBack?.Invoke(default); return default; } callBack?.Invoke(poolInerface); return poolInerface; } private string GetPoolName(string name) { return name + typeof(T); } #if !COMBAT_SERVER public T FetchAsyncForGameObject(GameObject gameObject, string poolName ) where T : IGObjectPoolInterface { T poolInerface = Fetch(poolName, gameObject); if (poolInerface == null) { return default; } return poolInerface; } public T Fetch(string poolName, GameObject gameObject, bool isActive = true) where T : IGObjectPoolInterface { string newPoolName = GetPoolName(poolName); GameObjectQueue gameObjectQueue = null; if (!this._dictionary.TryGetValue(newPoolName, out gameObjectQueue)) { gameObjectQueue = EnterPool(newPoolName, null); } return gameObjectQueue.DequeuForSynchronize(gameObject, isActive); } #endif private async CTask FetchObjectAsync(string prefabName, Clock clock, bool Prestore, string poolName, bool isActive = true, bool isUseSynchronous = false) where T : IGObjectPoolInterface { #if !COMBAT_SERVER try { GameObjectQueue gameObjectQueue = null; poolName = poolName == null ? prefabName : poolName; poolName = GetPoolName(poolName); // 加一个协程锁,让同时加载资源的时候lock住 // using (await CoroutineLockComponent.Instance.Wait(poolName,20000)) { if (clock != null && clock.isBreak) { return default; } if (this._dictionary.TryGetValue(poolName, out gameObjectQueue)) { if (Prestore) { await gameObjectQueue.Preset(clock, isUseSynchronous); return default; } return await gameObjectQueue.Dequeue(isActive, clock, isUseSynchronous); } if (!this._dictionary.TryGetValue(poolName, out gameObjectQueue)) { gameObjectQueue = EnterPool(poolName, prefabName); } if (gameObjectQueue == null) { return default; } if (Prestore) { await gameObjectQueue.Preset(clock, isUseSynchronous); return default; } return await gameObjectQueue.Dequeue(isActive, clock, isUseSynchronous); } } catch (Exception e) { LogTool.Exception(e); return default; } #else return default; #endif } #if !COMBAT_SERVER private Transform _parent; private GameObjectQueue EnterPool(string poolName, string prefabName) where T : IGObjectPoolInterface { if (_parent == null) { _parent = new GameObject().transform; _parent.gameObject.name = "Pool"; } GameObjectQueue queue = new GameObjectQueue(); queue.Init(poolName, prefabName); _dictionary.Add(poolName, queue); return queue; } #endif public void Recycle(IGObjectPoolInterface poolInterface) { if (poolInterface == null) { return; } #if !COMBAT_SERVER GameObjectQueue queue; if (!this._dictionary.TryGetValue(poolInterface.poolObjName, out queue)) { LogTool.Error("不再池子之中 " + poolInterface.poolObjName); return; } queue.Enqueue(poolInterface); #endif } public async CTask Recycle(IGObjectPoolInterface poolInterface, bool isNotAwaitDelay) { if (poolInterface == null) { return; } #if !COMBAT_SERVER GameObjectQueue queue; if (!this._dictionary.TryGetValue(poolInterface.poolObjName, out queue)) { LogTool.Error("不再池子之中 " + poolInterface.poolObjName); return; } await queue.Enqueue(poolInterface, isNotAwaitDelay); #endif } public void RecycleForDestroy(IGObjectPoolInterface poolInterface, bool immediately = false) { if (poolInterface == null) { return; } #if !COMBAT_SERVER GameObjectQueue queue; if (!this._dictionary.TryGetValue(poolInterface.poolObjName, out queue)) { LogTool.Error("不再池子之中 " + poolInterface.poolObjName); return; } queue.Enqueue(poolInterface); queue.AddDestroy(poolInterface, immediately); #endif } public void DestroyPool(string poolObjName) { #if !COMBAT_SERVER GameObjectQueue queue; if (!this._dictionary.TryGetValue(poolObjName, out queue)) { // LogTool.Warning("没有这个池子 " + poolObjName); return; } _dictionary.Remove(poolObjName); queue.Dispose(); #endif } /// /// 休眠一个池子 /// /// public void DormancyPool(string poolName) { #if !COMBAT_SERVER GameObjectQueue queue; if (!this._dictionary.TryGetValue(poolName, out queue)) { string poolObjName = GetPoolName(poolName); if (!this._dictionary.TryGetValue(poolObjName, out queue)) { // LogTool.Warning("没有这个池子 " + poolObjName); return; } } queue?.DormancyPool(); #endif } /// /// 清除所有池子 /// public void Clear() { Dispose(); } /// /// 清除所有池子 /// public void Dispose() { #if !COMBAT_SERVER foreach (KeyValuePair kv in this._dictionary) { kv.Value.Dispose(); } this._dictionary.Clear(); _instance = null; #endif } } }