こんばんは。
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using Object = UnityEngine.Object;
namespace Ruchi.Data.Repository
{
public static class AddressableRepository
{
private readonly struct AssetEntity
{
///アドレス、ラベル
public readonly string Path;
//参照カウンタ
public readonly int RefCount;
//Addressable のロードハンドラ
public readonly AsyncOperationHandle Handle;
public AssetEntity(string path, int refCount, AsyncOperationHandle handle)
{
Path = path;
RefCount = refCount;
Handle = handle;
}
public AssetEntity IncreaseRefCount()
{
var refCount = checked(RefCount + 1);
var entity = new AssetEntity(Path, refCount, Handle);
return entity;
}
public AssetEntity DecreaseRefCount()
{
if (RefCount == 0)
{
throw new Exception($"{nameof(RefCount)}は0以下にできません。");
}
var entity = new AssetEntity(Path, RefCount - 1, Handle);
return entity;
}
}
private static readonly Dictionary<(Type, string path), AssetEntity> Entities = new();
private static bool ContainsKey<T>(string path)
{
return Entities.ContainsKey((typeof(T), path));
}
private static AssetEntity GetEntity<T>(string path)
{
return Entities[(typeof(T), path)];
}
private static void SetEntity<T>(AssetEntity entity)
{
Entities[(typeof(T), entity.Path)] = entity;
}
private static void RemoveEntity<T>(string path)
{
Entities.Remove((typeof(T), path));
}
public static async UniTask<T> LoadAssetAsync<T>(string path) where T : Object
{
var contains = ContainsKey<T>(path);
// すでにロード済み
if (contains)
{
var cachedEntity = GetEntity<T>(path);
cachedEntity = cachedEntity.IncreaseRefCount();
SetEntity<T>(cachedEntity);
return cachedEntity.Handle.Result as T;
}
var handle = Addressables.LoadAssetAsync<T>(path);
await handle;
if (handle.Status != AsyncOperationStatus.Succeeded)
{
throw new ArgumentNullException(handle.Status.ToString());
}
var entity = new AssetEntity(path, 1, handle);
SetEntity<T>(entity);
return handle.Result;
}
// アセットアンロード
public static void Release<T>(string path)
{
if (ContainsKey<T>(path) == false)
{
return;
}
var entity = GetEntity<T>(path);
entity = entity.DecreaseRefCount();
if (entity.RefCount > 0)
{
return;
}
// アンロード
Addressables.Release(entity.Handle);
RemoveEntity<T>(path);
}
}
}
何かあれば@ruchi12377まで!
以上です。