using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using YooAsset; namespace UniFramework.Pooling { internal class GameObjectPool { private readonly Transform _poolRoot; private readonly Queue _cacheOperations; private readonly bool _dontDestroy; private readonly int _initCapacity; private readonly int _maxCapacity; private readonly float _destroyTime; private float _lastRestoreRealTime = -1f; /// /// 资源句柄 /// public AssetOperationHandle AssetHandle { private set; get; } /// /// 资源定位地址 /// public string Location { private set; get; } /// /// 内部缓存总数 /// public int CacheCount { get { return _cacheOperations.Count; } } /// /// 外部使用总数 /// public int SpawnCount { private set; get; } = 0; /// /// 是否常驻不销毁 /// public bool DontDestroy { get { return _dontDestroy; } } public GameObjectPool(GameObject poolRoot, string location, bool dontDestroy, int initCapacity, int maxCapacity, float destroyTime) { _poolRoot = poolRoot.transform; Location = location; _dontDestroy = dontDestroy; _initCapacity = initCapacity; _maxCapacity = maxCapacity; _destroyTime = destroyTime; // 创建缓存池 _cacheOperations = new Queue(initCapacity); } /// /// 创建对象池 /// public void CreatePool(ResourcePackage package) { // 加载游戏对象 AssetHandle = package.LoadAssetAsync(Location); // 创建初始对象 for (int i = 0; i < _initCapacity; i++) { var operation = AssetHandle.InstantiateAsync(_poolRoot); _cacheOperations.Enqueue(operation); } } /// /// 销毁游戏对象池 /// public void DestroyPool() { // 卸载资源对象 AssetHandle.Release(); AssetHandle = null; // 销毁游戏对象 foreach (var operation in _cacheOperations) { if (operation.Result != null) GameObject.Destroy(operation.Result); } _cacheOperations.Clear(); SpawnCount = 0; } /// /// 查询静默时间内是否可以销毁 /// public bool CanAutoDestroy() { if (_dontDestroy) return false; if (_destroyTime < 0) return false; if (_lastRestoreRealTime > 0 && SpawnCount <= 0) return (Time.realtimeSinceStartup - _lastRestoreRealTime) > _destroyTime; else return false; } /// /// 游戏对象池是否已经销毁 /// public bool IsDestroyed() { return AssetHandle == null; } /// /// 回收 /// public void Restore(InstantiateOperation operation) { if (IsDestroyed()) { DestroyInstantiateOperation(operation); return; } SpawnCount--; if (SpawnCount <= 0) _lastRestoreRealTime = Time.realtimeSinceStartup; // 如果外部逻辑销毁了游戏对象 if (operation.Status == EOperationStatus.Succeed) { if (operation.Result == null) return; } // 如果缓存池还未满员 if (_cacheOperations.Count < _maxCapacity) { SetRestoreGameObject(operation.Result); _cacheOperations.Enqueue(operation); } else { DestroyInstantiateOperation(operation); } } /// /// 丢弃 /// public void Discard(InstantiateOperation operation) { if (IsDestroyed()) { DestroyInstantiateOperation(operation); return; } SpawnCount--; if (SpawnCount <= 0) _lastRestoreRealTime = Time.realtimeSinceStartup; DestroyInstantiateOperation(operation); } /// /// 获取一个游戏对象 /// public SpawnHandle Spawn(Transform parent, Vector3 position, Quaternion rotation, bool forceClone, params System.Object[] userDatas) { InstantiateOperation operation; if (forceClone == false && _cacheOperations.Count > 0) operation = _cacheOperations.Dequeue(); else operation = AssetHandle.InstantiateAsync(); SpawnCount++; SpawnHandle handle = new SpawnHandle(this, operation, parent, position, rotation, userDatas); YooAssets.StartOperation(handle); return handle; } private void DestroyInstantiateOperation(InstantiateOperation operation) { // 取消异步操作 operation.Cancel(); // 销毁游戏对象 if (operation.Result != null) { GameObject.Destroy(operation.Result); } } private void SetRestoreGameObject(GameObject gameObj) { if (gameObj != null) { gameObj.SetActive(false); gameObj.transform.SetParent(_poolRoot); gameObj.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity); } } } }