#nullable enable
using Cysharp.Threading.Tasks;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace UVC.Util
{
///
/// Unity 리소스를 관리하고 비동기적으로 로드하는 기능을 제공합니다.
///
/// 클래스는 로드된 리소스의 내부 캐시를 유지하여
/// 후속 액세스를 최적화합니다. 리소스는 키별로 비동기적으로 로드하거나 키 목록을 사용하여 대량으로 로드할 수 있습니다.
///
public static class ResourceManager
{
private static Dictionary _resources = new();
///
/// 문자열 키로 매핑된 리소스가 포함된 읽기 전용 사전을 가져옵니다.
///
public static IReadOnlyDictionary get => _resources;
///
/// 지정된 경로에서 지정된 유형의 리소스를 비동기적으로 로드합니다.
///
/// 이 메서드는 Unity의 를 사용하여
/// 리소스를 비동기적으로 로드합니다. 지정된 리소스가 지정된 경로에 있는지 확인하여
/// 을 반환하지 않도록 합니다.
/// 로드할 리소스의 유형입니다. 에서 파생되어야 합니다.
/// 리소스 폴더 내 리소스 경로입니다. 이 경로는 리소스 폴더를 기준으로 하며
/// 파일 확장자를 포함하지 않아야 합니다.
/// 비동기 작업을 나타내는 작업입니다. 결과에는 로드된 리소스 유형이 포함됩니다.
/// (리소스가 발견되면); 그렇지 않으면 .
public static async UniTask LoadOnlyAsync(string path) where T : UnityEngine.Object
{
var request = Resources.LoadAsync(path);
await request;
return request.asset as T;
}
///
/// Unity 리소스 시스템에서 지정된 유형의 리소스를 비동기적으로 로드합니다.
///
/// 리소스가 이미 캐시된 경우, 새로운 로드 작업을 수행하지 않고 즉시 반환됩니다.
/// 그렇지 않은 경우, 리소스는 비동기적으로 로드되어 나중에 사용할 수 있도록 캐시에 추가됩니다.
///
/// 로드할 리소스의 유형입니다. 의 하위 클래스여야 합니다.
/// Unity 리소스 시스템에서 리소스를 찾는 데 사용되는 키 또는 경로입니다.
/// 로드된 리소스와 함께 호출할 선택적 콜백입니다. 콜백은 로드된 리소스를
/// 또는 (리소스를 로드할 수 없는 경우) 유형으로 받습니다.
/// 비동기 작업을 나타내는 작업입니다. 작업 결과는
/// 또는 (리소스를 로드할 수 없는 경우) 유형으로 로드된 리소스입니다.
public static async UniTask LoadAsync(string key, Action? callback = null) where T : UnityEngine.Object
{
T? t = null;
if (_resources.TryGetValue(key, out var resource))
{
t = resource as T;
callback?.Invoke(t);
return t;
}
var operation = Resources.LoadAsync(key);
await operation;
_resources.TryAdd(operation.asset.name, operation.asset);
t = operation.asset as T;
callback?.Invoke(t);
return t;
}
///
/// 지정된 프리팹 경로 목록에서 모든 에셋을 비동기적으로 로드합니다.
///
/// 이 메서드는 프리팹 경로 목록을 순차적으로 처리하여 각 에셋을
/// 비동기적으로 로드합니다. 콜백이 제공된 경우, 로드 작업의 진행 상황을 추적하는 데 사용할 수 있습니다.
///
/// 로드할 에셋의 유형입니다. 에서 파생되어야 합니다.
/// 로드할 프리팹 경로 목록입니다.
/// 각 에셋이 로드된 후 호출되는 선택적 콜백입니다. 이 콜백은 로드된 에셋의 경로,
/// 현재 로드된 에셋의 개수, 그리고 로드할 에셋의 총 개수를 받습니다.
public static async void LoadAllAsync(List prefabPath, Action? callback = null) where T : UnityEngine.Object
{
int loadCount = 0;
int totalCount = prefabPath.Count;
// preloadKeys 배열의 주소들을 로드
foreach (var key in prefabPath)
{
await LoadAsync(key);
loadCount++;
callback?.Invoke(key, loadCount, totalCount);
}
}
}
}