[+] 新增游戏物体缓存池ResourcePool

[+] 新增游戏物体缓存池ResourcePool
This commit is contained in:
ALEXTANG
2023-09-05 14:35:19 +08:00
parent 75725314ad
commit e3a47393f4
12 changed files with 1053 additions and 48 deletions

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 62c8f710f3264758a89eaefc4ae88921
timeCreated: 1693831262

View File

@@ -0,0 +1,70 @@
using YooAsset;
namespace TEngine
{
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();
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4e1853e7ff624c639fba990079beeee5
timeCreated: 1693831296

View File

@@ -0,0 +1,234 @@
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
namespace TEngine
{
/// <summary>
/// 游戏物体对象池。
/// </summary>
internal class GameObjectPool
{
private readonly GameObject _root;
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 => _cacheOperations.Count;
/// <summary>
/// 外部使用总数。
/// </summary>
public int SpawnCount { private set; get; } = 0;
/// <summary>
/// 是否常驻不销毁。
/// </summary>
public bool DontDestroy => _dontDestroy;
/// <summary>
/// 游戏物体对象池。
/// </summary>
/// <param name="poolingRoot">对象池根节点。</param>
/// <param name="location">资源定位地址。</param>
/// <param name="dontDestroy">是否常驻不销毁。</param>
/// <param name="initCapacity">初始容量。</param>
/// <param name="maxCapacity">最大容量。</param>
/// <param name="destroyTime">对象池销毁时间。</param>
public GameObjectPool(GameObject poolingRoot, string location, bool dontDestroy, int initCapacity, int maxCapacity, float destroyTime)
{
_root = new GameObject(location);
_root.transform.parent = poolingRoot.transform;
Location = location;
_dontDestroy = dontDestroy;
_initCapacity = initCapacity;
_maxCapacity = maxCapacity;
_destroyTime = destroyTime;
// 创建缓存池
_cacheOperations = new Queue<InstantiateOperation>(initCapacity);
}
/// <summary>
/// 创建对象池。
/// </summary>
/// <param name="package">资源包。</param>
public void CreatePool(ResourcePackage package)
{
// 加载游戏对象
AssetHandle = package.LoadAssetAsync<GameObject>(Location);
// 创建初始对象
for (int i = 0; i < _initCapacity; i++)
{
var operation = AssetHandle.InstantiateAsync(_root.transform);
operation.Completed += Operation_Completed;
_cacheOperations.Enqueue(operation);
}
}
private void Operation_Completed(AsyncOperationBase obj)
{
if (obj.Status == EOperationStatus.Succeed)
{
var op = obj as InstantiateOperation;
if (op.Result != null)
op.Result.SetActive(false);
}
}
/// <summary>
/// 销毁游戏对象池。
/// </summary>
public void DestroyPool()
{
// 卸载资源对象
AssetHandle.Release();
AssetHandle = null;
// 销毁游戏对象
Object.Destroy(_root);
_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>
/// <param name="operation">资源实例化操作句柄。</param>
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>
/// <param name="operation">资源实例化操作句柄。</param>
public void Discard(InstantiateOperation operation)
{
if (IsDestroyed())
{
DestroyInstantiateOperation(operation);
return;
}
SpawnCount--;
if (SpawnCount <= 0)
_lastRestoreRealTime = Time.realtimeSinceStartup;
DestroyInstantiateOperation(operation);
}
/// <summary>
/// 获取一个游戏对象。
/// </summary>
/// <param name="parent">父节点位置。</param>
/// <param name="position">位置。</param>
/// <param name="rotation">旋转。</param>
/// <param name="forceClone">是否强制克隆。</param>
/// <param name="userDatas">用户自定义数据。</param>
/// <returns>Spawn操作句柄。</returns>
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)
{
Object.Destroy(operation.Result);
}
}
private void SetRestoreGameObject(GameObject gameObj)
{
if (gameObj != null)
{
gameObj.SetActive(false);
gameObj.transform.SetParent(_root.transform);
gameObj.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3f0c9bab3d1243fda94ec9a08844ceee
timeCreated: 1693831296

View File

@@ -0,0 +1,253 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
namespace TEngine
{
/// <summary>
/// 游戏对象池系统。
/// <remarks>用法 SpawnHandle handle = ResourcePool.SpawnAsync("Cube");</remarks>
/// </summary>
public static class ResourcePool
{
private static bool _isInitialize = false;
private static readonly List<Spawner> Spawners = new List<Spawner>();
private static GameObject _root;
private static Spawner _defaultSpawner = null;
/// <summary>
/// 默认Package对象生成器。
/// </summary>
private static Spawner DefaultSpawner => _defaultSpawner ??= CreateSpawner();
/// <summary>
/// 初始化游戏对象池系统
/// </summary>
internal static void Initialize(GameObject root)
{
if (_isInitialize)
throw new Exception($"{nameof(ResourcePool)} is initialized !");
if (_isInitialize == false)
{
_root = root;
_isInitialize = true;
Log.Info($"{nameof(ResourcePool)} Initialize !");
}
}
/// <summary>
/// 销毁游戏对象池系统
/// </summary>
internal static void Destroy()
{
if (_isInitialize)
{
foreach (var spawner in Spawners)
{
spawner.Destroy();
}
Spawners.Clear();
_isInitialize = false;
Log.Debug($"{nameof(ResourcePool)} 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 = "")
{
if (string.IsNullOrEmpty(packageName))
{
packageName = GameModule.Resource.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(_root, assetPackage);
Spawners.Add(spawner);
return spawner;
}
/// <summary>
/// 获取游戏对象生成器。
/// </summary>
/// <param name="packageName">资源包名称。</param>
public static Spawner GetSpawner(string packageName = "")
{
if (string.IsNullOrEmpty(packageName))
{
packageName = GameModule.Resource.packageName;
}
foreach (var spawner in Spawners)
{
if (spawner.PackageName == packageName)
return spawner;
}
Log.Warning($"Not found spawner : {packageName}");
return null;
}
/// <summary>
/// 检测游戏对象生成器是否存在。
/// </summary>
/// <param name="packageName">资源包名称。</param>
public static bool HasSpawner(string packageName = "")
{
if (string.IsNullOrEmpty(packageName))
{
packageName = GameModule.Resource.packageName;
}
foreach (var spawner in Spawners)
{
if (spawner.PackageName == packageName)
return true;
}
return false;
}
#region
/// <summary>
/// 销毁所有对象池及其资源。
/// </summary>
/// <param name="includeAll">销毁所有对象池,包括常驻对象池。</param>
public static void DestroyAll(bool includeAll)
{
DefaultSpawner.DestroyAll(includeAll);
}
/// <summary>
/// 异步创建指定资源的游戏对象池。
/// </summary>
/// <param name="location">资源定位地址。</param>
/// <param name="dontDestroy">资源常驻不销毁。</param>
/// <param name="initCapacity">对象池的初始容量。</param>
/// <param name="maxCapacity">对象池的最大容量。</param>
/// <param name="destroyTime">静默销毁时间(注意:小于零代表不主动销毁)。</param>
public static CreatePoolOperation CreateGameObjectPoolAsync(string location, bool dontDestroy = false, int initCapacity = 0, int maxCapacity = int.MaxValue, float destroyTime = -1f)
{
return DefaultSpawner.CreateGameObjectPoolAsync(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 static CreatePoolOperation CreateGameObjectPoolSync(string location, bool dontDestroy = false, int initCapacity = 0, int maxCapacity = int.MaxValue, float destroyTime = -1f)
{
return DefaultSpawner.CreateGameObjectPoolSync(location, dontDestroy, initCapacity, maxCapacity, destroyTime);
}
/// <summary>
/// 异步实例化一个游戏对象。
/// </summary>
/// <param name="location">资源定位地址。</param>
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象。</param>
/// <param name="userDatas">用户自定义数据。</param>
public static SpawnHandle SpawnAsync(string location, bool forceClone = false, params System.Object[] userDatas)
{
return DefaultSpawner.SpawnAsync(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 static SpawnHandle SpawnAsync(string location, Transform parent, bool forceClone = false, params System.Object[] userDatas)
{
return DefaultSpawner.SpawnAsync(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 static SpawnHandle SpawnAsync(string location, Transform parent, Vector3 position, Quaternion rotation, bool forceClone = false, params System.Object[] userDatas)
{
return DefaultSpawner.SpawnAsync(location, parent, position, rotation, forceClone, userDatas);
}
/// <summary>
/// 同步实例化一个游戏对象。
/// </summary>
/// <param name="location">资源定位地址。</param>
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象。</param>
/// <param name="userDatas">用户自定义数据。</param>
public static SpawnHandle SpawnSync(string location, bool forceClone = false, params System.Object[] userDatas)
{
return DefaultSpawner.SpawnSync(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 static SpawnHandle SpawnSync(string location, Transform parent, bool forceClone = false, params System.Object[] userDatas)
{
return DefaultSpawner.SpawnAsync(location, parent, 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 static SpawnHandle SpawnSync(string location, Transform parent, Vector3 position, Quaternion rotation, bool forceClone = false, params System.Object[] userDatas)
{
return DefaultSpawner.SpawnSync(location,parent,position,rotation,forceClone,userDatas);
}
#endregion
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: be208ee3e46e4243b9a68d4c7212015e
timeCreated: 1693831058

View File

@@ -0,0 +1,152 @@
using UnityEngine;
using YooAsset;
namespace TEngine
{
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)
{
Log.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 !";
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: eb2cdce8eb814f7c92c74199d065688a
timeCreated: 1693831296

View File

@@ -0,0 +1,262 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
namespace TEngine
{
/// <summary>
/// 对象生成器。
/// </summary>
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)
{
Log.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;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 570ac9abe8a04e77b49c42719a9fa93b
timeCreated: 1693831272

View File

@@ -9,9 +9,10 @@ namespace TEngine
/// <summary>
/// 资源管理器。
/// </summary>
internal partial class ResourceManager: GameFrameworkModule,IResourceManager
internal partial class ResourceManager : GameFrameworkModule, IResourceManager
{
#region Propreties
/// <summary>
/// 资源包名称。
/// </summary>
@@ -21,21 +22,21 @@ namespace TEngine
/// 获取当前资源适用的游戏版本号。
/// </summary>
public string ApplicableGameVersion => m_ApplicableGameVersion;
private string m_ApplicableGameVersion;
/// <summary>
/// 获取当前内部资源版本号。
/// </summary>
public int InternalResourceVersion => m_InternalResourceVersion;
private int m_InternalResourceVersion;
/// <summary>
/// 同时下载的最大数目。
/// </summary>
public int DownloadingMaxNum { get; set; }
/// <summary>
/// 失败重试最大数目。
/// </summary>
@@ -45,50 +46,56 @@ namespace TEngine
/// 获取资源只读区路径。
/// </summary>
public string ReadOnlyPath => m_ReadOnlyPath;
private string m_ReadOnlyPath;
/// <summary>
/// 获取资源读写区路径。
/// </summary>
public string ReadWritePath => m_ReadWritePath;
private string m_ReadWritePath;
/// <summary>
/// 资源系统运行模式。
/// </summary>
public EPlayMode PlayMode { get; set; }
/// <summary>
/// 下载文件校验等级。
/// </summary>
public EVerifyLevel VerifyLevel { get; set; }
/// <summary>
/// 设置异步系统参数,每帧执行消耗的最大时间切片(单位:毫秒)。
/// </summary>
public long Milliseconds { get; set; }
/// <summary>
/// 获取游戏框架模块优先级。
/// </summary>
/// <remarks>优先级较高的模块会优先轮询,并且关闭操作会后进行。</remarks>
internal override int Priority => 4;
#endregion
#region
internal override void Update(float elapseSeconds, float realElapseSeconds)
{
ResourcePool.Update();
}
internal override void Shutdown()
{
YooAssets.Destroy();
ResourcePool.Destroy();
}
#endregion
#region
/// <summary>
/// 设置资源只读区路径。
/// </summary>
@@ -116,6 +123,7 @@ namespace TEngine
m_ReadWritePath = readWritePath;
}
#endregion
public void Initialize()
@@ -133,6 +141,7 @@ namespace TEngine
defaultPackage = YooAssets.CreatePackage(packageName);
YooAssets.SetDefaultPackage(defaultPackage);
}
ResourcePool.Initialize(GameModule.Resource.gameObject);
}
public InitializationOperation InitPackage()
@@ -154,7 +163,7 @@ namespace TEngine
//运行时使用。
EPlayMode playMode = PlayMode;
#endif
// 编辑器下的模拟模式
InitializationOperation initializationOperation = null;
if (playMode == EPlayMode.EditorSimulateMode)
@@ -185,7 +194,7 @@ namespace TEngine
return initializationOperation;
}
public void UnloadAsset(object asset)
{
throw new System.NotImplementedException();
@@ -207,14 +216,14 @@ namespace TEngine
{
throw new GameFrameworkException("Asset name is invalid.");
}
AssetInfo assetInfo = YooAssets.GetAssetInfo(assetName);
if (!CheckLocationValid(assetName))
{
return HasAssetResult.Valid;
}
if (assetInfo == null)
{
return HasAssetResult.NotExist;
@@ -296,6 +305,7 @@ namespace TEngine
}
#endregion
/// <summary>
/// 同步加载资源。
/// </summary>
@@ -309,6 +319,7 @@ namespace TEngine
Log.Error("Asset name is invalid.");
return default;
}
AssetOperationHandle handle = YooAssets.LoadAssetSync<T>(assetName);
if (typeof(T) == typeof(GameObject))
@@ -339,6 +350,7 @@ namespace TEngine
Log.Error("Asset name is invalid.");
return default;
}
AssetOperationHandle handle = YooAssets.LoadAssetSync<T>(assetName);
if (typeof(T) == typeof(GameObject))
@@ -362,7 +374,7 @@ namespace TEngine
/// <param name="assetName">要加载资源的名称。</param>
/// <typeparam name="T">要加载资源的类型。</typeparam>
/// <returns>资源实例。</returns>
public T LoadAsset<T>(string assetName,out AssetOperationHandle handle) where T : Object
public T LoadAsset<T>(string assetName, out AssetOperationHandle handle) where T : Object
{
handle = YooAssets.LoadAssetSync<T>(assetName);
@@ -391,7 +403,7 @@ namespace TEngine
/// <param name="parent">父节点位置。</param>
/// <typeparam name="T">要加载资源的类型。</typeparam>
/// <returns>资源实例。</returns>
public T LoadAsset<T>(string assetName, Transform parent,out AssetOperationHandle handle) where T : Object
public T LoadAsset<T>(string assetName, Transform parent, out AssetOperationHandle handle) where T : Object
{
handle = YooAssets.LoadAssetSync<T>(assetName);
@@ -453,7 +465,7 @@ namespace TEngine
{
return YooAssets.LoadSubAssetsAsync<TObject>(location: location);
}
/// <summary>
/// 同步加载子资源对象
/// </summary>
@@ -471,9 +483,10 @@ namespace TEngine
/// <param name="activateOnLoad">加载完毕时是否主动激活</param>
/// <param name="priority">优先级</param>
/// <returns>异步加载场景句柄。</returns>
public SceneOperationHandle LoadSceneAsync(string location, LoadSceneMode sceneMode = LoadSceneMode.Single, bool activateOnLoad = true, int priority = 100)
public SceneOperationHandle LoadSceneAsync(string location, LoadSceneMode sceneMode = LoadSceneMode.Single, bool activateOnLoad = true,
int priority = 100)
{
return YooAssets.LoadSceneAsync(location,sceneMode,activateOnLoad,priority);
return YooAssets.LoadSceneAsync(location, sceneMode, activateOnLoad, priority);
}
/// <summary>
@@ -484,12 +497,13 @@ namespace TEngine
/// <param name="activateOnLoad">加载完毕时是否主动激活</param>
/// <param name="priority">优先级</param>
/// <returns>异步加载场景句柄。</returns>
public SceneOperationHandle LoadSceneAsync(AssetInfo assetInfo, LoadSceneMode sceneMode = LoadSceneMode.Single, bool activateOnLoad = true, int priority = 100)
public SceneOperationHandle LoadSceneAsync(AssetInfo assetInfo, LoadSceneMode sceneMode = LoadSceneMode.Single, bool activateOnLoad = true,
int priority = 100)
{
return YooAssets.LoadSceneAsync(assetInfo,sceneMode,activateOnLoad,priority);
return YooAssets.LoadSceneAsync(assetInfo, sceneMode, activateOnLoad, priority);
}
/// <summary>
/// 异步加载资源实例。
/// </summary>
@@ -499,20 +513,20 @@ namespace TEngine
public async UniTask<T> LoadAssetAsync<T>(string assetName, CancellationToken cancellationToken) where T : Object
{
AssetOperationHandle handle = LoadAssetAsyncHandle<T>(assetName);
bool cancelOrFailed = await handle.ToUniTask().AttachExternalCancellation(cancellationToken).SuppressCancellationThrow();
if (cancelOrFailed)
{
return null;
}
if (typeof(T) == typeof(GameObject))
{
GameObject ret = handle.InstantiateSync();
AssetReference.BindAssetReference(ret, handle, assetName);
return ret as T;
}
else
@@ -530,7 +544,7 @@ namespace TEngine
public async UniTask<GameObject> LoadGameObjectAsync(string assetName, CancellationToken cancellationToken)
{
AssetOperationHandle handle = LoadAssetAsyncHandle<GameObject>(assetName);
bool cancelOrFailed = await handle.ToUniTask().AttachExternalCancellation(cancellationToken).SuppressCancellationThrow();
if (cancelOrFailed)
@@ -539,12 +553,12 @@ namespace TEngine
}
GameObject ret = handle.InstantiateSync();
AssetReference.BindAssetReference(ret, handle, assetName);
return ret;
}
/// <summary>
/// 异步加载游戏物体。
/// </summary>
@@ -554,7 +568,7 @@ namespace TEngine
/// <returns>异步游戏物体实例。</returns>
public async UniTask<GameObject> LoadGameObjectAsync(string location, Transform parent, CancellationToken cancellationToken)
{
GameObject gameObject = await LoadGameObjectAsync(location,cancellationToken);
GameObject gameObject = await LoadGameObjectAsync(location, cancellationToken);
if (parent != null)
{
gameObject.transform.SetParent(parent);
@@ -563,6 +577,7 @@ namespace TEngine
{
Log.Error("Set Parent Failed");
}
return gameObject;
}
@@ -575,11 +590,11 @@ namespace TEngine
public async UniTask<RawFileOperationHandle> LoadRawAssetAsync(string location, CancellationToken cancellationToken)
{
RawFileOperationHandle handle = YooAssets.LoadRawFileAsync(location);
bool cancelOrFailed = await handle.ToUniTask().AttachExternalCancellation(cancellationToken).SuppressCancellationThrow();
handle.Dispose();
return cancelOrFailed ? null : handle;
}
@@ -591,7 +606,7 @@ namespace TEngine
/// <param name="cancellationToken">取消操作Token。</param>
/// <typeparam name="T">资源实例类型。</typeparam>
/// <returns>原生文件资源实例。</returns>
public async UniTask<T> LoadSubAssetAsync<T>(string location,string assetName, CancellationToken cancellationToken) where T : Object
public async UniTask<T> LoadSubAssetAsync<T>(string location, string assetName, CancellationToken cancellationToken) where T : Object
{
var assetInfo = GetAssetInfo(location);
if (assetInfo == null)
@@ -599,16 +614,16 @@ namespace TEngine
Log.Fatal($"AssetsInfo is null");
return null;
}
SubAssetsOperationHandle handle = YooAssets.LoadSubAssetsAsync(assetInfo);
bool cancelOrFailed = await handle.ToUniTask().AttachExternalCancellation(cancellationToken).SuppressCancellationThrow();
handle.Dispose();
return cancelOrFailed ? null : handle.GetSubAssetObject<T>(assetName);
}
/// <summary>
/// 异步加载子文件。
/// </summary>
@@ -616,7 +631,7 @@ namespace TEngine
/// <param name="cancellationToken">取消操作Token。</param>
/// <typeparam name="T">资源实例类型。</typeparam>
/// <returns>原生文件资源实例。</returns>
public async UniTask<T[]> LoadAllSubAssetAsync<T>(string location,CancellationToken cancellationToken) where T : Object
public async UniTask<T[]> LoadAllSubAssetAsync<T>(string location, CancellationToken cancellationToken) where T : Object
{
var assetInfo = GetAssetInfo(location);
if (assetInfo == null)
@@ -624,13 +639,13 @@ namespace TEngine
Log.Fatal($"AssetsInfo is null");
return null;
}
SubAssetsOperationHandle handle = YooAssets.LoadSubAssetsAsync(assetInfo);
bool cancelOrFailed = await handle.ToUniTask().AttachExternalCancellation(cancellationToken).SuppressCancellationThrow();
handle.Dispose();
return cancelOrFailed ? null : handle.GetSubAssetObjects<T>();
}
@@ -643,11 +658,12 @@ namespace TEngine
/// <param name="activateOnLoad">加载完毕时是否主动激活.</param>
/// <param name="priority">优先级.</param>
/// <returns>场景资源实例。</returns>
public async UniTask<Scene> LoadSceneAsyncByUniTask(string location,CancellationToken cancellationToken,LoadSceneMode sceneMode = LoadSceneMode.Single,
public async UniTask<Scene> LoadSceneAsyncByUniTask(string location, CancellationToken cancellationToken,
LoadSceneMode sceneMode = LoadSceneMode.Single,
bool activateOnLoad = true, int priority = 100)
{
SceneOperationHandle handle = YooAssets.LoadSceneAsync(location,sceneMode,activateOnLoad,priority);
SceneOperationHandle handle = YooAssets.LoadSceneAsync(location, sceneMode, activateOnLoad, priority);
bool cancelOrFailed = await handle.ToUniTask().AttachExternalCancellation(cancellationToken).SuppressCancellationThrow();
return cancelOrFailed ? default : handle.SceneObject;