mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
Demo
Demo
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
using YooAsset;
|
||||
|
||||
namespace UniFramework.Pooling
|
||||
{
|
||||
public class CreatePoolOperation : GameAsyncOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
Waiting,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly AssetOperationHandle _handle;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal CreatePoolOperation(AssetOperationHandle handle)
|
||||
{
|
||||
_handle = handle;
|
||||
}
|
||||
protected override void OnStart()
|
||||
{
|
||||
_steps = ESteps.Waiting;
|
||||
}
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.Waiting)
|
||||
{
|
||||
if (_handle.IsValid == false)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"{nameof(AssetOperationHandle)} is invalid.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (_handle.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_handle.AssetObject == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"{nameof(AssetOperationHandle.AssetObject)} is null.";
|
||||
return;
|
||||
}
|
||||
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 等待异步实例化结束
|
||||
/// </summary>
|
||||
public void WaitForAsyncComplete()
|
||||
{
|
||||
if (_handle != null)
|
||||
{
|
||||
if (_steps == ESteps.Done)
|
||||
return;
|
||||
_handle.WaitForAsyncComplete();
|
||||
OnUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5687620a17f42e4085a0e2243be7561
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,215 @@
|
||||
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<InstantiateOperation> _cacheOperations;
|
||||
private readonly bool _dontDestroy;
|
||||
private readonly int _initCapacity;
|
||||
private readonly int _maxCapacity;
|
||||
private readonly float _destroyTime;
|
||||
private float _lastRestoreRealTime = -1f;
|
||||
|
||||
/// <summary>
|
||||
/// 资源句柄
|
||||
/// </summary>
|
||||
public AssetOperationHandle AssetHandle { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源定位地址
|
||||
/// </summary>
|
||||
public string Location { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 内部缓存总数
|
||||
/// </summary>
|
||||
public int CacheCount
|
||||
{
|
||||
get { return _cacheOperations.Count; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 外部使用总数
|
||||
/// </summary>
|
||||
public int SpawnCount { private set; get; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 是否常驻不销毁
|
||||
/// </summary>
|
||||
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<InstantiateOperation>(initCapacity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建对象池
|
||||
/// </summary>
|
||||
public void CreatePool(ResourcePackage package)
|
||||
{
|
||||
// 加载游戏对象
|
||||
AssetHandle = package.LoadAssetAsync<GameObject>(Location);
|
||||
|
||||
// 创建初始对象
|
||||
for (int i = 0; i < _initCapacity; i++)
|
||||
{
|
||||
var operation = AssetHandle.InstantiateAsync(_poolRoot);
|
||||
_cacheOperations.Enqueue(operation);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁游戏对象池
|
||||
/// </summary>
|
||||
public void DestroyPool()
|
||||
{
|
||||
// 卸载资源对象
|
||||
AssetHandle.Release();
|
||||
AssetHandle = null;
|
||||
|
||||
// 销毁游戏对象
|
||||
foreach (var operation in _cacheOperations)
|
||||
{
|
||||
if (operation.Result != null)
|
||||
GameObject.Destroy(operation.Result);
|
||||
}
|
||||
_cacheOperations.Clear();
|
||||
|
||||
SpawnCount = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询静默时间内是否可以销毁
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 游戏对象池是否已经销毁
|
||||
/// </summary>
|
||||
public bool IsDestroyed()
|
||||
{
|
||||
return AssetHandle == null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 丢弃
|
||||
/// </summary>
|
||||
public void Discard(InstantiateOperation operation)
|
||||
{
|
||||
if (IsDestroyed())
|
||||
{
|
||||
DestroyInstantiateOperation(operation);
|
||||
return;
|
||||
}
|
||||
|
||||
SpawnCount--;
|
||||
if (SpawnCount <= 0)
|
||||
_lastRestoreRealTime = Time.realtimeSinceStartup;
|
||||
|
||||
DestroyInstantiateOperation(operation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个游戏对象
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1dd976626eb4ca645b4ec80921f4e8fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,148 @@
|
||||
using UnityEngine;
|
||||
using YooAsset;
|
||||
|
||||
namespace UniFramework.Pooling
|
||||
{
|
||||
public sealed class SpawnHandle : GameAsyncOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
Waiting,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly GameObjectPool _pool;
|
||||
private InstantiateOperation _operation;
|
||||
private readonly Transform _parent;
|
||||
private readonly Vector3 _position;
|
||||
private readonly Quaternion _rotation;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
/// <summary>
|
||||
/// 实例化的游戏对象
|
||||
/// </summary>
|
||||
public GameObject GameObj
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_operation == null)
|
||||
{
|
||||
UniLogger.Warning("The spawn handle is invalid !");
|
||||
return null;
|
||||
}
|
||||
|
||||
return _operation.Result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用户自定义数据集
|
||||
/// </summary>
|
||||
public System.Object[] UserDatas { private set; get; }
|
||||
|
||||
private SpawnHandle()
|
||||
{
|
||||
}
|
||||
internal SpawnHandle(GameObjectPool pool, InstantiateOperation operation, Transform parent, Vector3 position, Quaternion rotation, params System.Object[] userDatas)
|
||||
{
|
||||
_pool = pool;
|
||||
_operation = operation;
|
||||
_parent = parent;
|
||||
_position = position;
|
||||
_rotation = rotation;
|
||||
UserDatas = userDatas;
|
||||
}
|
||||
protected override void OnStart()
|
||||
{
|
||||
_steps = ESteps.Waiting;
|
||||
}
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.Waiting)
|
||||
{
|
||||
if (_operation.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_operation.Status != EOperationStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _operation.Error;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_operation.Result == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Clone game object is null.";
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置参数
|
||||
_operation.Result.transform.SetParent(_parent);
|
||||
_operation.Result.transform.SetPositionAndRotation(_position, _rotation);
|
||||
_operation.Result.SetActive(true);
|
||||
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收
|
||||
/// </summary>
|
||||
public void Restore()
|
||||
{
|
||||
if (_operation != null)
|
||||
{
|
||||
ClearCompletedCallback();
|
||||
CancelHandle();
|
||||
_pool.Restore(_operation);
|
||||
_operation = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 丢弃
|
||||
/// </summary>
|
||||
public void Discard()
|
||||
{
|
||||
if (_operation != null)
|
||||
{
|
||||
ClearCompletedCallback();
|
||||
CancelHandle();
|
||||
_pool.Discard(_operation);
|
||||
_operation = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 等待异步实例化结束
|
||||
/// </summary>
|
||||
public void WaitForAsyncComplete()
|
||||
{
|
||||
if (_operation != null)
|
||||
{
|
||||
if (_steps == ESteps.Done)
|
||||
return;
|
||||
_operation.WaitForAsyncComplete();
|
||||
OnUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
private void CancelHandle()
|
||||
{
|
||||
if (IsDone == false)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"User cancelled !";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6350d2984a149b349b9cec658d21b12a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
259
Assets/GameScripts/HotFix/GameLogic/Demo/Uni/Runtime/Spawner.cs
Normal file
259
Assets/GameScripts/HotFix/GameLogic/Demo/Uni/Runtime/Spawner.cs
Normal file
@@ -0,0 +1,259 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using YooAsset;
|
||||
|
||||
namespace UniFramework.Pooling
|
||||
{
|
||||
public class Spawner
|
||||
{
|
||||
private readonly List<GameObjectPool> _gameObjectPools = new List<GameObjectPool>(100);
|
||||
private readonly List<GameObjectPool> _removeList = new List<GameObjectPool>(100);
|
||||
private readonly GameObject _spawnerRoot;
|
||||
private readonly ResourcePackage _package;
|
||||
|
||||
public string PackageName
|
||||
{
|
||||
get
|
||||
{
|
||||
return _package.PackageName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Spawner()
|
||||
{
|
||||
}
|
||||
internal Spawner(GameObject poolingRoot, ResourcePackage package)
|
||||
{
|
||||
_spawnerRoot = new GameObject($"{package.PackageName}");
|
||||
_spawnerRoot.transform.SetParent(poolingRoot.transform);
|
||||
_package = package;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新游戏对象池系统
|
||||
/// </summary>
|
||||
internal void Update()
|
||||
{
|
||||
_removeList.Clear();
|
||||
foreach (var pool in _gameObjectPools)
|
||||
{
|
||||
if (pool.CanAutoDestroy())
|
||||
_removeList.Add(pool);
|
||||
}
|
||||
|
||||
foreach (var pool in _removeList)
|
||||
{
|
||||
_gameObjectPools.Remove(pool);
|
||||
pool.DestroyPool();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁游戏对象池系统
|
||||
/// </summary>
|
||||
internal void Destroy()
|
||||
{
|
||||
DestroyAll(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁所有对象池及其资源
|
||||
/// </summary>
|
||||
/// <param name="includeAll">销毁所有对象池,包括常驻对象池</param>
|
||||
public void DestroyAll(bool includeAll)
|
||||
{
|
||||
if (includeAll)
|
||||
{
|
||||
foreach (var pool in _gameObjectPools)
|
||||
{
|
||||
pool.DestroyPool();
|
||||
}
|
||||
_gameObjectPools.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
List<GameObjectPool> removeList = new List<GameObjectPool>();
|
||||
foreach (var pool in _gameObjectPools)
|
||||
{
|
||||
if (pool.DontDestroy == false)
|
||||
removeList.Add(pool);
|
||||
}
|
||||
foreach (var pool in removeList)
|
||||
{
|
||||
_gameObjectPools.Remove(pool);
|
||||
pool.DestroyPool();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 异步创建指定资源的游戏对象池
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址</param>
|
||||
/// <param name="dontDestroy">资源常驻不销毁</param>
|
||||
/// <param name="initCapacity">对象池的初始容量</param>
|
||||
/// <param name="maxCapacity">对象池的最大容量</param>
|
||||
/// <param name="destroyTime">静默销毁时间(注意:小于零代表不主动销毁)</param>
|
||||
public CreatePoolOperation CreateGameObjectPoolAsync(string location, bool dontDestroy = false, int initCapacity = 0, int maxCapacity = int.MaxValue, float destroyTime = -1f)
|
||||
{
|
||||
return CreateGameObjectPoolInternal(location, dontDestroy, initCapacity, maxCapacity, destroyTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步创建指定资源的游戏对象池
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址</param>
|
||||
/// <param name="dontDestroy">资源常驻不销毁</param>
|
||||
/// <param name="initCapacity">对象池的初始容量</param>
|
||||
/// <param name="maxCapacity">对象池的最大容量</param>
|
||||
/// <param name="destroyTime">静默销毁时间(注意:小于零代表不主动销毁)</param>
|
||||
public CreatePoolOperation CreateGameObjectPoolSync(string location, bool dontDestroy = false, int initCapacity = 0, int maxCapacity = int.MaxValue, float destroyTime = -1f)
|
||||
{
|
||||
var operation = CreateGameObjectPoolInternal(location, dontDestroy, initCapacity, maxCapacity, destroyTime);
|
||||
operation.WaitForAsyncComplete();
|
||||
return operation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建指定资源的游戏对象池
|
||||
/// </summary>
|
||||
private CreatePoolOperation CreateGameObjectPoolInternal(string location, bool dontDestroy = false, int initCapacity = 0, int maxCapacity = int.MaxValue, float destroyTime = -1f)
|
||||
{
|
||||
if (maxCapacity < initCapacity)
|
||||
throw new Exception("The max capacity value must be greater the init capacity value.");
|
||||
|
||||
GameObjectPool pool = TryGetGameObjectPool(location);
|
||||
if (pool != null)
|
||||
{
|
||||
UniLogger.Warning($"GameObject pool is already existed : {location}");
|
||||
var operation = new CreatePoolOperation(pool.AssetHandle);
|
||||
YooAssets.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
else
|
||||
{
|
||||
pool = new GameObjectPool(_spawnerRoot, location, dontDestroy, initCapacity, maxCapacity, destroyTime);
|
||||
pool.CreatePool(_package);
|
||||
_gameObjectPools.Add(pool);
|
||||
|
||||
var operation = new CreatePoolOperation(pool.AssetHandle);
|
||||
YooAssets.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 异步实例化一个游戏对象
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址</param>
|
||||
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象</param>
|
||||
/// <param name="userDatas">用户自定义数据</param>
|
||||
public SpawnHandle SpawnAsync(string location, bool forceClone = false, params System.Object[] userDatas)
|
||||
{
|
||||
return SpawnInternal(location, null, Vector3.zero, Quaternion.identity, forceClone, userDatas);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步实例化一个游戏对象
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址</param>
|
||||
/// <param name="parent">父物体</param>
|
||||
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象</param>
|
||||
/// <param name="userDatas">用户自定义数据</param>
|
||||
public SpawnHandle SpawnAsync(string location, Transform parent, bool forceClone = false, params System.Object[] userDatas)
|
||||
{
|
||||
return SpawnInternal(location, parent, Vector3.zero, Quaternion.identity, forceClone, userDatas);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步实例化一个游戏对象
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址</param>
|
||||
/// <param name="parent">父物体</param>
|
||||
/// <param name="position">世界坐标</param>
|
||||
/// <param name="rotation">世界角度</param>
|
||||
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象</param>
|
||||
/// <param name="userDatas">用户自定义数据</param>
|
||||
public SpawnHandle SpawnAsync(string location, Transform parent, Vector3 position, Quaternion rotation, bool forceClone = false, params System.Object[] userDatas)
|
||||
{
|
||||
return SpawnInternal(location, parent, position, rotation, forceClone, userDatas);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步实例化一个游戏对象
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址</param>
|
||||
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象</param>
|
||||
/// <param name="userDatas">用户自定义数据</param>
|
||||
public SpawnHandle SpawnSync(string location, bool forceClone = false, params System.Object[] userDatas)
|
||||
{
|
||||
SpawnHandle handle = SpawnInternal(location, null, Vector3.zero, Quaternion.identity, forceClone, userDatas);
|
||||
handle.WaitForAsyncComplete();
|
||||
return handle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步实例化一个游戏对象
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址</param>
|
||||
/// <param name="parent">父物体</param>
|
||||
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象</param>
|
||||
/// <param name="userDatas">用户自定义数据</param>
|
||||
public SpawnHandle SpawnSync(string location, Transform parent, bool forceClone = false, params System.Object[] userDatas)
|
||||
{
|
||||
SpawnHandle handle = SpawnInternal(location, parent, Vector3.zero, Quaternion.identity, forceClone, userDatas);
|
||||
handle.WaitForAsyncComplete();
|
||||
return handle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步实例化一个游戏对象
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址</param>
|
||||
/// <param name="parent">父物体</param>
|
||||
/// <param name="position">世界坐标</param>
|
||||
/// <param name="rotation">世界角度</param>
|
||||
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象</param>
|
||||
/// <param name="userDatas">用户自定义数据</param>
|
||||
public SpawnHandle SpawnSync(string location, Transform parent, Vector3 position, Quaternion rotation, bool forceClone = false, params System.Object[] userDatas)
|
||||
{
|
||||
SpawnHandle handle = SpawnInternal(location, parent, position, rotation, forceClone, userDatas);
|
||||
handle.WaitForAsyncComplete();
|
||||
return handle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 实例化一个游戏对象
|
||||
/// </summary>
|
||||
private SpawnHandle SpawnInternal(string location, Transform parent, Vector3 position, Quaternion rotation, bool forceClone, params System.Object[] userDatas)
|
||||
{
|
||||
var pool = TryGetGameObjectPool(location);
|
||||
if (pool != null)
|
||||
{
|
||||
return pool.Spawn(parent, position, rotation, forceClone, userDatas);
|
||||
}
|
||||
|
||||
// 如果不存在创建游戏对象池
|
||||
pool = new GameObjectPool(_spawnerRoot, location, false, 0, int.MaxValue, -1f);
|
||||
pool.CreatePool(_package);
|
||||
_gameObjectPools.Add(pool);
|
||||
return pool.Spawn(parent, position, rotation, forceClone, userDatas);
|
||||
}
|
||||
|
||||
|
||||
private GameObjectPool TryGetGameObjectPool(string location)
|
||||
{
|
||||
foreach (var pool in _gameObjectPools)
|
||||
{
|
||||
if (pool.Location == location)
|
||||
return pool;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c0b7912d44674d47a5b7240670dcc87
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,21 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace UniFramework.Pooling
|
||||
{
|
||||
internal static class UniLogger
|
||||
{
|
||||
[Conditional("DEBUG")]
|
||||
public static void Log(string info)
|
||||
{
|
||||
UnityEngine.Debug.Log(info);
|
||||
}
|
||||
public static void Warning(string info)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning(info);
|
||||
}
|
||||
public static void Error(string info)
|
||||
{
|
||||
UnityEngine.Debug.LogError(info);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 50142a5596fb6c1439dced35faef4d4c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using YooAsset;
|
||||
|
||||
namespace UniFramework.Pooling
|
||||
{
|
||||
/// <summary>
|
||||
/// 游戏对象池系统
|
||||
/// </summary>
|
||||
public static class UniPooling
|
||||
{
|
||||
private static bool _isInitialize = false;
|
||||
private static GameObject _driver = null;
|
||||
private static readonly List<Spawner> _spawners = new List<Spawner>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 初始化游戏对象池系统
|
||||
/// </summary>
|
||||
public static void Initalize()
|
||||
{
|
||||
if (_isInitialize)
|
||||
throw new Exception($"{nameof(UniPooling)} is initialized !");
|
||||
|
||||
if (_isInitialize == false)
|
||||
{
|
||||
// 创建驱动器
|
||||
_isInitialize = true;
|
||||
_driver = new UnityEngine.GameObject($"[{nameof(UniPooling)}]");
|
||||
_driver.AddComponent<UniPoolingDriver>();
|
||||
UnityEngine.Object.DontDestroyOnLoad(_driver);
|
||||
UniLogger.Log($"{nameof(UniPooling)} initalize !");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁游戏对象池系统
|
||||
/// </summary>
|
||||
public static void Destroy()
|
||||
{
|
||||
if (_isInitialize)
|
||||
{
|
||||
foreach (var spawner in _spawners)
|
||||
{
|
||||
spawner.Destroy();
|
||||
}
|
||||
_spawners.Clear();
|
||||
|
||||
_isInitialize = false;
|
||||
if (_driver != null)
|
||||
GameObject.Destroy(_driver);
|
||||
UniLogger.Log($"{nameof(UniPooling)} destroy all !");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新游戏对象池系统
|
||||
/// </summary>
|
||||
internal static void Update()
|
||||
{
|
||||
if (_isInitialize)
|
||||
{
|
||||
foreach (var spawner in _spawners)
|
||||
{
|
||||
spawner.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建游戏对象生成器
|
||||
/// </summary>
|
||||
/// <param name="packageName">资源包名称</param>
|
||||
public static Spawner CreateSpawner(string packageName)
|
||||
{
|
||||
// 获取资源包
|
||||
var assetPackage = YooAssets.GetPackage(packageName);
|
||||
if (assetPackage == null)
|
||||
throw new Exception($"Not found asset package : {packageName}");
|
||||
|
||||
// 检测资源包初始化状态
|
||||
if (assetPackage.InitializeStatus == EOperationStatus.None)
|
||||
throw new Exception($"Asset package {packageName} not initialize !");
|
||||
if (assetPackage.InitializeStatus == EOperationStatus.Failed)
|
||||
throw new Exception($"Asset package {packageName} initialize failed !");
|
||||
|
||||
if (HasSpawner(packageName))
|
||||
return GetSpawner(packageName);
|
||||
|
||||
Spawner spawner = new Spawner(_driver, assetPackage);
|
||||
_spawners.Add(spawner);
|
||||
return spawner;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取游戏对象生成器
|
||||
/// </summary>
|
||||
/// <param name="packageName">资源包名称</param>
|
||||
public static Spawner GetSpawner(string packageName)
|
||||
{
|
||||
foreach (var spawner in _spawners)
|
||||
{
|
||||
if (spawner.PackageName == packageName)
|
||||
return spawner;
|
||||
}
|
||||
|
||||
UniLogger.Warning($"Not found spawner : {packageName}");
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测游戏对象生成器是否存在
|
||||
/// </summary>
|
||||
/// <param name="packageName">资源包名称</param>
|
||||
public static bool HasSpawner(string packageName)
|
||||
{
|
||||
foreach (var spawner in _spawners)
|
||||
{
|
||||
if (spawner.PackageName == packageName)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 04fd1800aa2e61644893fa7893d93db8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniFramework.Pooling
|
||||
{
|
||||
internal class UniPoolingDriver : MonoBehaviour
|
||||
{
|
||||
void Update()
|
||||
{
|
||||
UniPooling.Update();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4112e0723ed46c45927cc3498d62e5a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user