[Opt] MemoryPool & ResourceService
This commit is contained in:
parent
d6f36cc9df
commit
4cf5eb57d2
@ -96,6 +96,7 @@ namespace AlicizaX
|
|||||||
RunCase("ClearAll Unschedule", RunClearAllUnschedule);
|
RunCase("ClearAll Unschedule", RunClearAllUnschedule);
|
||||||
RunCase("ClearAll Active Queue Reset", RunClearAllActiveQueueReset);
|
RunCase("ClearAll Active Queue Reset", RunClearAllActiveQueueReset);
|
||||||
RunCase("Type API Cold Path", RunTypeApiColdPath);
|
RunCase("Type API Cold Path", RunTypeApiColdPath);
|
||||||
|
RunCase("Cached Handle Hot Path", RunCachedHandleHotPath);
|
||||||
RunCase("Info Buffer No Alloc", RunInfoBufferNoAlloc);
|
RunCase("Info Buffer No Alloc", RunInfoBufferNoAlloc);
|
||||||
RunCase("Explicit Compact", RunExplicitCompact);
|
RunCase("Explicit Compact", RunExplicitCompact);
|
||||||
}
|
}
|
||||||
@ -628,6 +629,28 @@ namespace AlicizaX
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void RunCachedHandleHotPath()
|
||||||
|
{
|
||||||
|
using (s_ExtremeMarker.Auto())
|
||||||
|
{
|
||||||
|
MemoryPool<BenchmarkMemory>.ClearAll();
|
||||||
|
MemoryPool<BenchmarkMemory>.Prewarm(objectCount);
|
||||||
|
MemoryPoolHandle handle = MemoryPool.GetHandle(typeof(BenchmarkMemory));
|
||||||
|
AssertTrue(handle.IsValid, "cached handle is invalid");
|
||||||
|
|
||||||
|
RestartCaseMeasure();
|
||||||
|
for (int i = 0; i < loopCount; i++)
|
||||||
|
{
|
||||||
|
IMemory item = handle.Acquire();
|
||||||
|
handle.Release(item);
|
||||||
|
}
|
||||||
|
StopCaseMeasure();
|
||||||
|
|
||||||
|
MemoryPool<BenchmarkMemory>.ClearAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void RunInfoBufferNoAlloc()
|
private void RunInfoBufferNoAlloc()
|
||||||
{
|
{
|
||||||
using (s_InfoMarker.Auto())
|
using (s_InfoMarker.Auto())
|
||||||
|
|||||||
@ -53,6 +53,19 @@ namespace AlicizaX
|
|||||||
return MemoryPool<T>.Acquire();
|
return MemoryPool<T>.Acquire();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取动态内存类型的缓存句柄。运行时热路径应提前缓存该句柄,避免反复使用 Type 查找。
|
||||||
|
/// </summary>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static MemoryPoolHandle GetHandle(Type memoryType)
|
||||||
|
{
|
||||||
|
return MemoryPoolRegistry.GetHandle(memoryType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 慢速动态路径。禁止在运行时热路径调用;请提前通过 GetHandle(Type) 缓存 MemoryPoolHandle 后再获取对象。
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("慢速动态路径,禁止在运行时热路径使用。请缓存 MemoryPoolHandle,或改用 MemoryPool<T>.Acquire / MemoryPool.Acquire<T>。", false)]
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static IMemory Acquire(Type memoryType)
|
public static IMemory Acquire(Type memoryType)
|
||||||
{
|
{
|
||||||
@ -66,6 +79,10 @@ namespace AlicizaX
|
|||||||
MemoryPool<T>.Release(memory);
|
MemoryPool<T>.Release(memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 慢速动态路径。禁止在运行时热路径调用;请通过缓存的 MemoryPoolHandle 或 Release<T> 回收对象。
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("慢速动态路径,禁止在运行时热路径使用。请通过缓存的 MemoryPoolHandle,或改用 MemoryPool<T>.Release / MemoryPool.Release<T>。", false)]
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Release(IMemory memory)
|
public static void Release(IMemory memory)
|
||||||
{
|
{
|
||||||
|
|||||||
32
Runtime/MemoryPool/MemoryPoolHandle.cs
Normal file
32
Runtime/MemoryPool/MemoryPoolHandle.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace AlicizaX
|
||||||
|
{
|
||||||
|
public readonly struct MemoryPoolHandle
|
||||||
|
{
|
||||||
|
private readonly MemoryPoolRegistry.MemoryPoolHandle _handle;
|
||||||
|
|
||||||
|
internal MemoryPoolHandle(MemoryPoolRegistry.MemoryPoolHandle handle)
|
||||||
|
{
|
||||||
|
_handle = handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsValid
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get => _handle != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public IMemory Acquire()
|
||||||
|
{
|
||||||
|
return _handle.Acquire();
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Release(IMemory memory)
|
||||||
|
{
|
||||||
|
_handle.Release(memory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Runtime/MemoryPool/MemoryPoolHandle.cs.meta
Normal file
11
Runtime/MemoryPool/MemoryPoolHandle.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2b7195e879c74d7c9d013fa76df5e37c
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -101,6 +101,23 @@ namespace AlicizaX
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static AlicizaX.MemoryPoolHandle GetHandle(Type type)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
throw new ArgumentNullException(nameof(type));
|
||||||
|
|
||||||
|
if (s_Handles.TryGetValue(type, out var handle))
|
||||||
|
return new AlicizaX.MemoryPoolHandle(handle);
|
||||||
|
|
||||||
|
EnsureRegistered(type);
|
||||||
|
|
||||||
|
if (s_Handles.TryGetValue(type, out handle))
|
||||||
|
return new AlicizaX.MemoryPoolHandle(handle);
|
||||||
|
|
||||||
|
throw new Exception($"MemoryPool: Type '{type.FullName}' is not a valid IMemory type.");
|
||||||
|
}
|
||||||
|
|
||||||
public static IMemory Acquire(Type type)
|
public static IMemory Acquire(Type type)
|
||||||
{
|
{
|
||||||
if (type == null)
|
if (type == null)
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
using AlicizaX;
|
using AlicizaX;
|
||||||
|
|
||||||
namespace AlicizaX.Resource.Runtime
|
namespace AlicizaX.Resource.Runtime
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
using AlicizaX.ObjectPool;
|
using AlicizaX.ObjectPool;
|
||||||
using AlicizaX;
|
using AlicizaX;
|
||||||
|
|
||||||
namespace AlicizaX.Resource.Runtime
|
namespace AlicizaX.Resource.Runtime
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
|
|
||||||
using AlicizaX;
|
using AlicizaX;
|
||||||
|
|
||||||
namespace AlicizaX.Resource.Runtime
|
namespace AlicizaX.Resource.Runtime
|
||||||
|
|||||||
@ -1,21 +1,31 @@
|
|||||||
using System;
|
using System;
|
||||||
using UnityEngine;
|
using AlicizaX;
|
||||||
|
|
||||||
|
|
||||||
namespace AlicizaX.Resource.Runtime
|
namespace AlicizaX.Resource.Runtime
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class LoadAssetObject
|
public class LoadAssetObject : IMemory
|
||||||
{
|
{
|
||||||
public ISetAssetObject AssetObject { get; }
|
public ISetAssetObject AssetObject { get; private set; }
|
||||||
public UnityEngine.Object AssetTarget { get; }
|
public UnityEngine.Object AssetTarget { get; private set; }
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
public bool IsSelect { get; set; }
|
public bool IsSelect { get; set; }
|
||||||
#endif
|
#endif
|
||||||
public LoadAssetObject(ISetAssetObject obj, UnityEngine.Object assetTarget)
|
public static LoadAssetObject Create(ISetAssetObject obj, UnityEngine.Object assetTarget)
|
||||||
{
|
{
|
||||||
AssetObject = obj;
|
LoadAssetObject item = MemoryPool.Acquire<LoadAssetObject>();
|
||||||
AssetTarget = assetTarget;
|
item.AssetObject = obj;
|
||||||
|
item.AssetTarget = assetTarget;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
AssetObject = null;
|
||||||
|
AssetTarget = null;
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
IsSelect = false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,11 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: b25c6b1f257bf3445b8e2651e169e314
|
guid: b25c6b1f257bf3445b8e2651e169e314
|
||||||
timeCreated: 1710733596
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using Cysharp.Text;
|
||||||
using Cysharp.Threading.Tasks;
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
namespace AlicizaX.Resource.Runtime
|
namespace AlicizaX.Resource.Runtime
|
||||||
@ -51,7 +51,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
UnityEngine.Object assetObject = asset as UnityEngine.Object;
|
UnityEngine.Object assetObject = asset as UnityEngine.Object;
|
||||||
if (assetObject == null)
|
if (assetObject == null)
|
||||||
{
|
{
|
||||||
Log.Error($"Load failure asset type is {asset?.GetType()}.");
|
Log.Error(ZString.Format("Load failure asset type is {0}.", asset?.GetType()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,22 +78,22 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
|
|
||||||
CancelAndCleanupOldRequest(target);
|
CancelAndCleanupOldRequest(target);
|
||||||
|
|
||||||
var linkedTokenSource = new CancellationTokenSource();
|
|
||||||
var loadingState = MemoryPool.Acquire<LoadingState>();
|
var loadingState = MemoryPool.Acquire<LoadingState>();
|
||||||
loadingState.Cts = linkedTokenSource;
|
CancellationToken loadToken = cancellationToken;
|
||||||
if (cancellationToken.CanBeCanceled)
|
if (cancellationToken.CanBeCanceled)
|
||||||
{
|
{
|
||||||
|
var linkedTokenSource = new CancellationTokenSource();
|
||||||
|
loadingState.Cts = linkedTokenSource;
|
||||||
loadingState.Registration = cancellationToken.Register(static state =>
|
loadingState.Registration = cancellationToken.Register(static state =>
|
||||||
{
|
{
|
||||||
((CancellationTokenSource)state).Cancel();
|
((CancellationTokenSource)state).Cancel();
|
||||||
}, linkedTokenSource);
|
}, linkedTokenSource);
|
||||||
|
loadToken = linkedTokenSource.Token;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadingState.Location = location;
|
loadingState.Location = location;
|
||||||
_loadingStates[target] = loadingState;
|
_loadingStates[target] = loadingState;
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!IsCurrentLocation(target, location))
|
if (!IsCurrentLocation(target, location))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -113,26 +113,15 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
T resource = await _resourceService.LoadAssetAsync<T>(location, linkedTokenSource.Token);
|
var loadResult = await _resourceService.LoadAssetAsync<T>(location, loadToken).SuppressCancellationThrow();
|
||||||
if (resource == null)
|
if (loadResult.IsCanceled || loadResult.Result == null)
|
||||||
{
|
{
|
||||||
ClearLoadingState(target);
|
ClearLoadingState(target);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OnLoadAssetSuccess(location, resource, 0f, setAssetObject);
|
OnLoadAssetSuccess(location, loadResult.Result, 0f, setAssetObject);
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
|
||||||
{
|
|
||||||
ClearLoadingState(target);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Error($"Failed to load asset '{location}': {ex}");
|
|
||||||
ClearLoadingState(target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CancelAndCleanupOldRequest(UnityEngine.Object target)
|
private void CancelAndCleanupOldRequest(UnityEngine.Object target)
|
||||||
{
|
{
|
||||||
if (_loadingStates.TryGetValue(target, out var oldState))
|
if (_loadingStates.TryGetValue(target, out var oldState))
|
||||||
@ -179,9 +168,10 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
UnityEngine.Application.lowMemory -= OnLowMemory;
|
UnityEngine.Application.lowMemory -= OnLowMemory;
|
||||||
ReleaseTrackedAssets();
|
ReleaseTrackedAssets();
|
||||||
|
|
||||||
foreach (var state in _loadingStates.Values)
|
var enumerator = _loadingStates.GetEnumerator();
|
||||||
|
while (enumerator.MoveNext())
|
||||||
{
|
{
|
||||||
MemoryPool.Release(state);
|
MemoryPool.Release(enumerator.Current.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
_loadingStates.Clear();
|
_loadingStates.Clear();
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using Cysharp.Text;
|
||||||
using Cysharp.Threading.Tasks;
|
using Cysharp.Threading.Tasks;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
@ -15,15 +15,60 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
{
|
{
|
||||||
private readonly Dictionary<string, SubAssetsHandle> _subAssetsHandles = new Dictionary<string, SubAssetsHandle>();
|
private readonly Dictionary<string, SubAssetsHandle> _subAssetsHandles = new Dictionary<string, SubAssetsHandle>();
|
||||||
private readonly Dictionary<string, int> _subSpriteReferences = new Dictionary<string, int>();
|
private readonly Dictionary<string, int> _subSpriteReferences = new Dictionary<string, int>();
|
||||||
private readonly Dictionary<string, UniTaskCompletionSource<SubAssetsHandle>> _subAssetLoadingOperations = new Dictionary<string, UniTaskCompletionSource<SubAssetsHandle>>();
|
private readonly Dictionary<string, AutoResetUniTaskCompletionSource<SubAssetsHandle>> _subAssetLoadingOperations = new Dictionary<string, AutoResetUniTaskCompletionSource<SubAssetsHandle>>();
|
||||||
|
private readonly Dictionary<SubSpriteKey, Sprite> _subSpriteCache = new Dictionary<SubSpriteKey, Sprite>(SubSpriteKeyComparer.Instance);
|
||||||
|
|
||||||
|
private readonly struct SubSpriteKey
|
||||||
|
{
|
||||||
|
public readonly string Location;
|
||||||
|
public readonly string SpriteName;
|
||||||
|
|
||||||
|
public SubSpriteKey(string location, string spriteName)
|
||||||
|
{
|
||||||
|
Location = location ?? string.Empty;
|
||||||
|
SpriteName = spriteName ?? string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class SubSpriteKeyComparer : IEqualityComparer<SubSpriteKey>
|
||||||
|
{
|
||||||
|
public static readonly SubSpriteKeyComparer Instance = new SubSpriteKeyComparer();
|
||||||
|
|
||||||
|
private SubSpriteKeyComparer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(SubSpriteKey x, SubSpriteKey y)
|
||||||
|
{
|
||||||
|
return string.Equals(x.Location, y.Location, System.StringComparison.Ordinal) &&
|
||||||
|
string.Equals(x.SpriteName, y.SpriteName, System.StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetHashCode(SubSpriteKey obj)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
int hash = 17;
|
||||||
|
hash = hash * 31 + System.StringComparer.Ordinal.GetHashCode(obj.Location ?? string.Empty);
|
||||||
|
hash = hash * 31 + System.StringComparer.Ordinal.GetHashCode(obj.SpriteName ?? string.Empty);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async UniTask SetSubSprite(Image image, string location, string spriteName, bool setNativeSize = false, CancellationToken cancellationToken = default)
|
public async UniTask SetSubSprite(Image image, string location, string spriteName, bool setNativeSize = false, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var subSprite = await GetSubSpriteImp(location, spriteName, cancellationToken);
|
|
||||||
|
|
||||||
if (image == null)
|
if (image == null)
|
||||||
{
|
{
|
||||||
Log.Warning($"SetSubAssets Image is null");
|
Log.Warning("SetSubAssets Image is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
var subSprite = await GetSubSpriteImp(location, spriteName, cancellationToken);
|
||||||
|
|
||||||
|
if (image == null || cancellationToken.IsCancellationRequested || subSprite == null)
|
||||||
|
{
|
||||||
ReleaseSubAssetsIfUnused(location);
|
ReleaseSubAssetsIfUnused(location);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -39,11 +84,17 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
|
|
||||||
public async UniTask SetSubSprite(SpriteRenderer spriteRenderer, string location, string spriteName, CancellationToken cancellationToken = default)
|
public async UniTask SetSubSprite(SpriteRenderer spriteRenderer, string location, string spriteName, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var subSprite = await GetSubSpriteImp(location, spriteName, cancellationToken);
|
|
||||||
|
|
||||||
if (spriteRenderer == null)
|
if (spriteRenderer == null)
|
||||||
{
|
{
|
||||||
Log.Warning($"SetSubAssets Image is null");
|
Log.Warning("SetSubAssets Image is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
var subSprite = await GetSubSpriteImp(location, spriteName, cancellationToken);
|
||||||
|
|
||||||
|
if (spriteRenderer == null || cancellationToken.IsCancellationRequested || subSprite == null)
|
||||||
|
{
|
||||||
ReleaseSubAssetsIfUnused(location);
|
ReleaseSubAssetsIfUnused(location);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -57,17 +108,28 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
var assetInfo = YooAssets.GetAssetInfo(location);
|
var assetInfo = YooAssets.GetAssetInfo(location);
|
||||||
if (assetInfo.IsInvalid)
|
if (assetInfo.IsInvalid)
|
||||||
{
|
{
|
||||||
throw new GameFrameworkException($"Invalid location: {location}");
|
throw new GameFrameworkException(ZString.Format("Invalid location: {0}", location));
|
||||||
|
}
|
||||||
|
|
||||||
|
SubSpriteKey key = new SubSpriteKey(location, spriteName);
|
||||||
|
if (_subSpriteCache.TryGetValue(key, out Sprite cachedSprite))
|
||||||
|
{
|
||||||
|
return cachedSprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
var subAssetsHandle = await GetOrLoadSubAssetsHandleAsync(location, cancellationToken);
|
var subAssetsHandle = await GetOrLoadSubAssetsHandleAsync(location, cancellationToken);
|
||||||
|
if (!subAssetsHandle.IsValid)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var subSprite = subAssetsHandle.GetSubAssetObject<Sprite>(spriteName);
|
var subSprite = subAssetsHandle.GetSubAssetObject<Sprite>(spriteName);
|
||||||
if (subSprite == null)
|
if (subSprite == null)
|
||||||
{
|
{
|
||||||
throw new GameFrameworkException($"Invalid sprite name: {spriteName}");
|
throw new GameFrameworkException(ZString.Format("Invalid sprite name: {0}", spriteName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_subSpriteCache[key] = subSprite;
|
||||||
return subSprite;
|
return subSprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +166,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
{
|
{
|
||||||
subAssetsHandle.Dispose();
|
subAssetsHandle.Dispose();
|
||||||
_subAssetsHandles.Remove(location);
|
_subAssetsHandles.Remove(location);
|
||||||
|
ClearSubSpriteCache(location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,29 +193,57 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var completionSource = new UniTaskCompletionSource<SubAssetsHandle>();
|
var completionSource = AutoResetUniTaskCompletionSource<SubAssetsHandle>.Create();
|
||||||
_subAssetLoadingOperations.Add(location, completionSource);
|
_subAssetLoadingOperations.Add(location, completionSource);
|
||||||
|
|
||||||
SubAssetsHandle subAssetsHandle = default;
|
SubAssetsHandle subAssetsHandle = YooAssets.LoadSubAssetsAsync<Sprite>(location);
|
||||||
try
|
while (subAssetsHandle is { IsValid: true, IsDone: false })
|
||||||
{
|
{
|
||||||
subAssetsHandle = YooAssets.LoadSubAssetsAsync<Sprite>(location);
|
if (cancellationToken.IsCancellationRequested)
|
||||||
await subAssetsHandle.ToUniTask();
|
{
|
||||||
|
DisposeSubAssetsHandle(subAssetsHandle);
|
||||||
|
CompleteSubAssetLoading(location, completionSource, default);
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
await UniTask.Yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!subAssetsHandle.IsValid || subAssetsHandle.Status == EOperationStatus.Failed)
|
||||||
|
{
|
||||||
|
DisposeSubAssetsHandle(subAssetsHandle);
|
||||||
|
CompleteSubAssetLoading(location, completionSource, default);
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
_subAssetsHandles[location] = subAssetsHandle;
|
_subAssetsHandles[location] = subAssetsHandle;
|
||||||
completionSource.TrySetResult(subAssetsHandle);
|
CompleteSubAssetLoading(location, completionSource, subAssetsHandle);
|
||||||
return subAssetsHandle;
|
return subAssetsHandle;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
subAssetsHandle?.Dispose();
|
|
||||||
completionSource.TrySetException(ex);
|
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
|
private void CompleteSubAssetLoading(string location, AutoResetUniTaskCompletionSource<SubAssetsHandle> completionSource, SubAssetsHandle subAssetsHandle)
|
||||||
{
|
{
|
||||||
_subAssetLoadingOperations.Remove(location);
|
_subAssetLoadingOperations.Remove(location);
|
||||||
|
completionSource.TrySetResult(subAssetsHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DisposeSubAssetsHandle(SubAssetsHandle subAssetsHandle)
|
||||||
|
{
|
||||||
|
if (subAssetsHandle.IsValid)
|
||||||
|
{
|
||||||
|
subAssetsHandle.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ClearSubSpriteCache(string location)
|
||||||
|
{
|
||||||
|
if (_subSpriteCache.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_subSpriteCache.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReleaseSubAssetsIfUnused(string location)
|
private void ReleaseSubAssetsIfUnused(string location)
|
||||||
@ -171,6 +262,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
{
|
{
|
||||||
subAssetsHandle.Dispose();
|
subAssetsHandle.Dispose();
|
||||||
_subAssetsHandles.Remove(location);
|
_subAssetsHandles.Remove(location);
|
||||||
|
ClearSubSpriteCache(location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using AlicizaX.ObjectPool;
|
using AlicizaX.ObjectPool;
|
||||||
using Cysharp.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Serialization;
|
|
||||||
using Object = UnityEngine.Object;
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
namespace AlicizaX.Resource.Runtime
|
namespace AlicizaX.Resource.Runtime
|
||||||
@ -17,54 +15,27 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
{
|
{
|
||||||
public static ResourceExtComponent Instance { private set; get; }
|
public static ResourceExtComponent Instance { private set; get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 检查是否可以释放间隔。
|
|
||||||
/// </summary>
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private float checkCanReleaseInterval = 30f;
|
private float checkCanReleaseInterval = 30f;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 对象池自动释放时间间隔。
|
|
||||||
/// </summary>
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private float autoReleaseInterval = 60f;
|
private float autoReleaseInterval = 60f;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 每帧最大处理资源数量,用于分帧处理避免卡顿。
|
|
||||||
/// </summary>
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private int maxProcessPerFrame = 50;
|
private int maxProcessPerFrame = 50;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private int releaseCheckThreshold = 16;
|
private int releaseCheckThreshold = 16;
|
||||||
|
|
||||||
/// <summary>
|
private LoadAssetObject[] _loadAssetObjects;
|
||||||
/// 当前正在处理的节点,用于分帧处理。
|
private int _loadAssetObjectCount;
|
||||||
/// </summary>
|
private int _currentProcessIndex;
|
||||||
private LinkedListNode<LoadAssetObject> _currentProcessNode;
|
private Dictionary<Object, int> _trackedAssetIndices;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 保存加载的图片对象。
|
|
||||||
/// </summary>
|
|
||||||
private LinkedList<LoadAssetObject> _loadAssetObjectsLinkedList;
|
|
||||||
|
|
||||||
private Dictionary<Object, LinkedListNode<LoadAssetObject>> _trackedAssetNodes;
|
|
||||||
private bool _releaseRequested;
|
private bool _releaseRequested;
|
||||||
private float _nextReleaseCheckTime = float.MaxValue;
|
private float _nextReleaseCheckTime = float.MaxValue;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 散图集合对象池。
|
|
||||||
/// </summary>
|
|
||||||
private IObjectPool<AssetItemObject> _assetItemPool;
|
private IObjectPool<AssetItemObject> _assetItemPool;
|
||||||
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
public LinkedList<LoadAssetObject> LoadAssetObjectsLinkedList
|
|
||||||
{
|
|
||||||
get => _loadAssetObjectsLinkedList;
|
|
||||||
set => _loadAssetObjectsLinkedList = value;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
private IEnumerator Start()
|
private IEnumerator Start()
|
||||||
{
|
{
|
||||||
Instance = this;
|
Instance = this;
|
||||||
@ -80,8 +51,8 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
capacity: 16,
|
capacity: 16,
|
||||||
expireTime: 60,
|
expireTime: 60,
|
||||||
priority: 0));
|
priority: 0));
|
||||||
_loadAssetObjectsLinkedList = new LinkedList<LoadAssetObject>();
|
_loadAssetObjects = new LoadAssetObject[16];
|
||||||
_trackedAssetNodes = new Dictionary<Object, LinkedListNode<LoadAssetObject>>(16);
|
_trackedAssetIndices = new Dictionary<Object, int>(16);
|
||||||
|
|
||||||
InitializedResources();
|
InitializedResources();
|
||||||
}
|
}
|
||||||
@ -102,50 +73,36 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
ReleaseUnused();
|
ReleaseUnused();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 回收无引用的缓存资产。
|
|
||||||
/// 使用分帧处理优化性能,避免一次性处理大量资源导致卡顿。
|
|
||||||
/// </summary>
|
|
||||||
public void ReleaseUnused()
|
public void ReleaseUnused()
|
||||||
{
|
{
|
||||||
if (_loadAssetObjectsLinkedList == null || _loadAssetObjectsLinkedList.Count == 0)
|
if (_loadAssetObjectCount == 0)
|
||||||
{
|
{
|
||||||
_currentProcessNode = null;
|
_currentProcessIndex = 0;
|
||||||
_releaseRequested = false;
|
_releaseRequested = false;
|
||||||
_nextReleaseCheckTime = float.MaxValue;
|
_nextReleaseCheckTime = float.MaxValue;
|
||||||
enabled = false;
|
enabled = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果当前没有正在处理的节点,从头开始
|
|
||||||
if (_currentProcessNode == null)
|
|
||||||
{
|
|
||||||
_currentProcessNode = _loadAssetObjectsLinkedList.First;
|
|
||||||
}
|
|
||||||
|
|
||||||
int processedCount = 0;
|
int processedCount = 0;
|
||||||
LinkedListNode<LoadAssetObject> current = _currentProcessNode;
|
while (_currentProcessIndex < _loadAssetObjectCount && processedCount < maxProcessPerFrame)
|
||||||
|
|
||||||
// 分帧处理:每帧最多处理 maxProcessPerFrame 个资源
|
|
||||||
while (current != null && processedCount < maxProcessPerFrame)
|
|
||||||
{
|
{
|
||||||
var next = current.Next;
|
LoadAssetObject item = _loadAssetObjects[_currentProcessIndex];
|
||||||
|
if (item.AssetObject.IsCanRelease())
|
||||||
if (current.Value.AssetObject.IsCanRelease())
|
|
||||||
{
|
{
|
||||||
RemoveTrackedNode(current, releaseAsset: true);
|
RemoveTrackedAt(_currentProcessIndex, releaseAsset: true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_currentProcessIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
current = next;
|
|
||||||
processedCount++;
|
processedCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新当前处理节点
|
if (_currentProcessIndex >= _loadAssetObjectCount)
|
||||||
_currentProcessNode = current;
|
|
||||||
|
|
||||||
// 如果已经处理完所有节点,重置状态
|
|
||||||
if (_currentProcessNode == null)
|
|
||||||
{
|
{
|
||||||
|
_currentProcessIndex = 0;
|
||||||
_releaseRequested = false;
|
_releaseRequested = false;
|
||||||
_nextReleaseCheckTime = float.MaxValue;
|
_nextReleaseCheckTime = float.MaxValue;
|
||||||
enabled = false;
|
enabled = false;
|
||||||
@ -159,15 +116,17 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
private void SetAsset(ISetAssetObject setAssetObject, Object assetObject)
|
private void SetAsset(ISetAssetObject setAssetObject, Object assetObject)
|
||||||
{
|
{
|
||||||
ReplaceTrackedAsset(setAssetObject.TargetObject);
|
ReplaceTrackedAsset(setAssetObject.TargetObject);
|
||||||
|
EnsureTrackedCapacity(_loadAssetObjectCount + 1);
|
||||||
|
|
||||||
var node = _loadAssetObjectsLinkedList.AddLast(new LoadAssetObject(setAssetObject, assetObject));
|
int index = _loadAssetObjectCount++;
|
||||||
|
_loadAssetObjects[index] = LoadAssetObject.Create(setAssetObject, assetObject);
|
||||||
if (setAssetObject.TargetObject != null)
|
if (setAssetObject.TargetObject != null)
|
||||||
{
|
{
|
||||||
_trackedAssetNodes[setAssetObject.TargetObject] = node;
|
_trackedAssetIndices[setAssetObject.TargetObject] = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
setAssetObject.SetAsset(assetObject);
|
setAssetObject.SetAsset(assetObject);
|
||||||
if (_loadAssetObjectsLinkedList.Count >= releaseCheckThreshold)
|
if (_loadAssetObjectCount >= releaseCheckThreshold)
|
||||||
{
|
{
|
||||||
ScheduleReleaseSweep();
|
ScheduleReleaseSweep();
|
||||||
}
|
}
|
||||||
@ -175,73 +134,105 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
|
|
||||||
private void ReplaceTrackedAsset(Object target)
|
private void ReplaceTrackedAsset(Object target)
|
||||||
{
|
{
|
||||||
if (target == null || _trackedAssetNodes == null)
|
if (target == null || _trackedAssetIndices == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_trackedAssetNodes.TryGetValue(target, out var existingNode))
|
if (_trackedAssetIndices.TryGetValue(target, out int existingIndex))
|
||||||
{
|
{
|
||||||
if (_currentProcessNode == existingNode)
|
RemoveTrackedAt(existingIndex, releaseAsset: true);
|
||||||
{
|
|
||||||
_currentProcessNode = existingNode.Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoveTrackedNode(existingNode, releaseAsset: true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveTrackedNode(LinkedListNode<LoadAssetObject> node, bool releaseAsset)
|
private void RemoveTrackedAt(int index, bool releaseAsset)
|
||||||
{
|
{
|
||||||
if (node == null)
|
if (index < 0 || index >= _loadAssetObjectCount)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var trackedObject = node.Value.AssetObject?.TargetObject;
|
LoadAssetObject item = _loadAssetObjects[index];
|
||||||
if (trackedObject != null && _trackedAssetNodes != null)
|
var trackedObject = item.AssetObject?.TargetObject;
|
||||||
|
if (trackedObject != null && _trackedAssetIndices != null)
|
||||||
{
|
{
|
||||||
_trackedAssetNodes.Remove(trackedObject);
|
_trackedAssetIndices.Remove(trackedObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (releaseAsset && node.Value.AssetTarget != null)
|
if (releaseAsset && item.AssetTarget != null)
|
||||||
{
|
{
|
||||||
_resourceService?.UnloadAsset(node.Value.AssetTarget);
|
_resourceService?.UnloadAsset(item.AssetTarget);
|
||||||
_assetItemPool?.Unspawn(node.Value.AssetTarget);
|
_assetItemPool?.Unspawn(item.AssetTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.Value.AssetObject != null)
|
if (item.AssetObject != null)
|
||||||
{
|
{
|
||||||
MemoryPool.Release(node.Value.AssetObject);
|
ReleaseSetAssetObject(item.AssetObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
_loadAssetObjectsLinkedList?.Remove(node);
|
MemoryPool.Release(item);
|
||||||
if (_loadAssetObjectsLinkedList != null && _loadAssetObjectsLinkedList.Count > 0)
|
|
||||||
|
int lastIndex = _loadAssetObjectCount - 1;
|
||||||
|
if (index != lastIndex)
|
||||||
|
{
|
||||||
|
LoadAssetObject lastItem = _loadAssetObjects[lastIndex];
|
||||||
|
_loadAssetObjects[index] = lastItem;
|
||||||
|
Object movedTarget = lastItem.AssetObject?.TargetObject;
|
||||||
|
if (movedTarget != null && _trackedAssetIndices != null)
|
||||||
|
{
|
||||||
|
_trackedAssetIndices[movedTarget] = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_loadAssetObjects[lastIndex] = null;
|
||||||
|
_loadAssetObjectCount = lastIndex;
|
||||||
|
if (_currentProcessIndex > index)
|
||||||
|
{
|
||||||
|
_currentProcessIndex--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_loadAssetObjectCount > 0)
|
||||||
{
|
{
|
||||||
ScheduleReleaseSweep(checkCanReleaseInterval);
|
ScheduleReleaseSweep(checkCanReleaseInterval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void ReleaseSetAssetObject(ISetAssetObject assetObject)
|
||||||
|
{
|
||||||
|
if (assetObject is SetSpriteObject setSpriteObject)
|
||||||
|
{
|
||||||
|
MemoryPool.Release(setSpriteObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
private void ReleaseTrackedAssets()
|
private void ReleaseTrackedAssets()
|
||||||
{
|
{
|
||||||
if (_loadAssetObjectsLinkedList == null)
|
for (int i = _loadAssetObjectCount - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
RemoveTrackedAt(i, releaseAsset: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
_currentProcessIndex = 0;
|
||||||
|
_trackedAssetIndices?.Clear();
|
||||||
|
_releaseRequested = false;
|
||||||
|
_nextReleaseCheckTime = float.MaxValue;
|
||||||
|
enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnsureTrackedCapacity(int capacity)
|
||||||
|
{
|
||||||
|
if (_loadAssetObjects.Length >= capacity)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var current = _loadAssetObjectsLinkedList.First;
|
int newCapacity = _loadAssetObjects.Length << 1;
|
||||||
while (current != null)
|
while (newCapacity < capacity)
|
||||||
{
|
{
|
||||||
var next = current.Next;
|
newCapacity <<= 1;
|
||||||
RemoveTrackedNode(current, releaseAsset: true);
|
|
||||||
current = next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentProcessNode = null;
|
Array.Resize(ref _loadAssetObjects, newCapacity);
|
||||||
_trackedAssetNodes?.Clear();
|
|
||||||
_releaseRequested = false;
|
|
||||||
_nextReleaseCheckTime = float.MaxValue;
|
|
||||||
enabled = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ScheduleReleaseSweep(float delay = 0f)
|
private void ScheduleReleaseSweep(float delay = 0f)
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Object = UnityEngine.Object;
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
@ -26,10 +25,12 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
private GameObject sourceGameObject;
|
private GameObject sourceGameObject;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private List<AssetsRefInfo> refAssetInfoList;
|
private AssetsRefInfo[] refAssetInfoArray;
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
private int refAssetInfoCount;
|
||||||
|
|
||||||
private static IResourceService _resourceService;
|
private static IResourceService _resourceService;
|
||||||
private HashSet<int> _refAssetIds;
|
|
||||||
|
|
||||||
private bool TryEnsureResourceModule()
|
private bool TryEnsureResourceModule()
|
||||||
{
|
{
|
||||||
@ -51,26 +52,19 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnsureReferenceCache()
|
private bool ContainsRefAsset(int instanceId)
|
||||||
{
|
{
|
||||||
if (_refAssetIds != null)
|
for (int i = 0; i < refAssetInfoCount; i++)
|
||||||
{
|
{
|
||||||
return;
|
AssetsRefInfo refInfo = refAssetInfoArray[i];
|
||||||
|
int refInstanceId = refInfo.instanceId != 0 ? refInfo.instanceId : refInfo.refAsset != null ? refInfo.refAsset.GetInstanceID() : 0;
|
||||||
|
if (refInstanceId == instanceId)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_refAssetIds = new HashSet<int>();
|
return false;
|
||||||
if (refAssetInfoList == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var refInfo in refAssetInfoList)
|
|
||||||
{
|
|
||||||
if (refInfo.refAsset != null)
|
|
||||||
{
|
|
||||||
_refAssetIds.Add(refInfo.instanceId != 0 ? refInfo.instanceId : refInfo.refAsset.GetInstanceID());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDestroy()
|
private void OnDestroy()
|
||||||
@ -78,40 +72,60 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
if (!TryEnsureResourceModule())
|
if (!TryEnsureResourceModule())
|
||||||
{
|
{
|
||||||
sourceGameObject = null;
|
sourceGameObject = null;
|
||||||
refAssetInfoList?.Clear();
|
ClearRefAssetInfoArray();
|
||||||
_refAssetIds?.Clear();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReleaseSourceReference();
|
ReleaseSourceReference();
|
||||||
ReleaseRefAssetInfoList();
|
ReleaseRefAssetInfoArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReleaseRefAssetInfoList()
|
private void ReleaseRefAssetInfoArray()
|
||||||
{
|
{
|
||||||
if (refAssetInfoList != null)
|
for (int i = 0; i < refAssetInfoCount; i++)
|
||||||
{
|
{
|
||||||
foreach (var refInfo in refAssetInfoList)
|
_resourceService.UnloadAsset(refAssetInfoArray[i].refAsset);
|
||||||
{
|
|
||||||
_resourceService.UnloadAsset(refInfo.refAsset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
refAssetInfoList.Clear();
|
ClearRefAssetInfoArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
_refAssetIds?.Clear();
|
private void ClearRefAssetInfoArray()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < refAssetInfoCount; i++)
|
||||||
|
{
|
||||||
|
refAssetInfoArray[i] = default;
|
||||||
|
}
|
||||||
|
|
||||||
|
refAssetInfoCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnsureRefAssetCapacity(int capacity)
|
||||||
|
{
|
||||||
|
if (refAssetInfoArray != null && refAssetInfoArray.Length >= capacity)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int newCapacity = refAssetInfoArray == null || refAssetInfoArray.Length == 0 ? 4 : refAssetInfoArray.Length << 1;
|
||||||
|
while (newCapacity < capacity)
|
||||||
|
{
|
||||||
|
newCapacity <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Array.Resize(ref refAssetInfoArray, newCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AssetsReference Ref(GameObject source, IResourceService resourceService = null)
|
public AssetsReference Ref(GameObject source, IResourceService resourceService = null)
|
||||||
{
|
{
|
||||||
if (source == null)
|
if (source == null)
|
||||||
{
|
{
|
||||||
throw new GameFrameworkException($"Source gameObject is null.");
|
throw new GameFrameworkException("Source gameObject is null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source.scene.name != null)
|
if (source.scene.name != null)
|
||||||
{
|
{
|
||||||
throw new GameFrameworkException($"Source gameObject is in scene.");
|
throw new GameFrameworkException("Source gameObject is in scene.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resourceService != null)
|
if (resourceService != null)
|
||||||
@ -132,7 +146,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
{
|
{
|
||||||
if (source == null)
|
if (source == null)
|
||||||
{
|
{
|
||||||
throw new GameFrameworkException($"Source gameObject is null.");
|
throw new GameFrameworkException("Source gameObject is null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resourceService != null)
|
if (resourceService != null)
|
||||||
@ -140,19 +154,14 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
_resourceService = resourceService;
|
_resourceService = resourceService;
|
||||||
}
|
}
|
||||||
|
|
||||||
EnsureReferenceCache();
|
|
||||||
int instanceId = source.GetInstanceID();
|
int instanceId = source.GetInstanceID();
|
||||||
if (!_refAssetIds.Add(instanceId))
|
if (ContainsRefAsset(instanceId))
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (refAssetInfoList == null)
|
EnsureRefAssetCapacity(refAssetInfoCount + 1);
|
||||||
{
|
refAssetInfoArray[refAssetInfoCount++] = new AssetsRefInfo(source);
|
||||||
refAssetInfoList = new List<AssetsRefInfo>();
|
|
||||||
}
|
|
||||||
|
|
||||||
refAssetInfoList.Add(new AssetsRefInfo(source));
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,12 +169,12 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
{
|
{
|
||||||
if (source == null)
|
if (source == null)
|
||||||
{
|
{
|
||||||
throw new GameFrameworkException($"Source gameObject is null.");
|
throw new GameFrameworkException("Source gameObject is null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source.scene.name != null)
|
if (source.scene.name != null)
|
||||||
{
|
{
|
||||||
throw new GameFrameworkException($"Source gameObject is in scene.");
|
throw new GameFrameworkException("Source gameObject is in scene.");
|
||||||
}
|
}
|
||||||
|
|
||||||
GameObject instance = Object.Instantiate(source, parent);
|
GameObject instance = Object.Instantiate(source, parent);
|
||||||
@ -176,12 +185,12 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
{
|
{
|
||||||
if (source == null)
|
if (source == null)
|
||||||
{
|
{
|
||||||
throw new GameFrameworkException($"Source gameObject is null.");
|
throw new GameFrameworkException("Source gameObject is null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source.scene.name != null)
|
if (source.scene.name != null)
|
||||||
{
|
{
|
||||||
throw new GameFrameworkException($"Source gameObject is in scene.");
|
throw new GameFrameworkException("Source gameObject is in scene.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var comp = instance.GetComponent<AssetsReference>();
|
var comp = instance.GetComponent<AssetsReference>();
|
||||||
@ -192,7 +201,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
{
|
{
|
||||||
if (source == null)
|
if (source == null)
|
||||||
{
|
{
|
||||||
throw new GameFrameworkException($"Source gameObject is null.");
|
throw new GameFrameworkException("Source gameObject is null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var comp = instance.GetComponent<AssetsReference>();
|
var comp = instance.GetComponent<AssetsReference>();
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using AlicizaX;
|
using AlicizaX;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
@ -6,6 +7,140 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
{
|
{
|
||||||
public static class AssetsSetHelper
|
public static class AssetsSetHelper
|
||||||
{
|
{
|
||||||
|
private enum MaterialTargetType
|
||||||
|
{
|
||||||
|
Image,
|
||||||
|
SpriteRenderer,
|
||||||
|
MeshRenderer,
|
||||||
|
MeshRendererShared,
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class MaterialSetRequest : IMemory
|
||||||
|
{
|
||||||
|
public MaterialTargetType TargetType;
|
||||||
|
public Image Image;
|
||||||
|
public SpriteRenderer SpriteRenderer;
|
||||||
|
public MeshRenderer MeshRenderer;
|
||||||
|
public bool NeedInstance;
|
||||||
|
|
||||||
|
public static MaterialSetRequest Create(Image image)
|
||||||
|
{
|
||||||
|
MaterialSetRequest request = MemoryPool.Acquire<MaterialSetRequest>();
|
||||||
|
request.TargetType = MaterialTargetType.Image;
|
||||||
|
request.Image = image;
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MaterialSetRequest Create(SpriteRenderer spriteRenderer)
|
||||||
|
{
|
||||||
|
MaterialSetRequest request = MemoryPool.Acquire<MaterialSetRequest>();
|
||||||
|
request.TargetType = MaterialTargetType.SpriteRenderer;
|
||||||
|
request.SpriteRenderer = spriteRenderer;
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MaterialSetRequest Create(MeshRenderer meshRenderer, bool needInstance, bool sharedMaterial)
|
||||||
|
{
|
||||||
|
MaterialSetRequest request = MemoryPool.Acquire<MaterialSetRequest>();
|
||||||
|
request.TargetType = sharedMaterial ? MaterialTargetType.MeshRendererShared : MaterialTargetType.MeshRenderer;
|
||||||
|
request.MeshRenderer = meshRenderer;
|
||||||
|
request.NeedInstance = needInstance;
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Apply(Material material)
|
||||||
|
{
|
||||||
|
if (material == null)
|
||||||
|
{
|
||||||
|
MemoryPool.Release(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (TargetType)
|
||||||
|
{
|
||||||
|
case MaterialTargetType.Image:
|
||||||
|
{
|
||||||
|
if (Image == null || Image.gameObject == null)
|
||||||
|
{
|
||||||
|
_resourceService.UnloadAsset(material);
|
||||||
|
MemoryPool.Release(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image.material = material;
|
||||||
|
AssetsReference.Ref(material, Image.gameObject);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MaterialTargetType.SpriteRenderer:
|
||||||
|
{
|
||||||
|
if (SpriteRenderer == null || SpriteRenderer.gameObject == null)
|
||||||
|
{
|
||||||
|
_resourceService.UnloadAsset(material);
|
||||||
|
MemoryPool.Release(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpriteRenderer.material = material;
|
||||||
|
AssetsReference.Ref(material, SpriteRenderer.gameObject);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MaterialTargetType.MeshRenderer:
|
||||||
|
{
|
||||||
|
if (MeshRenderer == null || MeshRenderer.gameObject == null)
|
||||||
|
{
|
||||||
|
_resourceService.UnloadAsset(material);
|
||||||
|
MemoryPool.Release(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetMeshMaterial(MeshRenderer, material, NeedInstance);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MaterialTargetType.MeshRendererShared:
|
||||||
|
{
|
||||||
|
if (MeshRenderer == null || MeshRenderer.gameObject == null)
|
||||||
|
{
|
||||||
|
_resourceService.UnloadAsset(material);
|
||||||
|
MemoryPool.Release(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MeshRenderer.sharedMaterial = material;
|
||||||
|
AssetsReference.Ref(material, MeshRenderer.gameObject);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryPool.Release(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
TargetType = MaterialTargetType.Image;
|
||||||
|
Image = null;
|
||||||
|
SpriteRenderer = null;
|
||||||
|
MeshRenderer = null;
|
||||||
|
NeedInstance = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class MaterialLoadCallbacks
|
||||||
|
{
|
||||||
|
public static readonly LoadAssetCallbacks Instance = new LoadAssetCallbacks(OnSuccess, OnFailure);
|
||||||
|
|
||||||
|
private static void OnSuccess(string assetName, object asset, float duration, object userData)
|
||||||
|
{
|
||||||
|
MaterialSetRequest request = (MaterialSetRequest)userData;
|
||||||
|
request.Apply(asset as Material);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnFailure(string assetName, LoadResourceStatus status, string errorMessage, object userData)
|
||||||
|
{
|
||||||
|
MaterialSetRequest request = (MaterialSetRequest)userData;
|
||||||
|
MemoryPool.Release(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static IResourceService _resourceService;
|
private static IResourceService _resourceService;
|
||||||
|
|
||||||
private static void CheckResourceManager()
|
private static void CheckResourceManager()
|
||||||
@ -16,13 +151,39 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void LoadMaterialAsync(string location, string packageName, MaterialSetRequest request)
|
||||||
|
{
|
||||||
|
_resourceService.LoadAssetAsync(location, typeof(Material), 0, MaterialLoadCallbacks.Instance, request, packageName).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetMeshMaterial(MeshRenderer meshRenderer, Material material, bool needInstance)
|
||||||
|
{
|
||||||
|
if (!needInstance)
|
||||||
|
{
|
||||||
|
meshRenderer.material = material;
|
||||||
|
AssetsReference.Ref(material, meshRenderer.gameObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Material instance = Object.Instantiate(material);
|
||||||
|
meshRenderer.material = instance;
|
||||||
|
AssetsReference.Ref(material, meshRenderer.gameObject);
|
||||||
|
var reference = meshRenderer.GetComponent<MaterialInstanceReference>();
|
||||||
|
if (reference == null)
|
||||||
|
{
|
||||||
|
reference = meshRenderer.gameObject.AddComponent<MaterialInstanceReference>();
|
||||||
|
}
|
||||||
|
|
||||||
|
reference.Set(instance);
|
||||||
|
}
|
||||||
|
|
||||||
#region SetMaterial
|
#region SetMaterial
|
||||||
|
|
||||||
public static void SetMaterial(this Image image, string location, bool isAsync = false, string packageName = "")
|
public static void SetMaterial(this Image image, string location, bool isAsync = false, string packageName = "")
|
||||||
{
|
{
|
||||||
if (image == null)
|
if (image == null)
|
||||||
{
|
{
|
||||||
throw new GameFrameworkException($"SetSprite failed. Because image is null.");
|
throw new GameFrameworkException("SetSprite failed. Because image is null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckResourceManager();
|
CheckResourceManager();
|
||||||
@ -32,29 +193,17 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
Material material = _resourceService.LoadAsset<Material>(location, packageName);
|
Material material = _resourceService.LoadAsset<Material>(location, packageName);
|
||||||
image.material = material;
|
image.material = material;
|
||||||
AssetsReference.Ref(material, image.gameObject);
|
AssetsReference.Ref(material, image.gameObject);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_resourceService.LoadAsset<Material>(location, material =>
|
|
||||||
{
|
|
||||||
if (image == null || image.gameObject == null)
|
|
||||||
{
|
|
||||||
_resourceService.UnloadAsset(material);
|
|
||||||
material = null;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
image.material = material;
|
LoadMaterialAsync(location, packageName, MaterialSetRequest.Create(image));
|
||||||
AssetsReference.Ref(material, image.gameObject);
|
|
||||||
}, packageName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetMaterial(this SpriteRenderer spriteRenderer, string location, bool isAsync = false, string packageName = "")
|
public static void SetMaterial(this SpriteRenderer spriteRenderer, string location, bool isAsync = false, string packageName = "")
|
||||||
{
|
{
|
||||||
if (spriteRenderer == null)
|
if (spriteRenderer == null)
|
||||||
{
|
{
|
||||||
throw new GameFrameworkException($"SetSprite failed. Because image is null.");
|
throw new GameFrameworkException("SetSprite failed. Because image is null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckResourceManager();
|
CheckResourceManager();
|
||||||
@ -64,29 +213,17 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
Material material = _resourceService.LoadAsset<Material>(location, packageName);
|
Material material = _resourceService.LoadAsset<Material>(location, packageName);
|
||||||
spriteRenderer.material = material;
|
spriteRenderer.material = material;
|
||||||
AssetsReference.Ref(material, spriteRenderer.gameObject);
|
AssetsReference.Ref(material, spriteRenderer.gameObject);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_resourceService.LoadAsset<Material>(location, material =>
|
|
||||||
{
|
|
||||||
if (spriteRenderer == null || spriteRenderer.gameObject == null)
|
|
||||||
{
|
|
||||||
_resourceService.UnloadAsset(material);
|
|
||||||
material = null;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
spriteRenderer.material = material;
|
LoadMaterialAsync(location, packageName, MaterialSetRequest.Create(spriteRenderer));
|
||||||
AssetsReference.Ref(material, spriteRenderer.gameObject);
|
|
||||||
}, packageName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetMaterial(this MeshRenderer meshRenderer, string location, bool needInstance = true, bool isAsync = false, string packageName = "")
|
public static void SetMaterial(this MeshRenderer meshRenderer, string location, bool needInstance = true, bool isAsync = false, string packageName = "")
|
||||||
{
|
{
|
||||||
if (meshRenderer == null)
|
if (meshRenderer == null)
|
||||||
{
|
{
|
||||||
throw new GameFrameworkException($"SetSprite failed. Because image is null.");
|
throw new GameFrameworkException("SetSprite failed. Because image is null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckResourceManager();
|
CheckResourceManager();
|
||||||
@ -94,31 +231,18 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
if (!isAsync)
|
if (!isAsync)
|
||||||
{
|
{
|
||||||
Material material = _resourceService.LoadAsset<Material>(location, packageName);
|
Material material = _resourceService.LoadAsset<Material>(location, packageName);
|
||||||
meshRenderer.material = needInstance ? Object.Instantiate(material) : material;
|
SetMeshMaterial(meshRenderer, material, needInstance);
|
||||||
AssetsReference.Ref(material, meshRenderer.gameObject);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_resourceService.LoadAsset<Material>(location, material =>
|
|
||||||
{
|
|
||||||
if (meshRenderer == null || meshRenderer.gameObject == null)
|
|
||||||
{
|
|
||||||
_resourceService.UnloadAsset(material);
|
|
||||||
material = null;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
meshRenderer.material = needInstance ? Object.Instantiate(material) : material;
|
LoadMaterialAsync(location, packageName, MaterialSetRequest.Create(meshRenderer, needInstance, false));
|
||||||
AssetsReference.Ref(material, meshRenderer.gameObject);
|
|
||||||
}, packageName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetSharedMaterial(this MeshRenderer meshRenderer, string location, bool isAsync = false, string packageName = "")
|
public static void SetSharedMaterial(this MeshRenderer meshRenderer, string location, bool isAsync = false, string packageName = "")
|
||||||
{
|
{
|
||||||
if (meshRenderer == null)
|
if (meshRenderer == null)
|
||||||
{
|
{
|
||||||
throw new GameFrameworkException($"SetSprite failed. Because image is null.");
|
throw new GameFrameworkException("SetSprite failed. Because image is null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckResourceManager();
|
CheckResourceManager();
|
||||||
@ -128,22 +252,10 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
Material material = _resourceService.LoadAsset<Material>(location, packageName);
|
Material material = _resourceService.LoadAsset<Material>(location, packageName);
|
||||||
meshRenderer.sharedMaterial = material;
|
meshRenderer.sharedMaterial = material;
|
||||||
AssetsReference.Ref(material, meshRenderer.gameObject);
|
AssetsReference.Ref(material, meshRenderer.gameObject);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_resourceService.LoadAsset<Material>(location, material =>
|
|
||||||
{
|
|
||||||
if (meshRenderer == null || meshRenderer.gameObject == null)
|
|
||||||
{
|
|
||||||
_resourceService.UnloadAsset(material);
|
|
||||||
material = null;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
meshRenderer.sharedMaterial = material;
|
LoadMaterialAsync(location, packageName, MaterialSetRequest.Create(meshRenderer, false, true));
|
||||||
AssetsReference.Ref(material, meshRenderer.gameObject);
|
|
||||||
}, packageName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@ -1,3 +1,11 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 370ab69f738b11b429fbcc1d9e7a2fb1
|
guid: 370ab69f738b11b429fbcc1d9e7a2fb1
|
||||||
timeCreated: 1708490345
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|||||||
@ -0,0 +1,29 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace AlicizaX.Resource.Runtime
|
||||||
|
{
|
||||||
|
[DisallowMultipleComponent]
|
||||||
|
public sealed class MaterialInstanceReference : MonoBehaviour
|
||||||
|
{
|
||||||
|
private Material _material;
|
||||||
|
|
||||||
|
public void Set(Material material)
|
||||||
|
{
|
||||||
|
if (_material != null && _material != material)
|
||||||
|
{
|
||||||
|
Object.Destroy(_material);
|
||||||
|
}
|
||||||
|
|
||||||
|
_material = material;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
if (_material != null)
|
||||||
|
{
|
||||||
|
Object.Destroy(_material);
|
||||||
|
_material = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: eec0821e60a7c3946b3b434cfdbd999d
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Cysharp.Text;
|
||||||
using AlicizaX;
|
using AlicizaX;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Serialization;
|
using UnityEngine.Serialization;
|
||||||
@ -17,6 +18,8 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
|
|
||||||
private bool _forceUnloadUnusedAssets = false;
|
private bool _forceUnloadUnusedAssets = false;
|
||||||
|
|
||||||
|
private bool _forceSystemUnloadUnusedAssets = false;
|
||||||
|
|
||||||
private bool _preorderUnloadUnusedAssets = false;
|
private bool _preorderUnloadUnusedAssets = false;
|
||||||
|
|
||||||
private bool _performGCCollect = false;
|
private bool _performGCCollect = false;
|
||||||
@ -153,7 +156,9 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
Application.lowMemory += OnLowMemory;
|
Application.lowMemory += OnLowMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string PrefsKey = Application.dataPath.GetHashCode() + "GamePlayMode";
|
#if UNITY_EDITOR
|
||||||
|
public static string PrefsKey = ZString.Concat(Application.dataPath.GetHashCode(), "GamePlayMode");
|
||||||
|
#endif
|
||||||
|
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
@ -173,7 +178,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
_resourceService.AssetExpireTime = assetExpireTime;
|
_resourceService.AssetExpireTime = assetExpireTime;
|
||||||
_resourceService.AssetPriority = assetPriority;
|
_resourceService.AssetPriority = assetPriority;
|
||||||
_resourceService.SetForceUnloadUnusedAssetsAction(ForceUnloadUnusedAssets);
|
_resourceService.SetForceUnloadUnusedAssetsAction(ForceUnloadUnusedAssets);
|
||||||
Log.Info($"ResourceModule Run Mode {_playMode}");
|
Log.Info(ZString.Format("ResourceModule Run Mode {0}", _playMode));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnApplicationQuit()
|
private void OnApplicationQuit()
|
||||||
@ -189,6 +194,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
if (performGCCollect)
|
if (performGCCollect)
|
||||||
{
|
{
|
||||||
_performGCCollect = true;
|
_performGCCollect = true;
|
||||||
|
_forceSystemUnloadUnusedAssets = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,12 +206,13 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
if (_asyncOperation == null && (_forceUnloadUnusedAssets || _lastUnloadUnusedAssetsOperationElapseSeconds >= maxUnloadUnusedAssetsInterval ||
|
if (_asyncOperation == null && (_forceUnloadUnusedAssets || _lastUnloadUnusedAssetsOperationElapseSeconds >= maxUnloadUnusedAssetsInterval ||
|
||||||
_preorderUnloadUnusedAssets && _lastUnloadUnusedAssetsOperationElapseSeconds >= minUnloadUnusedAssetsInterval))
|
_preorderUnloadUnusedAssets && _lastUnloadUnusedAssetsOperationElapseSeconds >= minUnloadUnusedAssetsInterval))
|
||||||
{
|
{
|
||||||
Log.Info("Unload unused assets...");
|
bool useSystemUnload = _forceSystemUnloadUnusedAssets && useSystemUnloadUnusedAssets;
|
||||||
_forceUnloadUnusedAssets = false;
|
_forceUnloadUnusedAssets = false;
|
||||||
|
_forceSystemUnloadUnusedAssets = false;
|
||||||
_preorderUnloadUnusedAssets = false;
|
_preorderUnloadUnusedAssets = false;
|
||||||
_lastUnloadUnusedAssetsOperationElapseSeconds = 0f;
|
_lastUnloadUnusedAssetsOperationElapseSeconds = 0f;
|
||||||
_resourceService.UnloadUnusedAssets();
|
_resourceService.UnloadUnusedAssets();
|
||||||
_asyncOperation = useSystemUnloadUnusedAssets ? Resources.UnloadUnusedAssets() : null;
|
_asyncOperation = useSystemUnload ? Resources.UnloadUnusedAssets() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_asyncOperation == null && _performGCCollect)
|
if (_asyncOperation == null && _performGCCollect)
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using AlicizaX.ObjectPool;
|
using AlicizaX.ObjectPool;
|
||||||
using AlicizaX;
|
using AlicizaX;
|
||||||
@ -46,8 +46,6 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected internal override void Release(bool isShutdown)
|
protected internal override void Release(bool isShutdown)
|
||||||
{
|
|
||||||
if (!isShutdown)
|
|
||||||
{
|
{
|
||||||
AssetHandle handle = m_AssetHandle;
|
AssetHandle handle = m_AssetHandle;
|
||||||
if (handle is { IsValid: true })
|
if (handle is { IsValid: true })
|
||||||
@ -58,4 +56,3 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Cysharp.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using YooAsset;
|
using YooAsset;
|
||||||
|
|
||||||
@ -90,7 +91,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
// 小游戏缓存根目录
|
// 小游戏缓存根目录
|
||||||
// 注意:此处代码根据微信插件配置来填写!
|
// 注意:此处代码根据微信插件配置来填写!
|
||||||
WeChatWASM.WXBase.PreloadConcurrent(10);
|
WeChatWASM.WXBase.PreloadConcurrent(10);
|
||||||
string packageRoot = $"{WeChatWASM.WX.env.USER_DATA_PATH}/__GAME_FILE_CACHE/yoo";
|
string packageRoot = ZString.Concat(WeChatWASM.WX.env.USER_DATA_PATH, "/__GAME_FILE_CACHE/yoo");
|
||||||
webRemoteFileSystemParams = WechatFileSystemCreater.CreateFileSystemParameters(packageRoot, remoteServices, null);
|
webRemoteFileSystemParams = WechatFileSystemCreater.CreateFileSystemParameters(packageRoot, remoteServices, null);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
using AlicizaX.ObjectPool;
|
using AlicizaX.ObjectPool;
|
||||||
using AlicizaX;
|
using AlicizaX;
|
||||||
|
|
||||||
namespace AlicizaX.Resource.Runtime
|
namespace AlicizaX.Resource.Runtime
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
|
using Cysharp.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using YooAsset;
|
using YooAsset;
|
||||||
|
|
||||||
@ -20,12 +21,12 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
|
|
||||||
string IRemoteServices.GetRemoteMainURL(string fileName)
|
string IRemoteServices.GetRemoteMainURL(string fileName)
|
||||||
{
|
{
|
||||||
return $"{_defaultHostServer}/{fileName}";
|
return ZString.Concat(_defaultHostServer, "/", fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
string IRemoteServices.GetRemoteFallbackURL(string fileName)
|
string IRemoteServices.GetRemoteFallbackURL(string fileName)
|
||||||
{
|
{
|
||||||
return $"{_fallbackHostServer}/{fileName}";
|
return ZString.Concat(_fallbackHostServer, "/", fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using AlicizaX.ObjectPool;
|
using AlicizaX.ObjectPool;
|
||||||
using AlicizaX;
|
using AlicizaX;
|
||||||
|
using Cysharp.Text;
|
||||||
using Cysharp.Threading.Tasks;
|
using Cysharp.Threading.Tasks;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using YooAsset;
|
using YooAsset;
|
||||||
@ -28,7 +29,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
public string DecryptionServices { get; set; }
|
public string DecryptionServices { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自动释放资源引用计数为0的资源包
|
/// 自动释放资源引用计数。。的资源包
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AutoUnloadBundleWhenUnused { get; set; } = false;
|
public bool AutoUnloadBundleWhenUnused { get; set; } = false;
|
||||||
|
|
||||||
@ -60,7 +61,6 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
|
|
||||||
public int FailedTryAgain { get; set; }
|
public int FailedTryAgain { get; set; }
|
||||||
|
|
||||||
|
|
||||||
#region internal
|
#region internal
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -76,39 +76,89 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 资源信息列表。
|
/// 资源信息列表。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly Dictionary<string, AssetInfo> _assetInfoMap = new Dictionary<string, AssetInfo>();
|
private readonly Dictionary<AssetCacheKey, AssetInfo> _assetInfoMap = new Dictionary<AssetCacheKey, AssetInfo>(AssetCacheKeyComparer.Instance);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 正在加载的资源任务。
|
/// 正在加载的资源任务。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly Dictionary<string, UniTaskCompletionSource<bool>> _assetLoadingOperations = new Dictionary<string, UniTaskCompletionSource<bool>>();
|
private readonly Dictionary<string, AutoResetUniTaskCompletionSource<bool>> _assetLoadingOperations = new Dictionary<string, AutoResetUniTaskCompletionSource<bool>>();
|
||||||
|
|
||||||
|
private readonly Dictionary<AssetCacheKey, string> _assetObjectKeyMap = new Dictionary<AssetCacheKey, string>(AssetCacheKeyComparer.Instance);
|
||||||
|
|
||||||
private const float ProgressCallbackThreshold = 0.01f;
|
private const float ProgressCallbackThreshold = 0.01f;
|
||||||
|
|
||||||
|
private UnloadUnusedAssetsOperation _unloadUnusedAssetsOperation;
|
||||||
|
|
||||||
|
private UnloadAllAssetsOperation _unloadAllAssetsOperation;
|
||||||
|
|
||||||
|
private readonly struct AssetCacheKey
|
||||||
|
{
|
||||||
|
public readonly string PackageName;
|
||||||
|
|
||||||
|
public readonly string Location;
|
||||||
|
|
||||||
|
public AssetCacheKey(string packageName, string location)
|
||||||
|
{
|
||||||
|
PackageName = packageName ?? string.Empty;
|
||||||
|
Location = location ?? string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class AssetCacheKeyComparer : IEqualityComparer<AssetCacheKey>
|
||||||
|
{
|
||||||
|
public static readonly AssetCacheKeyComparer Instance = new AssetCacheKeyComparer();
|
||||||
|
|
||||||
|
private AssetCacheKeyComparer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(AssetCacheKey x, AssetCacheKey y)
|
||||||
|
{
|
||||||
|
return string.Equals(x.PackageName, y.PackageName, StringComparison.Ordinal) &&
|
||||||
|
string.Equals(x.Location, y.Location, StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetHashCode(AssetCacheKey obj)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
int hash = 17;
|
||||||
|
hash = hash * 31 + StringComparer.Ordinal.GetHashCode(obj.PackageName ?? string.Empty);
|
||||||
|
hash = hash * 31 + StringComparer.Ordinal.GetHashCode(obj.Location ?? string.Empty);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
// 初始化资源系统
|
// 初始化资源系。。
|
||||||
YooAssets.Initialize(new ResourceLogger());
|
YooAssets.Initialize(new ResourceLogger());
|
||||||
|
|
||||||
YooAssets.SetOperationSystemMaxTimeSlice(Milliseconds);
|
YooAssets.SetOperationSystemMaxTimeSlice(Milliseconds);
|
||||||
|
|
||||||
// 创建默认的资源包
|
// 创建默认的资源包
|
||||||
string packageName = DefaultPackageName;
|
string packageName = DefaultPackageName;
|
||||||
|
|
||||||
var defaultPackage = YooAssets.TryGetPackage(packageName);
|
var defaultPackage = YooAssets.TryGetPackage(packageName);
|
||||||
|
|
||||||
if (defaultPackage == null)
|
if (defaultPackage == null)
|
||||||
|
|
||||||
{
|
{
|
||||||
defaultPackage = YooAssets.CreatePackage(packageName);
|
defaultPackage = YooAssets.CreatePackage(packageName);
|
||||||
|
|
||||||
YooAssets.SetDefaultPackage(defaultPackage);
|
YooAssets.SetDefaultPackage(defaultPackage);
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultPackage = defaultPackage;
|
DefaultPackage = defaultPackage;
|
||||||
|
|
||||||
PackageMap[packageName] = defaultPackage;
|
PackageMap[packageName] = defaultPackage;
|
||||||
|
|
||||||
CreateAssetPool();
|
CreateAssetPool();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override void OnInitialize()
|
protected override void OnInitialize()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -124,6 +174,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
_assetPool = null;
|
_assetPool = null;
|
||||||
_assetLoadingOperations.Clear();
|
_assetLoadingOperations.Clear();
|
||||||
_assetInfoMap.Clear();
|
_assetInfoMap.Clear();
|
||||||
|
_assetObjectKeyMap.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTask<bool> InitPackageAsync(string packageName = "", string hostServerURL = "", string fallbackHostServerURL = "")
|
public UniTask<bool> InitPackageAsync(string packageName = "", string hostServerURL = "", string fallbackHostServerURL = "")
|
||||||
@ -137,7 +188,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
{
|
{
|
||||||
if (resPackage.InitializeStatus is EOperationStatus.Processing or EOperationStatus.Succeed)
|
if (resPackage.InitializeStatus is EOperationStatus.Processing or EOperationStatus.Succeed)
|
||||||
{
|
{
|
||||||
Log.Error($"ResourceSystem has already init package : {packageName}");
|
Log.Error(ZString.Format("ResourceSystem has already init package : {0}", packageName));
|
||||||
return new UniTask<bool>(false);
|
return new UniTask<bool>(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -150,7 +201,6 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
GameFrameworkGuard.NotNull(packageName, nameof(packageName));
|
GameFrameworkGuard.NotNull(packageName, nameof(packageName));
|
||||||
GameFrameworkGuard.NotNull(hostServerURL, nameof(hostServerURL));
|
GameFrameworkGuard.NotNull(hostServerURL, nameof(hostServerURL));
|
||||||
GameFrameworkGuard.NotNull(fallbackHostServerURL, nameof(fallbackHostServerURL));
|
GameFrameworkGuard.NotNull(fallbackHostServerURL, nameof(fallbackHostServerURL));
|
||||||
|
|
||||||
// 创建默认的资源包
|
// 创建默认的资源包
|
||||||
var resourcePackage = YooAssets.TryGetPackage(packageName);
|
var resourcePackage = YooAssets.TryGetPackage(packageName);
|
||||||
if (resourcePackage == null)
|
if (resourcePackage == null)
|
||||||
@ -159,7 +209,6 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
}
|
}
|
||||||
|
|
||||||
PackageMap[packageName] = resourcePackage;
|
PackageMap[packageName] = resourcePackage;
|
||||||
|
|
||||||
var initializationOperationHandler = CreateInitializationOperationHandler(resourcePackage, hostServerURL, fallbackHostServerURL, DecryptionServices);
|
var initializationOperationHandler = CreateInitializationOperationHandler(resourcePackage, hostServerURL, fallbackHostServerURL, DecryptionServices);
|
||||||
initializationOperationHandler.Completed += asyncOperationBase =>
|
initializationOperationHandler.Completed += asyncOperationBase =>
|
||||||
{
|
{
|
||||||
@ -172,10 +221,10 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
taskCompletionSource.TrySetException(new Exception(asyncOperationBase.Error));
|
taskCompletionSource.TrySetException(new Exception(asyncOperationBase.Error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return taskCompletionSource.Task;
|
return taskCompletionSource.Task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取当前资源包版本。
|
/// 获取当前资源包版本。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -186,6 +235,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
var package = string.IsNullOrEmpty(customPackageName)
|
var package = string.IsNullOrEmpty(customPackageName)
|
||||||
? YooAssets.GetPackage(DefaultPackageName)
|
? YooAssets.GetPackage(DefaultPackageName)
|
||||||
: YooAssets.GetPackage(customPackageName);
|
: YooAssets.GetPackage(customPackageName);
|
||||||
|
|
||||||
if (package == null)
|
if (package == null)
|
||||||
{
|
{
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
@ -204,44 +254,29 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
public RequestPackageVersionOperation RequestPackageVersionAsync(bool appendTimeTicks = false, int timeout = 60,
|
public RequestPackageVersionOperation RequestPackageVersionAsync(bool appendTimeTicks = false, int timeout = 60,
|
||||||
string customPackageName = "")
|
string customPackageName = "")
|
||||||
{
|
{
|
||||||
var package = string.IsNullOrEmpty(customPackageName)
|
var package = GetPackageOrThrow(customPackageName);
|
||||||
? YooAssets.GetPackage(DefaultPackageName)
|
|
||||||
: YooAssets.GetPackage(customPackageName);
|
|
||||||
return package.RequestPackageVersionAsync(appendTimeTicks, timeout);
|
return package.RequestPackageVersionAsync(appendTimeTicks, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 向网络端请求并更新清单
|
/// 向网络端请求并更新清。。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="packageVersion">更新的包裹版本</param>
|
/// <param name="packageVersion">更新的包裹版。。</param>
|
||||||
/// <param name="timeout">超时时间(默认值:60秒)</param>
|
/// <param name="timeout">超时时间(默认值:60秒)</param>
|
||||||
/// <param name="customPackageName">指定资源包的名称。不传使用默认资源包</param>
|
/// <param name="customPackageName">指定资源包的名称。不传使用默认资源包</param>
|
||||||
public UpdatePackageManifestOperation UpdatePackageManifestAsync(string packageVersion, int timeout = 60, string customPackageName = "")
|
public UpdatePackageManifestOperation UpdatePackageManifestAsync(string packageVersion, int timeout = 60, string customPackageName = "")
|
||||||
{
|
{
|
||||||
var package = string.IsNullOrEmpty(customPackageName)
|
var package = GetPackageOrThrow(customPackageName);
|
||||||
? YooAssets.GetPackage(this.DefaultPackageName)
|
|
||||||
: YooAssets.GetPackage(customPackageName);
|
|
||||||
return package.UpdatePackageManifestAsync(packageVersion, timeout);
|
return package.UpdatePackageManifestAsync(packageVersion, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建资源下载器,用于下载当前资源版本所有的资源包文件。
|
/// 创建资源下载器,用于下载当前资源版本所有的资源包文件。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="customPackageName">指定资源包的名称。不传使用默认资源包</param>
|
/// <param name="customPackageName">指定资源包的名称。不传使用默认资源包</param>
|
||||||
public ResourceDownloaderOperation CreateResourceDownloader(string customPackageName = "")
|
public ResourceDownloaderOperation CreateResourceDownloader(string customPackageName = "")
|
||||||
{
|
{
|
||||||
ResourcePackage package = null;
|
ResourcePackage package = GetPackageOrThrow(customPackageName);
|
||||||
if (string.IsNullOrEmpty(customPackageName))
|
|
||||||
{
|
|
||||||
package = YooAssets.GetPackage(this.DefaultPackageName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
package = YooAssets.GetPackage(customPackageName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return package.CreateResourceDownloader(DownloadingMaxNum, FailedTryAgain);
|
return package.CreateResourceDownloader(DownloadingMaxNum, FailedTryAgain);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,10 +289,8 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
EFileClearMode clearMode = EFileClearMode.ClearUnusedBundleFiles,
|
EFileClearMode clearMode = EFileClearMode.ClearUnusedBundleFiles,
|
||||||
string customPackageName = "")
|
string customPackageName = "")
|
||||||
{
|
{
|
||||||
var package = string.IsNullOrEmpty(customPackageName)
|
var package = GetPackageOrThrow(customPackageName);
|
||||||
? YooAssets.GetPackage(DefaultPackageName)
|
return package.ClearCacheFilesAsync(clearMode);
|
||||||
: YooAssets.GetPackage(customPackageName);
|
|
||||||
return package.ClearCacheFilesAsync(EFileClearMode.ClearUnusedBundleFiles);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -266,9 +299,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
/// <param name="customPackageName">指定资源包的名称。不传使用默认资源包</param>
|
/// <param name="customPackageName">指定资源包的名称。不传使用默认资源包</param>
|
||||||
public void ClearAllBundleFiles(string customPackageName = "")
|
public void ClearAllBundleFiles(string customPackageName = "")
|
||||||
{
|
{
|
||||||
var package = string.IsNullOrEmpty(customPackageName)
|
var package = GetPackageOrThrow(customPackageName);
|
||||||
? YooAssets.GetPackage(DefaultPackageName)
|
|
||||||
: YooAssets.GetPackage(customPackageName);
|
|
||||||
package.ClearCacheFilesAsync(EFileClearMode.ClearAllBundleFiles);
|
package.ClearCacheFilesAsync(EFileClearMode.ClearAllBundleFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,11 +328,16 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
public void UnloadUnusedAssets()
|
public void UnloadUnusedAssets()
|
||||||
{
|
{
|
||||||
_assetPool.ReleaseAllUnused();
|
_assetPool.ReleaseAllUnused();
|
||||||
|
if (_unloadUnusedAssetsOperation is { IsDone: false })
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var package in PackageMap.Values)
|
foreach (var package in PackageMap.Values)
|
||||||
{
|
{
|
||||||
if (package is { InitializeStatus: EOperationStatus.Succeed })
|
if (package is { InitializeStatus: EOperationStatus.Succeed })
|
||||||
{
|
{
|
||||||
package.UnloadUnusedAssetsAsync();
|
_unloadUnusedAssetsOperation = package.UnloadUnusedAssetsAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -312,15 +348,19 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
public void ForceUnloadAllAssets()
|
public void ForceUnloadAllAssets()
|
||||||
{
|
{
|
||||||
#if UNITY_WEBGL
|
#if UNITY_WEBGL
|
||||||
Log.Warning($"WebGL not support invoke {nameof(ForceUnloadAllAssets)}");
|
Log.Warning(ZString.Format("WebGL not support invoke {0}", nameof(ForceUnloadAllAssets)));
|
||||||
return;
|
return;
|
||||||
#else
|
#else
|
||||||
|
if (_unloadAllAssetsOperation is { IsDone: false })
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var package in PackageMap.Values)
|
foreach (var package in PackageMap.Values)
|
||||||
{
|
{
|
||||||
if (package is { InitializeStatus: EOperationStatus.Succeed })
|
if (package is { InitializeStatus: EOperationStatus.Succeed })
|
||||||
{
|
{
|
||||||
package.UnloadAllAssetsAsync();
|
_unloadAllAssetsOperation = package.UnloadAllAssetsAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -331,6 +371,19 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
_forceUnloadUnusedAssetsAction?.Invoke(performGCCollect);
|
_forceUnloadUnusedAssetsAction?.Invoke(performGCCollect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ResourcePackage GetPackageOrThrow(string packageName)
|
||||||
|
{
|
||||||
|
ResourcePackage package = string.IsNullOrEmpty(packageName)
|
||||||
|
? YooAssets.GetPackage(DefaultPackageName)
|
||||||
|
: YooAssets.GetPackage(packageName);
|
||||||
|
if (package == null)
|
||||||
|
{
|
||||||
|
throw new GameFrameworkException(ZString.Format("The package does not exist. Package Name :{0}", string.IsNullOrEmpty(packageName) ? DefaultPackageName : packageName));
|
||||||
|
}
|
||||||
|
|
||||||
|
return package;
|
||||||
|
}
|
||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
#region 获取资源信息
|
#region 获取资源信息
|
||||||
@ -346,12 +399,10 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
{
|
{
|
||||||
return YooAssets.IsNeedDownloadFromRemote(location);
|
return YooAssets.IsNeedDownloadFromRemote(location);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
var package = YooAssets.GetPackage(packageName);
|
var package = YooAssets.GetPackage(packageName);
|
||||||
return package.IsNeedDownloadFromRemote(location);
|
return package.IsNeedDownloadFromRemote(location);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否需要从远端更新下载。
|
/// 是否需要从远端更新下载。
|
||||||
@ -364,12 +415,10 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
{
|
{
|
||||||
return YooAssets.IsNeedDownloadFromRemote(assetInfo);
|
return YooAssets.IsNeedDownloadFromRemote(assetInfo);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
var package = YooAssets.GetPackage(packageName);
|
var package = YooAssets.GetPackage(packageName);
|
||||||
return package.IsNeedDownloadFromRemote(assetInfo);
|
return package.IsNeedDownloadFromRemote(assetInfo);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取资源信息列表。
|
/// 获取资源信息列表。
|
||||||
@ -383,12 +432,10 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
{
|
{
|
||||||
return YooAssets.GetAssetInfos(tag);
|
return YooAssets.GetAssetInfos(tag);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
var package = YooAssets.GetPackage(packageName);
|
var package = YooAssets.GetPackage(packageName);
|
||||||
return package.GetAssetInfos(tag);
|
return package.GetAssetInfos(tag);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取资源信息列表。
|
/// 获取资源信息列表。
|
||||||
@ -402,12 +449,10 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
{
|
{
|
||||||
return YooAssets.GetAssetInfos(tags);
|
return YooAssets.GetAssetInfos(tags);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
var package = YooAssets.GetPackage(packageName);
|
var package = YooAssets.GetPackage(packageName);
|
||||||
return package.GetAssetInfos(tags);
|
return package.GetAssetInfos(tags);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取资源信息。
|
/// 获取资源信息。
|
||||||
@ -424,18 +469,19 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
|
|
||||||
if (string.IsNullOrEmpty(packageName))
|
if (string.IsNullOrEmpty(packageName))
|
||||||
{
|
{
|
||||||
if (_assetInfoMap.TryGetValue(location, out AssetInfo assetInfo))
|
AssetCacheKey key = new AssetCacheKey(DefaultPackageName, location);
|
||||||
|
if (_assetInfoMap.TryGetValue(key, out AssetInfo assetInfo))
|
||||||
{
|
{
|
||||||
return assetInfo;
|
return assetInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
assetInfo = YooAssets.GetAssetInfo(location);
|
assetInfo = YooAssets.GetAssetInfo(location);
|
||||||
_assetInfoMap[location] = assetInfo;
|
_assetInfoMap[key] = assetInfo;
|
||||||
return assetInfo;
|
return assetInfo;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string key = $"{packageName}/{location}";
|
AssetCacheKey key = new AssetCacheKey(packageName, location);
|
||||||
if (_assetInfoMap.TryGetValue(key, out AssetInfo assetInfo))
|
if (_assetInfoMap.TryGetValue(key, out AssetInfo assetInfo))
|
||||||
{
|
{
|
||||||
return assetInfo;
|
return assetInfo;
|
||||||
@ -444,7 +490,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
var package = YooAssets.GetPackage(packageName);
|
var package = YooAssets.GetPackage(packageName);
|
||||||
if (package == null)
|
if (package == null)
|
||||||
{
|
{
|
||||||
throw new GameFrameworkException($"The package does not exist. Package Name :{packageName}");
|
throw new GameFrameworkException(ZString.Format("The package does not exist. Package Name :{0}", packageName));
|
||||||
}
|
}
|
||||||
|
|
||||||
assetInfo = package.GetAssetInfo(location);
|
assetInfo = package.GetAssetInfo(location);
|
||||||
@ -467,10 +513,9 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
}
|
}
|
||||||
|
|
||||||
AssetInfo assetInfo = GetAssetInfo(location, packageName);
|
AssetInfo assetInfo = GetAssetInfo(location, packageName);
|
||||||
|
|
||||||
if (!CheckLocationValid(location, packageName))
|
if (!CheckLocationValid(location, packageName))
|
||||||
{
|
{
|
||||||
return HasAssetResult.Valid;
|
return HasAssetResult.NotExist;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (assetInfo == null)
|
if (assetInfo == null)
|
||||||
@ -499,7 +544,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
}
|
}
|
||||||
|
|
||||||
var package = YooAssets.GetPackage(packageName);
|
var package = YooAssets.GetPackage(packageName);
|
||||||
return package.CheckLocationValid(location);
|
return package != null && package.CheckLocationValid(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -546,6 +591,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
private AssetHandle GetHandleAsync(string location, Type assetType, string packageName = "", uint priority = 0)
|
private AssetHandle GetHandleAsync(string location, Type assetType, string packageName = "", uint priority = 0)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(packageName))
|
if (string.IsNullOrEmpty(packageName))
|
||||||
|
|
||||||
{
|
{
|
||||||
return YooAssets.LoadAssetAsync(location, assetType, priority);
|
return YooAssets.LoadAssetAsync(location, assetType, priority);
|
||||||
}
|
}
|
||||||
@ -574,7 +620,16 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $"{packageName}/{location}";
|
AssetCacheKey key = new AssetCacheKey(packageName, location);
|
||||||
|
|
||||||
|
if (_assetObjectKeyMap.TryGetValue(key, out string cacheKey))
|
||||||
|
{
|
||||||
|
return cacheKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheKey = ZString.Concat(packageName, "/", location);
|
||||||
|
_assetObjectKeyMap[key] = cacheKey;
|
||||||
|
return cacheKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public T LoadAsset<T>(string location, string packageName = "") where T : UnityEngine.Object
|
public T LoadAsset<T>(string location, string packageName = "") where T : UnityEngine.Object
|
||||||
@ -586,21 +641,20 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
|
|
||||||
if (!CheckLocationValid(location, packageName))
|
if (!CheckLocationValid(location, packageName))
|
||||||
{
|
{
|
||||||
Log.Error($"Could not found location [{location}].");
|
Log.Error(ZString.Format("Could not found location [{0}].", location));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
string assetObjectKey = GetCacheKey(location, packageName);
|
string assetObjectKey = GetCacheKey(location, packageName);
|
||||||
AssetObject assetObject = _assetPool.Spawn(assetObjectKey);
|
AssetObject assetObject = _assetPool.Spawn(assetObjectKey);
|
||||||
|
|
||||||
if (assetObject != null)
|
if (assetObject != null)
|
||||||
{
|
{
|
||||||
return assetObject.Target as T;
|
return assetObject.Target as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
AssetHandle handle = GetHandleSync<T>(location, packageName: packageName);
|
AssetHandle handle = GetHandleSync<T>(location, packageName: packageName);
|
||||||
|
|
||||||
T ret = handle.AssetObject as T;
|
T ret = handle.AssetObject as T;
|
||||||
|
|
||||||
assetObject = AssetObject.Create(assetObjectKey, handle.AssetObject, handle);
|
assetObject = AssetObject.Create(assetObjectKey, handle.AssetObject, handle);
|
||||||
_assetPool.Register(assetObject, true);
|
_assetPool.Register(assetObject, true);
|
||||||
|
|
||||||
@ -616,21 +670,20 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
|
|
||||||
if (!CheckLocationValid(location, packageName))
|
if (!CheckLocationValid(location, packageName))
|
||||||
{
|
{
|
||||||
Log.Error($"Could not found location [{location}].");
|
Log.Error(ZString.Format("Could not found location [{0}].", location));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
string assetObjectKey = GetCacheKey(location, packageName);
|
string assetObjectKey = GetCacheKey(location, packageName);
|
||||||
AssetObject assetObject = _assetPool.Spawn(assetObjectKey);
|
AssetObject assetObject = _assetPool.Spawn(assetObjectKey);
|
||||||
|
|
||||||
if (assetObject != null)
|
if (assetObject != null)
|
||||||
{
|
{
|
||||||
return AssetsReference.Instantiate(assetObject.Target as GameObject, parent, this).gameObject;
|
return AssetsReference.Instantiate(assetObject.Target as GameObject, parent, this).gameObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
AssetHandle handle = GetHandleSync<GameObject>(location, packageName: packageName);
|
AssetHandle handle = GetHandleSync<GameObject>(location, packageName: packageName);
|
||||||
|
|
||||||
GameObject gameObject = AssetsReference.Instantiate(handle.AssetObject as GameObject, parent, this).gameObject;
|
GameObject gameObject = AssetsReference.Instantiate(handle.AssetObject as GameObject, parent, this).gameObject;
|
||||||
|
|
||||||
assetObject = AssetObject.Create(assetObjectKey, handle.AssetObject, handle);
|
assetObject = AssetObject.Create(assetObjectKey, handle.AssetObject, handle);
|
||||||
_assetPool.Register(assetObject, true);
|
_assetPool.Register(assetObject, true);
|
||||||
|
|
||||||
@ -654,23 +707,15 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
|
|
||||||
if (!CheckLocationValid(location, packageName))
|
if (!CheckLocationValid(location, packageName))
|
||||||
{
|
{
|
||||||
Log.Error($"Could not found location [{location}].");
|
Log.Error(ZString.Format("Could not found location [{0}].", location));
|
||||||
callback?.Invoke(null);
|
callback?.Invoke(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string assetObjectKey = GetCacheKey(location, packageName);
|
string assetObjectKey = GetCacheKey(location, packageName);
|
||||||
try
|
|
||||||
{
|
|
||||||
var asset = await GetOrLoadAssetAsync(location, typeof(T), packageName, assetObjectKey);
|
var asset = await GetOrLoadAssetAsync(location, typeof(T), packageName, assetObjectKey);
|
||||||
callback?.Invoke(asset as T);
|
callback?.Invoke(asset as T);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Error($"Can not load asset '{location}'. {ex}");
|
|
||||||
callback?.Invoke(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async UniTask<T> LoadAssetAsync<T>(string location, CancellationToken cancellationToken = default, string packageName = "") where T : UnityEngine.Object
|
public async UniTask<T> LoadAssetAsync<T>(string location, CancellationToken cancellationToken = default, string packageName = "") where T : UnityEngine.Object
|
||||||
{
|
{
|
||||||
@ -681,13 +726,11 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
|
|
||||||
if (!CheckLocationValid(location, packageName))
|
if (!CheckLocationValid(location, packageName))
|
||||||
{
|
{
|
||||||
Log.Error($"Could not found location [{location}].");
|
Log.Error(ZString.Format("Could not found location [{0}].", location));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
string assetObjectKey = GetCacheKey(location, packageName);
|
string assetObjectKey = GetCacheKey(location, packageName);
|
||||||
|
|
||||||
var asset = await GetOrLoadAssetAsync(location, typeof(T), packageName, assetObjectKey, cancellationToken: cancellationToken);
|
var asset = await GetOrLoadAssetAsync(location, typeof(T), packageName, assetObjectKey, cancellationToken: cancellationToken);
|
||||||
return asset as T;
|
return asset as T;
|
||||||
}
|
}
|
||||||
@ -701,12 +744,11 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
|
|
||||||
if (!CheckLocationValid(location, packageName))
|
if (!CheckLocationValid(location, packageName))
|
||||||
{
|
{
|
||||||
Log.Error($"Could not found location [{location}].");
|
Log.Error(ZString.Format("Could not found location [{0}].", location));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
string assetObjectKey = GetCacheKey(location, packageName);
|
string assetObjectKey = GetCacheKey(location, packageName);
|
||||||
|
|
||||||
var asset = await GetOrLoadAssetAsync(location, typeof(GameObject), packageName, assetObjectKey, cancellationToken: cancellationToken);
|
var asset = await GetOrLoadAssetAsync(location, typeof(GameObject), packageName, assetObjectKey, cancellationToken: cancellationToken);
|
||||||
return asset != null ? AssetsReference.Instantiate(asset as GameObject, parent, this).gameObject : null;
|
return asset != null ? AssetsReference.Instantiate(asset as GameObject, parent, this).gameObject : null;
|
||||||
}
|
}
|
||||||
@ -736,7 +778,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
|
|
||||||
if (!CheckLocationValid(location, packageName))
|
if (!CheckLocationValid(location, packageName))
|
||||||
{
|
{
|
||||||
string errorMessage = Utility.Text.Format("Could not found location [{0}].", location);
|
string errorMessage = ZString.Format("Could not found location [{0}].", location);
|
||||||
Log.Error(errorMessage);
|
Log.Error(errorMessage);
|
||||||
if (loadAssetCallbacks.LoadAssetFailureCallback != null)
|
if (loadAssetCallbacks.LoadAssetFailureCallback != null)
|
||||||
{
|
{
|
||||||
@ -747,14 +789,11 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
}
|
}
|
||||||
|
|
||||||
string assetObjectKey = GetCacheKey(location, packageName);
|
string assetObjectKey = GetCacheKey(location, packageName);
|
||||||
|
|
||||||
float duration = Time.time;
|
float duration = Time.time;
|
||||||
|
|
||||||
AssetInfo assetInfo = GetAssetInfo(location, packageName);
|
AssetInfo assetInfo = GetAssetInfo(location, packageName);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(assetInfo.Error))
|
if (!string.IsNullOrEmpty(assetInfo.Error))
|
||||||
{
|
{
|
||||||
string errorMessage = Utility.Text.Format("Can not load asset '{0}' because :'{1}'.", location, assetInfo.Error);
|
string errorMessage = ZString.Format("Can not load asset '{0}' because :'{1}'.", location, assetInfo.Error);
|
||||||
if (loadAssetCallbacks.LoadAssetFailureCallback != null)
|
if (loadAssetCallbacks.LoadAssetFailureCallback != null)
|
||||||
{
|
{
|
||||||
loadAssetCallbacks.LoadAssetFailureCallback(location, LoadResourceStatus.NotExist, errorMessage, userData);
|
loadAssetCallbacks.LoadAssetFailureCallback(location, LoadResourceStatus.NotExist, errorMessage, userData);
|
||||||
@ -764,24 +803,17 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
throw new GameFrameworkException(errorMessage);
|
throw new GameFrameworkException(errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var asset = await GetOrLoadAssetAsync(location, assetType, packageName, assetObjectKey, NormalizePriority(priority), default,
|
var asset = await GetOrLoadAssetAsync(location, assetType, packageName, assetObjectKey, NormalizePriority(priority), default,
|
||||||
handle => StartProgressTask(location, handle, loadAssetCallbacks.LoadAssetUpdateCallback, userData));
|
loadAssetCallbacks.LoadAssetUpdateCallback, userData);
|
||||||
loadAssetCallbacks.LoadAssetSuccessCallback?.Invoke(location, asset, Time.time - duration, userData);
|
|
||||||
}
|
if (asset == null)
|
||||||
catch (Exception ex)
|
|
||||||
{
|
{
|
||||||
string errorMessage = Utility.Text.Format("Can not load asset '{0}'.", location);
|
string errorMessage = ZString.Format("Can not load asset '{0}'.", location);
|
||||||
Log.Error($"{errorMessage} {ex}");
|
loadAssetCallbacks.LoadAssetFailureCallback?.Invoke(location, LoadResourceStatus.NotReady, errorMessage, userData);
|
||||||
if (loadAssetCallbacks.LoadAssetFailureCallback != null)
|
|
||||||
{
|
|
||||||
loadAssetCallbacks.LoadAssetFailureCallback(location, LoadResourceStatus.NotReady, errorMessage, userData);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw;
|
loadAssetCallbacks.LoadAssetSuccessCallback?.Invoke(location, asset, Time.time - duration, userData);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -806,7 +838,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
|
|
||||||
if (!CheckLocationValid(location, packageName))
|
if (!CheckLocationValid(location, packageName))
|
||||||
{
|
{
|
||||||
string errorMessage = Utility.Text.Format("Could not found location [{0}].", location);
|
string errorMessage = ZString.Format("Could not found location [{0}].", location);
|
||||||
Log.Error(errorMessage);
|
Log.Error(errorMessage);
|
||||||
if (loadAssetCallbacks.LoadAssetFailureCallback != null)
|
if (loadAssetCallbacks.LoadAssetFailureCallback != null)
|
||||||
{
|
{
|
||||||
@ -817,14 +849,11 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
}
|
}
|
||||||
|
|
||||||
string assetObjectKey = GetCacheKey(location, packageName);
|
string assetObjectKey = GetCacheKey(location, packageName);
|
||||||
|
|
||||||
float duration = Time.time;
|
float duration = Time.time;
|
||||||
|
|
||||||
AssetInfo assetInfo = GetAssetInfo(location, packageName);
|
AssetInfo assetInfo = GetAssetInfo(location, packageName);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(assetInfo.Error))
|
if (!string.IsNullOrEmpty(assetInfo.Error))
|
||||||
{
|
{
|
||||||
string errorMessage = Utility.Text.Format("Can not load asset '{0}' because :'{1}'.", location, assetInfo.Error);
|
string errorMessage = ZString.Format("Can not load asset '{0}' because :'{1}'.", location, assetInfo.Error);
|
||||||
if (loadAssetCallbacks.LoadAssetFailureCallback != null)
|
if (loadAssetCallbacks.LoadAssetFailureCallback != null)
|
||||||
{
|
{
|
||||||
loadAssetCallbacks.LoadAssetFailureCallback(location, LoadResourceStatus.NotExist, errorMessage, userData);
|
loadAssetCallbacks.LoadAssetFailureCallback(location, LoadResourceStatus.NotExist, errorMessage, userData);
|
||||||
@ -834,24 +863,17 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
throw new GameFrameworkException(errorMessage);
|
throw new GameFrameworkException(errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var asset = await GetOrLoadAssetAsync(location, assetInfo.AssetType, packageName, assetObjectKey, NormalizePriority(priority), default,
|
var asset = await GetOrLoadAssetAsync(location, assetInfo.AssetType, packageName, assetObjectKey, NormalizePriority(priority), default,
|
||||||
handle => StartProgressTask(location, handle, loadAssetCallbacks.LoadAssetUpdateCallback, userData));
|
loadAssetCallbacks.LoadAssetUpdateCallback, userData);
|
||||||
loadAssetCallbacks.LoadAssetSuccessCallback?.Invoke(location, asset, Time.time - duration, userData);
|
|
||||||
}
|
if (asset == null)
|
||||||
catch (Exception ex)
|
|
||||||
{
|
{
|
||||||
string errorMessage = Utility.Text.Format("Can not load asset '{0}'.", location);
|
string errorMessage = ZString.Format("Can not load asset '{0}'.", location);
|
||||||
Log.Error($"{errorMessage} {ex}");
|
loadAssetCallbacks.LoadAssetFailureCallback?.Invoke(location, LoadResourceStatus.NotReady, errorMessage, userData);
|
||||||
if (loadAssetCallbacks.LoadAssetFailureCallback != null)
|
|
||||||
{
|
|
||||||
loadAssetCallbacks.LoadAssetFailureCallback(location, LoadResourceStatus.NotReady, errorMessage, userData);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw;
|
loadAssetCallbacks.LoadAssetSuccessCallback?.Invoke(location, asset, Time.time - duration, userData);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async UniTaskVoid InvokeProgress(string location, AssetHandle assetHandle, LoadAssetUpdateCallback loadAssetUpdateCallback, object userData)
|
private async UniTaskVoid InvokeProgress(string location, AssetHandle assetHandle, LoadAssetUpdateCallback loadAssetUpdateCallback, object userData)
|
||||||
@ -921,12 +943,11 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private async UniTask<UnityEngine.Object> GetOrLoadAssetAsync(string location, Type assetType, string packageName,
|
private async UniTask<UnityEngine.Object> GetOrLoadAssetAsync(string location, Type assetType, string packageName,
|
||||||
string assetObjectKey, uint priority = 0, CancellationToken cancellationToken = default, Action<AssetHandle> onHandleCreated = null)
|
string assetObjectKey, uint priority = 0, CancellationToken cancellationToken = default, LoadAssetUpdateCallback loadAssetUpdateCallback = null, object userData = null)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
AssetObject cachedAssetObject = _assetPool.Spawn(assetObjectKey);
|
AssetObject cachedAssetObject = _assetPool.Spawn(assetObjectKey);
|
||||||
if (cachedAssetObject != null)
|
if (cachedAssetObject != null)
|
||||||
{
|
{
|
||||||
@ -939,16 +960,25 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
AssetHandle handle = null;
|
AssetHandle handle = GetHandleAsync(location, assetType, packageName: packageName, priority: priority);
|
||||||
try
|
StartProgressTask(location, handle, loadAssetUpdateCallback, userData);
|
||||||
|
while (handle is { IsValid: true, IsDone: false })
|
||||||
{
|
{
|
||||||
handle = GetHandleAsync(location, assetType, packageName: packageName, priority: priority);
|
if (cancellationToken.IsCancellationRequested)
|
||||||
onHandleCreated?.Invoke(handle);
|
{
|
||||||
await handle.ToUniTask();
|
DisposeHandle(handle);
|
||||||
|
FailLoading(assetObjectKey, null);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
await UniTask.Yield();
|
||||||
|
}
|
||||||
|
|
||||||
if (handle.AssetObject == null || handle.Status == EOperationStatus.Failed)
|
if (handle.AssetObject == null || handle.Status == EOperationStatus.Failed)
|
||||||
{
|
{
|
||||||
throw new GameFrameworkException(Utility.Text.Format("Can not load asset '{0}'.", location));
|
DisposeHandle(handle);
|
||||||
|
FailLoading(assetObjectKey, null);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var assetObject = AssetObject.Create(assetObjectKey, handle.AssetObject, handle);
|
var assetObject = AssetObject.Create(assetObjectKey, handle.AssetObject, handle);
|
||||||
@ -956,23 +986,16 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
CompleteLoading(assetObjectKey);
|
CompleteLoading(assetObjectKey);
|
||||||
return handle.AssetObject as UnityEngine.Object;
|
return handle.AssetObject as UnityEngine.Object;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
DisposeHandle(handle);
|
|
||||||
FailLoading(assetObjectKey, ex);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryBeginLoading(string assetObjectKey)
|
private bool TryBeginLoading(string assetObjectKey)
|
||||||
{
|
{
|
||||||
if (_assetLoadingOperations.ContainsKey(assetObjectKey))
|
if (_assetLoadingOperations.TryGetValue(assetObjectKey, out _))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_assetLoadingOperations.Add(assetObjectKey, new UniTaskCompletionSource<bool>());
|
_assetLoadingOperations.Add(assetObjectKey, AutoResetUniTaskCompletionSource<bool>.Create());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1007,12 +1030,13 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
private void FailLoading(string assetObjectKey, Exception exception)
|
private void FailLoading(string assetObjectKey, Exception exception)
|
||||||
{
|
{
|
||||||
if (!_assetLoadingOperations.TryGetValue(assetObjectKey, out var loadingOperation))
|
if (!_assetLoadingOperations.TryGetValue(assetObjectKey, out var loadingOperation))
|
||||||
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_assetLoadingOperations.Remove(assetObjectKey);
|
_assetLoadingOperations.Remove(assetObjectKey);
|
||||||
loadingOperation.TrySetException(exception);
|
loadingOperation.TrySetResult(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisposeHandle(AssetHandle handle)
|
private void DisposeHandle(AssetHandle handle)
|
||||||
@ -1038,7 +1062,7 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置下载系统参数,自定义下载请求。
|
/// 设置下载系统参数,自定义下载请求。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="downloadSystemUnityWebRequest">自定义下载器的请求委托。<see cref="UnityWebRequestDelegate"/></param>
|
/// <param name="downloadSystemUnityWebRequest">自定义下载器的请求委托,<see cref="UnityWebRequestDelegate"/></param>
|
||||||
public void SetDownloadSystemUnityWebRequest(UnityWebRequestDelegate downloadSystemUnityWebRequest)
|
public void SetDownloadSystemUnityWebRequest(UnityWebRequestDelegate downloadSystemUnityWebRequest)
|
||||||
{
|
{
|
||||||
YooAssets.SetDownloadSystemUnityWebRequest(downloadSystemUnityWebRequest);
|
YooAssets.SetDownloadSystemUnityWebRequest(downloadSystemUnityWebRequest);
|
||||||
@ -1054,9 +1078,9 @@ namespace AlicizaX.Resource.Runtime
|
|||||||
|
|
||||||
private string GetAuthorization(string userName, string password)
|
private string GetAuthorization(string userName, string password)
|
||||||
{
|
{
|
||||||
string auth = $"{userName}:{password}";
|
string auth = ZString.Concat(userName, ":", password);
|
||||||
var bytes = System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(auth);
|
var bytes = System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(auth);
|
||||||
return $"Basic {Convert.ToBase64String(bytes)}";
|
return ZString.Concat("Basic ", Convert.ToBase64String(bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user