AddressableをIDisposableで管理する
Addressable、めっちゃ便利だけどAsyncOperationHandleを握っておいてReleaseメソッドを呼ぶ。という開放がちょっと面倒なんですよね。
そこで、IDisposableで管理できるようにしてみました。
合わせて読みたい -> EditorではAddressableのロードを早くする
使い方
// 読み込む
var prefab = await AddressableWrapper.Load<GameObject>("Test.prefab", cancellationToken);
// 使う
GameObject.Instantiate(prefab.Value);
// 開放する
prefab.Dispose();コード
AddressableWrapper.cs
using System;
using System.Threading;
using Cysharp.Threading.Tasks;
using JetBrains.Annotations;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
namespace KyubunsSandbox
{
public static class AddressableWrapper
{
private static IAddressableLoader _addressableLoader;
public static IAddressableLoader AddressableLoader
{
get => _addressableLoader ?? (_addressableLoader = new DefaultAddressableLoader());
set => _addressableLoader = value;
}
[MustUseReturnValue]
public static UniTask<IDisposableAsset<TObject>> Load<TObject>(string address, CancellationToken cancellationToken) where TObject : UnityEngine.Object
{
return AddressableLoader.LoadAssetAsync<TObject>(address, cancellationToken);
}
public interface IAddressableLoader
{
UniTask<IDisposableAsset<TObject>> LoadAssetAsync<TObject>(string address, CancellationToken cancellationToken) where TObject : UnityEngine.Object;
}
public class DefaultAddressableLoader : IAddressableLoader
{
public async UniTask<IDisposableAsset<TObject>> LoadAssetAsync<TObject>(string address, CancellationToken cancellationToken) where TObject : UnityEngine.Object
{
var handle = Addressables.LoadAssetAsync<TObject>(address);
await handle.ToUniTask(cancellationToken: cancellationToken);
if (handle.Status == AsyncOperationStatus.Succeeded)
{
return new DisposableAsset<TObject>(handle.Result, () => Addressables.Release(handle));
}
throw new Exception($"Failed to load {address} {handle.Status}");
}
}
}
public interface IDisposableAsset<out T> : IDisposable
{
T Value { get; }
}
public class DisposableAsset<T> : IDisposableAsset<T>
{
public T Value { get; }
private bool _disposed;
private readonly Action _dispose;
public DisposableAsset(T value, Action dispose)
{
Value = value;
_dispose = dispose;
}
public void Dispose()
{
if (_disposed) return;
_disposed = true;
_dispose();
}
}
}