71 lines
2.2 KiB
C#
71 lines
2.2 KiB
C#
using System;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using FlowScope.Resources;
|
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
|
using UnityAddressables = UnityEngine.AddressableAssets.Addressables;
|
|
|
|
namespace FlowScope.Addressables
|
|
{
|
|
public sealed class AddressablesResourceBackend : IResourceBackend
|
|
{
|
|
public string Name => "Addressables";
|
|
|
|
public async Task<T> LoadAsync<T>(string key, CancellationToken cancellationToken)
|
|
where T : class
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
var handle = UnityAddressables.LoadAssetAsync<T>(key);
|
|
try
|
|
{
|
|
await WaitWithCancellation(handle.Task, cancellationToken);
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
UnityAddressables.Release(handle);
|
|
throw;
|
|
}
|
|
|
|
if (handle.OperationException != null ||
|
|
handle.Status != AsyncOperationStatus.Succeeded ||
|
|
handle.Result == null)
|
|
{
|
|
var exception = new InvalidOperationException(
|
|
$"Failed to load Addressables resource '{key}' as {typeof(T).Name} from backend '{Name}'.",
|
|
handle.OperationException);
|
|
UnityAddressables.Release(handle);
|
|
throw exception;
|
|
}
|
|
|
|
return handle.Result;
|
|
}
|
|
|
|
public void Release<T>(string key, T asset)
|
|
where T : class
|
|
{
|
|
UnityAddressables.Release(asset);
|
|
}
|
|
|
|
private static async Task WaitWithCancellation(Task task, CancellationToken cancellationToken)
|
|
{
|
|
if (!cancellationToken.CanBeCanceled)
|
|
{
|
|
await task;
|
|
return;
|
|
}
|
|
|
|
var cancellation = new TaskCompletionSource<bool>();
|
|
using (cancellationToken.Register(() => cancellation.TrySetResult(true)))
|
|
{
|
|
if (await Task.WhenAny(task, cancellation.Task) == cancellation.Task)
|
|
{
|
|
throw new OperationCanceledException(cancellationToken);
|
|
}
|
|
}
|
|
|
|
await task;
|
|
}
|
|
}
|
|
}
|