1
This commit is contained in:
parent
9172d11d84
commit
ad913aceb4
@ -19,5 +19,11 @@ namespace AlicizaX.Resource.Runtime
|
||||
/// 是否可以回收。
|
||||
/// </summary>
|
||||
bool IsCanRelease();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Unity资源对象。
|
||||
/// </summary>
|
||||
public UnityEngine.Object TargetObject { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,6 +39,8 @@ namespace AlicizaX.Resource.Runtime
|
||||
#endif
|
||||
private Sprite _sprite;
|
||||
|
||||
public Object TargetObject { get; set; }
|
||||
|
||||
public string Location { get; private set; }
|
||||
|
||||
private bool _setNativeSize = false;
|
||||
@ -90,6 +92,7 @@ namespace AlicizaX.Resource.Runtime
|
||||
_sprite = null;
|
||||
_setType = SetType.None;
|
||||
_setNativeSize = false;
|
||||
TargetObject = null;
|
||||
}
|
||||
|
||||
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._cancellationToken = cancellationToken;
|
||||
item._setType = SetType.Image;
|
||||
item.TargetObject = image;
|
||||
return item;
|
||||
}
|
||||
|
||||
@ -110,6 +114,7 @@ namespace AlicizaX.Resource.Runtime
|
||||
item.Location = location;
|
||||
item._cancellationToken = cancellationToken;
|
||||
item._setType = SetType.SpriteRender;
|
||||
item.TargetObject = spriteRenderer;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,26 +1,52 @@
|
||||
using AlicizaX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
|
||||
namespace AlicizaX.Resource.Runtime
|
||||
{
|
||||
public partial class ResourceExtComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// 资源组件。
|
||||
/// </summary>
|
||||
private IResourceModule m_ResourceModule;
|
||||
private static IResourceModule _resourceModule;
|
||||
private LoadAssetCallbacks _loadAssetCallbacks;
|
||||
|
||||
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()
|
||||
{
|
||||
m_ResourceModule = ModuleSystem.GetModule<IResourceModule>();
|
||||
m_LoadAssetCallbacks = new LoadAssetCallbacks(OnLoadAssetSuccess, OnLoadAssetFailure);
|
||||
_resourceModule = ModuleSystem.GetModule<IResourceModule>();
|
||||
_loadAssetCallbacks = new LoadAssetCallbacks(OnLoadAssetSuccess, OnLoadAssetFailure);
|
||||
}
|
||||
|
||||
private void OnLoadAssetFailure(string assetName, LoadResourceStatus status, string errormessage, object userdata)
|
||||
{
|
||||
_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);
|
||||
}
|
||||
|
||||
@ -29,35 +55,151 @@ namespace AlicizaX.Resource.Runtime
|
||||
_assetLoadingList.Remove(assetName);
|
||||
ISetAssetObject setAssetObject = (ISetAssetObject)userdata;
|
||||
UnityEngine.Object assetObject = asset as UnityEngine.Object;
|
||||
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 资源已经过期,卸载。
|
||||
_resourceModule.UnloadAsset(assetObject);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error($"Load failure asset type is {asset.GetType()}.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过资源系统设置资源。
|
||||
/// 通过Unity对象加载资源。
|
||||
/// </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
|
||||
{
|
||||
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);
|
||||
}
|
||||
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>
|
||||
private IObjectPool<AssetItemObject> m_AssetItemPool;
|
||||
private IObjectPool<AssetItemObject> _assetItemPool;
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
@ -66,7 +66,7 @@ namespace AlicizaX.Resource.Runtime
|
||||
{
|
||||
yield return new WaitForEndOfFrame();
|
||||
IObjectPoolModule objectPoolComponent = ModuleSystem.GetModule<IObjectPoolModule>();
|
||||
m_AssetItemPool = objectPoolComponent.CreateMultiSpawnObjectPool<AssetItemObject>(
|
||||
_assetItemPool = objectPoolComponent.CreateMultiSpawnObjectPool<AssetItemObject>(
|
||||
"SetAssetPool",
|
||||
m_AutoReleaseInterval, 16, 60, 0);
|
||||
m_LoadAssetObjectsLinkedList = new LinkedList<LoadAssetObject>();
|
||||
@ -105,7 +105,7 @@ namespace AlicizaX.Resource.Runtime
|
||||
var next = current.Next;
|
||||
if (current.Value.AssetObject.IsCanRelease())
|
||||
{
|
||||
m_AssetItemPool.Unspawn(current.Value.AssetTarget);
|
||||
_assetItemPool.Unspawn(current.Value.AssetTarget);
|
||||
MemoryPool.Release(current.Value.AssetObject);
|
||||
m_LoadAssetObjectsLinkedList.Remove(current);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user