From 5d83df6b2951f918aa0fcc71e454a5191b7157f0 Mon Sep 17 00:00:00 2001
From: ALEXTANG <574809918@qq.com>
Date: Tue, 4 Apr 2023 16:04:55 +0800
Subject: [PATCH] ResourceModule
ResourceModule
---
.../GameFramework/Resource/AssetTag.cs | 42 ++
.../GameFramework/Resource/AssetTag.cs.meta | 3 +
.../GameFramework/Resource/HasAssetResult.cs | 11 +-
.../Resource/IResourceManager.cs | 97 ++++-
.../GameFramework/Resource/ResourceManager.cs | 378 ++++++++++++++++--
.../Resource/YooAsset/YooAssetsExtension.cs | 22 +
6 files changed, 509 insertions(+), 44 deletions(-)
create mode 100644 Assets/TEngine/Runtime/GameFramework/Resource/AssetTag.cs
create mode 100644 Assets/TEngine/Runtime/GameFramework/Resource/AssetTag.cs.meta
diff --git a/Assets/TEngine/Runtime/GameFramework/Resource/AssetTag.cs b/Assets/TEngine/Runtime/GameFramework/Resource/AssetTag.cs
new file mode 100644
index 00000000..3b5790c2
--- /dev/null
+++ b/Assets/TEngine/Runtime/GameFramework/Resource/AssetTag.cs
@@ -0,0 +1,42 @@
+using UnityEngine;
+using YooAsset;
+
+namespace TEngine
+{
+ ///
+ /// 资源标识。
+ ///
+ [DisallowMultipleComponent, AddComponentMenu("")]
+ public sealed class AssetTag: MonoBehaviour
+ {
+ private AssetOperationHandle _operationHandle;
+
+ private int _instanceID = 0;
+
+ private string location;
+
+ private void Awake()
+ {
+ if (location != null && (_instanceID == -1 || _instanceID != gameObject.GetInstanceID()))
+ {
+ // Bind(GetAsset(operation, assetLocation));
+ }
+ }
+
+ public void Bind(AssetOperationHandle operation,string assetLocation)
+ {
+ _operationHandle = operation;
+ this.location = assetLocation;
+ _instanceID = gameObject.GetInstanceID();
+ }
+
+ private void OnDestroy()
+ {
+ if (_operationHandle != null)
+ {
+ _operationHandle.Release();
+ _operationHandle = null;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/TEngine/Runtime/GameFramework/Resource/AssetTag.cs.meta b/Assets/TEngine/Runtime/GameFramework/Resource/AssetTag.cs.meta
new file mode 100644
index 00000000..55aa5b44
--- /dev/null
+++ b/Assets/TEngine/Runtime/GameFramework/Resource/AssetTag.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 854f63fe041d43f0ab0f76b1059eab89
+timeCreated: 1680592471
\ No newline at end of file
diff --git a/Assets/TEngine/Runtime/GameFramework/Resource/HasAssetResult.cs b/Assets/TEngine/Runtime/GameFramework/Resource/HasAssetResult.cs
index 99bcf951..c599bbc1 100644
--- a/Assets/TEngine/Runtime/GameFramework/Resource/HasAssetResult.cs
+++ b/Assets/TEngine/Runtime/GameFramework/Resource/HasAssetResult.cs
@@ -11,9 +11,9 @@
NotExist = 0,
///
- /// 资源尚未准备完毕。
+ /// 资源需要从远端更新下载。
///
- NotReady,
+ AssetOnline,
///
/// 存在资源且存储在磁盘上。
@@ -33,6 +33,11 @@
///
/// 存在二进制资源且存储在文件系统里。
///
- BinaryOnFileSystem
+ BinaryOnFileSystem,
+
+ ///
+ /// 资源定位地址无效。
+ ///
+ Valid,
}
}
diff --git a/Assets/TEngine/Runtime/GameFramework/Resource/IResourceManager.cs b/Assets/TEngine/Runtime/GameFramework/Resource/IResourceManager.cs
index 1e66d407..74dd0789 100644
--- a/Assets/TEngine/Runtime/GameFramework/Resource/IResourceManager.cs
+++ b/Assets/TEngine/Runtime/GameFramework/Resource/IResourceManager.cs
@@ -1,6 +1,7 @@
using System.Threading;
using Cysharp.Threading.Tasks;
using UnityEngine;
+using UnityEngine.SceneManagement;
using YooAsset;
namespace TEngine
@@ -103,6 +104,70 @@ namespace TEngine
/// 检查资源是否存在的结果。
HasAssetResult HasAsset(string assetName);
+ ///
+ /// 设置默认资源包。
+ ///
+ /// 资源包。
+ void SetDefaultPackage(ResourcePackage package);
+
+ ///
+ /// 是否需要从远端更新下载。
+ ///
+ /// 资源的定位地址。
+ ///
+ bool IsNeedDownloadFromRemote(string location);
+
+ ///
+ /// 是否需要从远端更新下载。
+ ///
+ /// 资源信息。
+ ///
+ bool IsNeedDownloadFromRemote(AssetInfo assetInfo);
+
+ ///
+ /// 获取资源信息列表。
+ ///
+ /// 资源标签。
+ /// 资源信息列表。
+ AssetInfo[] GetAssetInfos(string tag);
+
+ ///
+ /// 获取资源信息列表。
+ ///
+ /// 资源标签列表。
+ /// 资源信息列表。
+ AssetInfo[] GetAssetInfos(string[] tags);
+
+ ///
+ /// 获取资源信息。
+ ///
+ /// 资源的定位地址。
+ /// 资源信息。
+ AssetInfo GetAssetInfo(string location);
+
+ ///
+ /// 检查资源定位地址是否有效。
+ ///
+ /// 资源的定位地址
+ bool CheckLocationValid(string location);
+
+ ///
+ /// 同步加载资源。
+ ///
+ /// 要加载资源的名称。
+ /// 要加载资源的类型。
+ /// 资源实例。
+ T LoadAsset(string assetName) where T : Object;
+
+ ///
+ /// 同步加载资源。
+ ///
+ /// 要加载资源的名称。
+ /// 父节点位置。
+ /// 要加载资源的类型。
+ /// 资源实例。
+ T LoadAsset(string assetName, Transform parent) where T :Object;
+
///
/// 同步加载资源。
///
@@ -110,7 +175,7 @@ namespace TEngine
/// 要加载资源的名称。
/// 要加载资源的类型。
/// 资源实例。
- T LoadAsset(string assetName,out AssetOperationHandle handle) where T : UnityEngine.Object;
+ T LoadAsset(string assetName,out AssetOperationHandle handle) where T : Object;
///
/// 同步加载资源。
@@ -120,7 +185,7 @@ namespace TEngine
/// 父节点位置。
/// 要加载资源的类型。
/// 资源实例。
- T LoadAsset(string assetName, Transform parent,out AssetOperationHandle handle) where T : UnityEngine.Object;
+ T LoadAsset(string assetName, Transform parent,out AssetOperationHandle handle) where T :Object;
///
/// 异步加载资源。
@@ -129,7 +194,7 @@ namespace TEngine
/// 取消操作Token。
/// 要加载资源的类型。
/// 异步资源实例。
- UniTask LoadAssetAsync(string assetName,CancellationToken cancellationToken) where T : UnityEngine.Object;
+ UniTask LoadAssetAsync(string assetName,CancellationToken cancellationToken) where T : Object;
///
/// 异步加载游戏物体。
@@ -145,14 +210,34 @@ namespace TEngine
/// 要加载资源的名称。
/// 要加载资源的类型。
/// 同步加载资源句柄。
- AssetOperationHandle LoadAssetGetOperation(string assetName) where T : UnityEngine.Object;
+ AssetOperationHandle LoadAssetGetOperation(string assetName) where T : Object;
///
/// 异步加载资源并获取句柄。
///
/// 要加载资源的名称。
/// 要加载资源的类型。
- /// 同步加载资源句柄。
- AssetOperationHandle LoadAssetAsyncHandle(string assetName) where T : UnityEngine.Object;
+ /// 异步加载资源句柄。
+ AssetOperationHandle LoadAssetAsyncHandle(string assetName) where T : Object;
+
+ ///
+ /// 异步加载场景。
+ ///
+ /// 场景的定位地址
+ /// 场景加载模式
+ /// 加载完毕时是否主动激活
+ /// 优先级
+ /// 异步加载场景句柄。
+ SceneOperationHandle LoadSceneAsync(string location, LoadSceneMode sceneMode = LoadSceneMode.Single, bool activateOnLoad = true, int priority = 100);
+
+ ///
+ /// 异步加载场景
+ ///
+ /// 场景的资源信息
+ /// 场景加载模式
+ /// 加载完毕时是否主动激活
+ /// 优先级
+ /// 异步加载场景句柄。
+ SceneOperationHandle LoadSceneAsync(AssetInfo assetInfo, LoadSceneMode sceneMode = LoadSceneMode.Single, bool activateOnLoad = true, int priority = 100);
}
}
\ No newline at end of file
diff --git a/Assets/TEngine/Runtime/GameFramework/Resource/ResourceManager.cs b/Assets/TEngine/Runtime/GameFramework/Resource/ResourceManager.cs
index 6d528b11..365b7dd9 100644
--- a/Assets/TEngine/Runtime/GameFramework/Resource/ResourceManager.cs
+++ b/Assets/TEngine/Runtime/GameFramework/Resource/ResourceManager.cs
@@ -1,7 +1,7 @@
-using System.Diagnostics;
-using System.Threading;
+using System.Threading;
using Cysharp.Threading.Tasks;
using UnityEngine;
+using UnityEngine.SceneManagement;
using YooAsset;
namespace TEngine
@@ -70,40 +70,28 @@ namespace TEngine
///
public long Milliseconds { get; set; }
- ///
- /// The total number of frames since the start of the game (Read Only).
- ///
- private static int _lastUpdateFrame = 0;
-
///
/// 获取游戏框架模块优先级。
///
/// 优先级较高的模块会优先轮询,并且关闭操作会后进行。
internal override int Priority => 4;
+
+ ///
+ /// 资源服务器地址。
+ ///
+ public string HostServerURL { get; set; }
#endregion
+ #region 生命周期
internal override void Update(float elapseSeconds, float realElapseSeconds)
{
- DebugCheckDuplicateDriver();
- YooAssets.Update();
- }
-
- [Conditional("DEBUG")]
- private void DebugCheckDuplicateDriver()
- {
- if (_lastUpdateFrame > 0)
- {
- if (_lastUpdateFrame == Time.frameCount)
- YooLogger.Warning($"There are two {nameof(YooAssetsDriver)} in the scene. Please ensure there is always exactly one driver in the scene.");
- }
-
- _lastUpdateFrame = Time.frameCount;
}
internal override void Shutdown()
{
YooAssets.Destroy();
}
+ #endregion
#region 设置接口
///
@@ -137,14 +125,63 @@ namespace TEngine
public void Initialize()
{
- throw new System.NotImplementedException();
+ // 初始化资源系统
+ YooAssets.Initialize(new YooAssetsLogger());
+ YooAssets.SetOperationSystemMaxTimeSlice(Milliseconds);
+ YooAssets.SetCacheSystemCachedFileVerifyLevel(VerifyLevel);
+
+ // 创建默认的资源包
+ string packageName = PackageName;
+ var defaultPackage = YooAssets.TryGetPackage(packageName);
+ if (defaultPackage == null)
+ {
+ defaultPackage = YooAssets.CreatePackage(packageName);
+ YooAssets.SetDefaultPackage(defaultPackage);
+ }
}
public InitializationOperation InitPackage()
{
- throw new System.NotImplementedException();
- }
+ // 创建默认的资源包
+ string packageName = PackageName;
+ var package = YooAssets.TryGetPackage(packageName);
+ if (package == null)
+ {
+ package = YooAssets.CreatePackage(packageName);
+ YooAssets.SetDefaultPackage(package);
+ }
+ // 编辑器下的模拟模式
+ InitializationOperation initializationOperation = null;
+ if (PlayMode == EPlayMode.EditorSimulateMode)
+ {
+ var createParameters = new EditorSimulateModeParameters();
+ createParameters.SimulateManifestFilePath = EditorSimulateModeHelper.SimulateBuild(packageName);
+ initializationOperation = package.InitializeAsync(createParameters);
+ }
+
+ // 单机运行模式
+ if (PlayMode == EPlayMode.OfflinePlayMode)
+ {
+ var createParameters = new OfflinePlayModeParameters();
+ createParameters.DecryptionServices = new GameDecryptionServices();
+ initializationOperation = package.InitializeAsync(createParameters);
+ }
+
+ // 联机运行模式
+ if (PlayMode == EPlayMode.HostPlayMode)
+ {
+ var createParameters = new HostPlayModeParameters();
+ createParameters.DecryptionServices = new GameDecryptionServices();
+ createParameters.QueryServices = new GameQueryServices();
+ createParameters.DefaultHostServer = HostServerURL;
+ createParameters.FallbackHostServer = HostServerURL;
+ initializationOperation = package.InitializeAsync(createParameters);
+ }
+
+ return initializationOperation;
+ }
+
public void UnloadAsset(object asset)
{
throw new System.NotImplementedException();
@@ -152,47 +189,318 @@ namespace TEngine
public void UnloadUnusedAssets()
{
- throw new System.NotImplementedException();
+ YooAssets.UnloadUnusedAssets();
}
public void ForceUnloadAllAssets()
{
- throw new System.NotImplementedException();
+ YooAssets.ForceUnloadAllAssets();
}
public HasAssetResult HasAsset(string assetName)
{
- throw new System.NotImplementedException();
+ if (string.IsNullOrEmpty(assetName))
+ {
+ throw new GameFrameworkException("Asset name is invalid.");
+ }
+
+ AssetInfo assetInfo = YooAssets.GetAssetInfo(assetName);
+
+ if (!CheckLocationValid(assetName))
+ {
+ return HasAssetResult.Valid;
+ }
+
+ if (assetInfo == null)
+ {
+ return HasAssetResult.NotExist;
+ }
+
+ if (IsNeedDownloadFromRemote(assetInfo))
+ {
+ return HasAssetResult.AssetOnline;
+ }
+
+ return HasAssetResult.AssetOnDisk;
}
+ ///
+ /// 设置默认的资源包。
+ ///
+ public void SetDefaultPackage(ResourcePackage package)
+ {
+ YooAssets.SetDefaultPackage(package);
+ }
+
+ #region 资源信息
+
+ ///
+ /// 是否需要从远端更新下载。
+ ///
+ /// 资源的定位地址
+ public bool IsNeedDownloadFromRemote(string location)
+ {
+ return YooAssets.IsNeedDownloadFromRemote(location);
+ }
+
+ ///
+ /// 是否需要从远端更新下载。
+ ///
+ /// 资源信息。
+ public bool IsNeedDownloadFromRemote(AssetInfo assetInfo)
+ {
+ return YooAssets.IsNeedDownloadFromRemote(assetInfo);
+ }
+
+ ///
+ /// 获取资源信息列表。
+ ///
+ /// 资源标签。
+ /// 资源信息列表。
+ public AssetInfo[] GetAssetInfos(string tag)
+ {
+ return YooAssets.GetAssetInfos(tag);
+ }
+
+ ///
+ /// 获取资源信息列表。
+ ///
+ /// 资源标签列表。
+ /// 资源信息列表。
+ public AssetInfo[] GetAssetInfos(string[] tags)
+ {
+ return YooAssets.GetAssetInfos(tags);
+ }
+
+ ///
+ /// 获取资源信息。
+ ///
+ /// 资源的定位地址。
+ /// 资源信息。
+ public AssetInfo GetAssetInfo(string location)
+ {
+ return YooAssets.GetAssetInfo(location);
+ }
+
+ ///
+ /// 检查资源定位地址是否有效。
+ ///
+ /// 资源的定位地址
+ public bool CheckLocationValid(string location)
+ {
+ return YooAssets.CheckLocationValid(location);
+ }
+
+ #endregion
+ ///
+ /// 同步加载资源。
+ ///
+ /// 要加载资源的名称。
+ /// 要加载资源的类型。
+ /// 资源实例。
+ public T LoadAsset(string assetName) where T : Object
+ {
+ if (string.IsNullOrEmpty(assetName))
+ {
+ Log.Error("Asset name is invalid.");
+ return default;
+ }
+ AssetOperationHandle handle = YooAssets.LoadAssetSync(assetName);
+
+ if (typeof(T) == typeof(GameObject))
+ {
+ GameObject ret = handle.InstantiateSync();
+ BindAssetTag(ret, handle, assetName);
+ return ret as T;
+ }
+ else
+ {
+ return handle.AssetObject as T;
+ }
+ }
+
+ ///
+ /// 同步加载资源。
+ ///
+ /// 要加载资源的名称。
+ /// 父节点位置。
+ /// 要加载资源的类型。
+ /// 资源实例。
+ public T LoadAsset(string assetName, Transform parent) where T : Object
+ {
+ if (string.IsNullOrEmpty(assetName))
+ {
+ Log.Error("Asset name is invalid.");
+ return default;
+ }
+ AssetOperationHandle handle = YooAssets.LoadAssetSync(assetName);
+
+ if (typeof(T) == typeof(GameObject))
+ {
+ GameObject ret = handle.InstantiateSync(parent);
+ BindAssetTag(ret, handle, assetName);
+ return ret as T;
+ }
+ else
+ {
+ return handle.AssetObject as T;
+ }
+ }
+
+ ///
+ /// 同步加载资源。
+ ///
+ /// 资源操作句柄。
+ /// 要加载资源的名称。
+ /// 要加载资源的类型。
+ /// 资源实例。
public T LoadAsset(string assetName,out AssetOperationHandle handle) where T : Object
{
- throw new System.NotImplementedException();
+ handle = YooAssets.LoadAssetSync(assetName);
+
+ if (string.IsNullOrEmpty(assetName))
+ {
+ Log.Error("Asset name is invalid.");
+ return default;
+ }
+
+ if (typeof(T) == typeof(GameObject))
+ {
+ GameObject ret = handle.InstantiateSync();
+ return ret as T;
+ }
+ else
+ {
+ return handle.AssetObject as T;
+ }
}
+ ///
+ /// 同步加载资源。
+ ///
+ /// 要加载资源的名称。
+ /// 资源操作句柄。
+ /// 父节点位置。
+ /// 要加载资源的类型。
+ /// 资源实例。
public T LoadAsset(string assetName, Transform parent,out AssetOperationHandle handle) where T : Object
{
- throw new System.NotImplementedException();
+ handle = YooAssets.LoadAssetSync(assetName);
+
+ if (string.IsNullOrEmpty(assetName))
+ {
+ Log.Error("Asset name is invalid.");
+ return default;
+ }
+
+ if (typeof(T) == typeof(GameObject))
+ {
+ GameObject ret = handle.InstantiateSync(parent);
+ return ret as T;
+ }
+ else
+ {
+ return handle.AssetObject as T;
+ }
}
- public UniTask LoadAssetAsync(string assetName, CancellationToken cancellationToken) where T : Object
+ ///
+ /// 异步加载资源实例。
+ ///
+ /// 要加载的实例名称。
+ /// 取消操作Token。
+ /// 资源实实例。
+ public async UniTask LoadAssetAsync(string assetName, CancellationToken cancellationToken) where T : Object
{
- throw new System.NotImplementedException();
+ AssetOperationHandle handle = LoadAssetAsyncHandle(assetName);
+
+ await handle.ToUniTask(cancellationToken:cancellationToken);
+
+ return handle.AssetObject as T;
}
- public UniTask LoadGameObjectAsync(string assetName, CancellationToken cancellationToken)
+ ///
+ /// 异步加载游戏物体。
+ ///
+ /// 要加载的游戏物体名称。
+ /// 取消操作Token。
+ /// 异步游戏物体实例。
+ public async UniTask LoadGameObjectAsync(string assetName, CancellationToken cancellationToken)
{
- throw new System.NotImplementedException();
+ AssetOperationHandle handle = LoadAssetAsyncHandle(assetName);
+
+ await handle.ToUniTask(cancellationToken:cancellationToken);
+
+ GameObject ret = handle.InstantiateSync();
+
+ BindAssetTag(ret, handle, assetName);
+
+ return ret;
}
+ ///
+ /// 同步加载资源并获取句柄。
+ ///
+ /// 要加载资源的名称。
+ /// 要加载资源的类型。
+ /// 同步加载资源句柄。
public AssetOperationHandle LoadAssetGetOperation(string assetName) where T : Object
{
- throw new System.NotImplementedException();
+ return YooAssets.LoadAssetSync(assetName);
}
+ ///
+ /// 异步加载资源并获取句柄。
+ ///
+ /// 要加载资源的名称。
+ /// 要加载资源的类型。
+ /// 异步加载资源句柄。
public AssetOperationHandle LoadAssetAsyncHandle(string assetName) where T : Object
{
- throw new System.NotImplementedException();
+ return YooAssets.LoadAssetAsync(assetName);
+ }
+
+ ///
+ /// 异步加载场景。
+ ///
+ /// 场景的定位地址
+ /// 场景加载模式
+ /// 加载完毕时是否主动激活
+ /// 优先级
+ /// 异步加载场景句柄。
+ public SceneOperationHandle LoadSceneAsync(string location, LoadSceneMode sceneMode = LoadSceneMode.Single, bool activateOnLoad = true, int priority = 100)
+ {
+ return YooAssets.LoadSceneAsync(location,sceneMode,activateOnLoad,priority);
+ }
+
+ ///
+ /// 异步加载场景
+ ///
+ /// 场景的资源信息
+ /// 场景加载模式
+ /// 加载完毕时是否主动激活
+ /// 优先级
+ /// 异步加载场景句柄。
+ public SceneOperationHandle LoadSceneAsync(AssetInfo assetInfo, LoadSceneMode sceneMode = LoadSceneMode.Single, bool activateOnLoad = true, int priority = 100)
+ {
+ return YooAssets.LoadSceneAsync(assetInfo,sceneMode,activateOnLoad,priority);
+ }
+
+ private bool BindAssetTag(GameObject go,AssetOperationHandle handle,string location)
+ {
+ if (go == null)
+ {
+ throw new GameFrameworkException($"ResourceMgr BindAssetTag Failed! GameObject is null!");
+ }
+
+ if (handle == null)
+ {
+ throw new GameFrameworkException($"ResourceMgr BindAssetTag Failed! AssetOperationHandle is null!");
+ }
+
+ go.AddComponent().Bind(handle,location);
+
+ return true;
}
}
}
\ No newline at end of file
diff --git a/Assets/TEngine/Runtime/GameFramework/Resource/YooAsset/YooAssetsExtension.cs b/Assets/TEngine/Runtime/GameFramework/Resource/YooAsset/YooAssetsExtension.cs
index 1e0220bf..5f7ebb6c 100644
--- a/Assets/TEngine/Runtime/GameFramework/Resource/YooAsset/YooAssetsExtension.cs
+++ b/Assets/TEngine/Runtime/GameFramework/Resource/YooAsset/YooAssetsExtension.cs
@@ -405,6 +405,28 @@ namespace YooAsset
return _defaultPackage.CreateResourceUnpacker(unpackingMaxNumber, failedTryAgain);
}
#endregion
+
+ #region 资源卸载
+
+ ///
+ /// 资源回收(卸载引用计数为零的资源)
+ ///
+ public static void UnloadUnusedAssets()
+ {
+ DebugCheckDefaultPackageValid();
+ _defaultPackage.UnloadUnusedAssets();
+ }
+
+ ///
+ /// 强制回收所有资源
+ ///
+ public static void ForceUnloadAllAssets()
+ {
+ DebugCheckDefaultPackageValid();
+ _defaultPackage.ForceUnloadAllAssets();
+ }
+
+ #endregion
#region 调试方法
[Conditional("DEBUG")]