1
This commit is contained in:
parent
9172d11d84
commit
ad913aceb4
@ -19,5 +19,11 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
/// 是否可以回收。
|
/// 是否可以回收。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool IsCanRelease();
|
bool IsCanRelease();
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unity资源对象。
|
||||||
|
/// </summary>
|
||||||
|
public UnityEngine.Object TargetObject { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,6 +39,8 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
#endif
|
#endif
|
||||||
private Sprite _sprite;
|
private Sprite _sprite;
|
||||||
|
|
||||||
|
public Object TargetObject { get; set; }
|
||||||
|
|
||||||
public string Location { get; private set; }
|
public string Location { get; private set; }
|
||||||
|
|
||||||
private bool _setNativeSize = false;
|
private bool _setNativeSize = false;
|
||||||
@ -90,6 +92,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
_sprite = null;
|
_sprite = null;
|
||||||
_setType = SetType.None;
|
_setType = SetType.None;
|
||||||
_setNativeSize = false;
|
_setNativeSize = false;
|
||||||
|
TargetObject = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SetSpriteObject Create(Image image, string location, bool setNativeSize = false, CancellationToken cancellationToken = default)
|
public static SetSpriteObject Create(Image image, string location, bool setNativeSize = false, CancellationToken cancellationToken = default)
|
||||||
@ -100,6 +103,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
item.Location = location;
|
item.Location = location;
|
||||||
item._cancellationToken = cancellationToken;
|
item._cancellationToken = cancellationToken;
|
||||||
item._setType = SetType.Image;
|
item._setType = SetType.Image;
|
||||||
|
item.TargetObject = image;
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +114,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
item.Location = location;
|
item.Location = location;
|
||||||
item._cancellationToken = cancellationToken;
|
item._cancellationToken = cancellationToken;
|
||||||
item._setType = SetType.SpriteRender;
|
item._setType = SetType.SpriteRender;
|
||||||
|
item.TargetObject = spriteRenderer;
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,26 +1,52 @@
|
|||||||
using AlicizaX;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
using Cysharp.Threading.Tasks;
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
namespace AlicizaX.Resource.Runtime
|
namespace AlicizaX.Resource.Runtime
|
||||||
{
|
{
|
||||||
public partial class ResourceExtComponent
|
public partial class ResourceExtComponent
|
||||||
{
|
{
|
||||||
/// <summary>
|
private static IResourceModule _resourceModule;
|
||||||
/// 资源组件。
|
private LoadAssetCallbacks _loadAssetCallbacks;
|
||||||
/// </summary>
|
|
||||||
private IResourceModule m_ResourceModule;
|
|
||||||
|
|
||||||
private LoadAssetCallbacks m_LoadAssetCallbacks;
|
public static IResourceModule ResourceModule => _resourceModule;
|
||||||
|
|
||||||
|
private class LoadingState : IMemory
|
||||||
|
{
|
||||||
|
public CancellationTokenSource Cts { get; set; }
|
||||||
|
public string Location { get; set; }
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
if (Cts != null)
|
||||||
|
{
|
||||||
|
Cts.Cancel();
|
||||||
|
Cts.Dispose();
|
||||||
|
Cts = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Location = String.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly Dictionary<UnityEngine.Object, LoadingState> _loadingStates = new Dictionary<UnityEngine.Object, LoadingState>();
|
||||||
|
|
||||||
private void InitializedResources()
|
private void InitializedResources()
|
||||||
{
|
{
|
||||||
m_ResourceModule = ModuleSystem.GetModule<IResourceModule>();
|
_resourceModule = ModuleSystem.GetModule<IResourceModule>();
|
||||||
m_LoadAssetCallbacks = new LoadAssetCallbacks(OnLoadAssetSuccess, OnLoadAssetFailure);
|
_loadAssetCallbacks = new LoadAssetCallbacks(OnLoadAssetSuccess, OnLoadAssetFailure);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnLoadAssetFailure(string assetName, LoadResourceStatus status, string errormessage, object userdata)
|
private void OnLoadAssetFailure(string assetName, LoadResourceStatus status, string errormessage, object userdata)
|
||||||
{
|
{
|
||||||
_assetLoadingList.Remove(assetName);
|
_assetLoadingList.Remove(assetName);
|
||||||
|
ISetAssetObject setAssetObject = (ISetAssetObject)userdata;
|
||||||
|
if (setAssetObject != null)
|
||||||
|
{
|
||||||
|
ClearLoadingState(setAssetObject.TargetObject);
|
||||||
|
}
|
||||||
|
|
||||||
Log.Error("Can not load asset from '{0}' with error message '{1}'.", assetName, errormessage);
|
Log.Error("Can not load asset from '{0}' with error message '{1}'.", assetName, errormessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,35 +55,151 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
_assetLoadingList.Remove(assetName);
|
_assetLoadingList.Remove(assetName);
|
||||||
ISetAssetObject setAssetObject = (ISetAssetObject)userdata;
|
ISetAssetObject setAssetObject = (ISetAssetObject)userdata;
|
||||||
UnityEngine.Object assetObject = asset as UnityEngine.Object;
|
UnityEngine.Object assetObject = asset as UnityEngine.Object;
|
||||||
|
|
||||||
if (assetObject != null)
|
if (assetObject != null)
|
||||||
{
|
{
|
||||||
m_AssetItemPool.Register(AssetItemObject.Create(setAssetObject.Location, assetObject), true);
|
// 检查资源是否仍然是当前需要的。
|
||||||
|
if (IsCurrentLocation(setAssetObject.TargetObject, setAssetObject.Location))
|
||||||
|
{
|
||||||
|
ClearLoadingState(setAssetObject.TargetObject);
|
||||||
|
|
||||||
|
_assetItemPool.Register(AssetItemObject.Create(setAssetObject.Location, assetObject), true);
|
||||||
SetAsset(setAssetObject, assetObject);
|
SetAsset(setAssetObject, assetObject);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
// 资源已经过期,卸载。
|
||||||
|
_resourceModule.UnloadAsset(assetObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
Log.Error($"Load failure asset type is {asset.GetType()}.");
|
Log.Error($"Load failure asset type is {asset.GetType()}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 通过资源系统设置资源。
|
/// 通过Unity对象加载资源。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="setAssetObject">需要设置的对象。</param>
|
/// <param name="setAssetObject">ISetAssetObject。</param>
|
||||||
|
/// <typeparam name="T">Unity对象类型。</typeparam>
|
||||||
public async UniTaskVoid SetAssetByResources<T>(ISetAssetObject setAssetObject) where T : UnityEngine.Object
|
public async UniTaskVoid SetAssetByResources<T>(ISetAssetObject setAssetObject) where T : UnityEngine.Object
|
||||||
{
|
{
|
||||||
await TryWaitingLoading(setAssetObject.Location);
|
var target = setAssetObject.TargetObject;
|
||||||
|
var location = setAssetObject.Location;
|
||||||
|
|
||||||
if (m_AssetItemPool.CanSpawn(setAssetObject.Location))
|
if (target == null)
|
||||||
{
|
{
|
||||||
var assetObject = (T)m_AssetItemPool.Spawn(setAssetObject.Location).Target;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取消并清理旧的加载请求。
|
||||||
|
CancelAndCleanupOldRequest(target);
|
||||||
|
|
||||||
|
// 创建新的加载状态
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
var loadingState = MemoryPool.Acquire<LoadingState>();
|
||||||
|
loadingState.Cts = cts;
|
||||||
|
loadingState.Location = location;
|
||||||
|
_loadingStates[target] = loadingState;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 等待其他可能正在进行的加载。
|
||||||
|
await TryWaitingLoading(location).AttachExternalCancellation(cts.Token);
|
||||||
|
|
||||||
|
// 再次检查是否被新请求替换。
|
||||||
|
if (!IsCurrentLocation(target, location))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查缓存。
|
||||||
|
if (_assetItemPool.CanSpawn(location))
|
||||||
|
{
|
||||||
|
ClearLoadingState(target);
|
||||||
|
|
||||||
|
var assetObject = (T)_assetItemPool.Spawn(location).Target;
|
||||||
SetAsset(setAssetObject, assetObject);
|
SetAsset(setAssetObject, assetObject);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_assetLoadingList.Add(setAssetObject.Location);
|
// 最后一次检查是否被替换。
|
||||||
m_ResourceModule.LoadAssetAsync(setAssetObject.Location, typeof(T), 0, m_LoadAssetCallbacks, setAssetObject);
|
if (!IsCurrentLocation(target, location))
|
||||||
|
{
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 防止重复加载同一资源。
|
||||||
|
if (!_assetLoadingList.Add(location))
|
||||||
|
{
|
||||||
|
// 已经在加载中,等待回调处理。
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_resourceModule.LoadAssetAsync(location, typeof(T), 0, _loadAssetCallbacks, setAssetObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
// 请求被取消,正常情况,无需处理。
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error($"Failed to load asset '{location}': {ex}");
|
||||||
|
ClearLoadingState(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 取消并清理旧的加载请求。
|
||||||
|
/// <param name="target">Unity对象。</param>
|
||||||
|
/// </summary>
|
||||||
|
private void CancelAndCleanupOldRequest(UnityEngine.Object target)
|
||||||
|
{
|
||||||
|
if (_loadingStates.TryGetValue(target, out var oldState))
|
||||||
|
{
|
||||||
|
MemoryPool.Release(oldState);
|
||||||
|
_loadingStates.Remove(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清理加载状态。
|
||||||
|
/// <param name="target">Unity对象。</param>
|
||||||
|
/// </summary>
|
||||||
|
private void ClearLoadingState(UnityEngine.Object target)
|
||||||
|
{
|
||||||
|
if (_loadingStates.TryGetValue(target, out var state))
|
||||||
|
{
|
||||||
|
MemoryPool.Release(state);
|
||||||
|
_loadingStates.Remove(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查指定位置是否仍是该目标的当前加载位置。
|
||||||
|
/// </summary>
|
||||||
|
private bool IsCurrentLocation(UnityEngine.Object target, string location)
|
||||||
|
{
|
||||||
|
if (target == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return _loadingStates.TryGetValue(target, out var state) && state.Location == location;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 组件销毁时清理所有资源。
|
||||||
|
/// </summary>
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
foreach (var state in _loadingStates.Values)
|
||||||
|
{
|
||||||
|
MemoryPool.Release(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
_loadingStates.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,7 +47,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 散图集合对象池
|
/// 散图集合对象池
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private IObjectPool<AssetItemObject> m_AssetItemPool;
|
private IObjectPool<AssetItemObject> _assetItemPool;
|
||||||
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
@ -66,7 +66,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
{
|
{
|
||||||
yield return new WaitForEndOfFrame();
|
yield return new WaitForEndOfFrame();
|
||||||
IObjectPoolModule objectPoolComponent = ModuleSystem.GetModule<IObjectPoolModule>();
|
IObjectPoolModule objectPoolComponent = ModuleSystem.GetModule<IObjectPoolModule>();
|
||||||
m_AssetItemPool = objectPoolComponent.CreateMultiSpawnObjectPool<AssetItemObject>(
|
_assetItemPool = objectPoolComponent.CreateMultiSpawnObjectPool<AssetItemObject>(
|
||||||
"SetAssetPool",
|
"SetAssetPool",
|
||||||
m_AutoReleaseInterval, 16, 60, 0);
|
m_AutoReleaseInterval, 16, 60, 0);
|
||||||
m_LoadAssetObjectsLinkedList = new LinkedList<LoadAssetObject>();
|
m_LoadAssetObjectsLinkedList = new LinkedList<LoadAssetObject>();
|
||||||
@ -105,7 +105,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
var next = current.Next;
|
var next = current.Next;
|
||||||
if (current.Value.AssetObject.IsCanRelease())
|
if (current.Value.AssetObject.IsCanRelease())
|
||||||
{
|
{
|
||||||
m_AssetItemPool.Unspawn(current.Value.AssetTarget);
|
_assetItemPool.Unspawn(current.Value.AssetTarget);
|
||||||
MemoryPool.Release(current.Value.AssetObject);
|
MemoryPool.Release(current.Value.AssetObject);
|
||||||
m_LoadAssetObjectsLinkedList.Remove(current);
|
m_LoadAssetObjectsLinkedList.Remove(current);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user