어드레서블 에셋 로드 소개
Addressables
클래스에서는 어드레서블 에셋을 로드하는 방법을 제공합니다. 한 번에 하나 또는 배치별로 에셋을 로드할 수 있습니다. 로드할 에셋을 식별하려면 단일 키 또는 키 목록을 로드 메서드에 전달합니다. 키는 다음 오브젝트 중 하나가 될 수 있습니다.
- Address: 에셋에 할당한 주소가 포함된 문자열입니다.
- Label: 하나 이상의 에셋에 할당된 레이블을 포함하는 문자열입니다.
- AssetReference 오브젝트:
AssetReference
의 인스턴스입니다. IResourceLocation
인스턴스: 에셋 및 그 종속성을 로드하는 방법을 설명하는 중간 오브젝트입니다.
어드레서블이 에셋을 로드하는 방법
에셋 로드 메서드 중 하나를 호출하면 어드레서블 시스템은 다음 작업을 수행하는 비동기 작업을 시작합니다.
IResourceLocation
키를 제외하고 지정된 키에 대한 리소스 위치를 조회합니다.- 종속성 목록을 수집합니다.
- 필요한 원격 에셋 번들을 다운로드합니다.
- 에셋 번들을 메모리에 로드합니다.
- 작업의
Result
오브젝트를 로드된 오브젝트로 설정합니다. - 작업의
Status
를 업데이트하고Completed
이벤트 리스너를 호출합니다.
로드 작업이 성공하면 Status
가 Succeeded
로 설정되고, 로드된 오브젝트는 Result
오브젝트에서 액세스할 수 있습니다.
오류가 발생하면 예외가 작업 오브젝트의 OperationException
멤버에 복사되고 Status
가 Failed
로 설정됩니다. 기본적으로 예외는 작업의 일부로 발생하지 않습니다. 하지만 예외를 처리하기 위해 ResourceManager.ExceptionHandler
프로퍼티에 핸들러 함수를 할당할 수 있습니다. 또한 어드레서블 시스템 설정에서 Log Runtime Exceptions 옵션을 활성화하여 Unity 콘솔에 오류를 기록할 수 있습니다.
여러 개의 어드레서블 에셋을 로드하는 로드 메서드를 호출할 때, 단일 로드 작업이 실패할 경우 전체 작업을 중단할지 아니면 가능한 모든 에셋을 로드할지 여부를 지정할 수 있습니다. 두 경우 모두 작업 상태는 실패로 설정됩니다. 실패 시 전체 작업을 중단하려면 로드 메서드 호출에서 releaseDependenciesOnFailure
파라미터를 true
로 설정합니다.
비동기 작업과 Unity 스크립트에서의 비동기 코드 작성에 대한 자세한 내용은 작업을 참조하십시오.
로드된 에셋과 키 연결
Unity가 개별 에셋을 로드하는 순서는 로드 메서드에 전달하는 목록의 키 순서와 다를 수도 있습니다.
결합된 작업에서 에셋을 로드하는 데 사용된 키와 에셋을 연결해야 하는 경우 다음 단계에 따라 작업을 수행할 수 있습니다.
- 에셋 키 목록을 사용하여
IResourceLocation
인스턴스를 로드합니다. IResourceLocation
인스턴스를 키로 사용하여 개별 에셋을 로드합니다.
IResourceLocation
오브젝트는 키 정보를 포함하므로, 예를 들어 키를 에셋과 연관시키기 위해 사전을 활용할 수 있습니다. LoadAssetsAsync
와 같은 로드 메서드를 호출하면, 작업에서는 먼저 키에 해당하는 IResourceLocation
인스턴스를 조회한 다음 이를 사용하여 에셋을 로드합니다. IResourceLocation
을 사용하여 에셋을 로드하는 경우 첫 번째 단계를 건너뛰므로 두 단계로 작업을 수행해도 작업이 많이 추가되지는 않습니다.
다음 예제에서는 키 목록에 대한 에셋을 로드하고 해당 주소(PrimaryKey
)로 사전에 삽입합니다. 이 예제에서는 먼저 지정된 키에 대한 리소스 위치를 로드합니다. 해당 작업이 완료되면 Completed
이벤트를 사용하여 각 위치에 대한 에셋을 로드하고 개별 작업 핸들을 사전에 삽입합니다. 작업 핸들을 사용하여 에셋을 인스턴스화하고, 에셋이 더 이상 필요하지 않은 경우 해제할 수 있습니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Events;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceLocations;
internal class LoadWithLocation : MonoBehaviour
{
public Dictionary<string, AsyncOperationHandle<GameObject>> operationDictionary;
public List<string> keys;
public UnityEvent Ready;
IEnumerator LoadAndAssociateResultWithKey(IList<string> keys)
{
if (operationDictionary == null)
operationDictionary = new Dictionary<string, AsyncOperationHandle<GameObject>>();
AsyncOperationHandle<IList<IResourceLocation>> locations
= Addressables.LoadResourceLocationsAsync(keys,
Addressables.MergeMode.Union, typeof(GameObject));
yield return locations;
var loadOps = new List<AsyncOperationHandle>(locations.Result.Count);
foreach (IResourceLocation location in locations.Result)
{
AsyncOperationHandle<GameObject> handle =
Addressables.LoadAssetAsync<GameObject>(location);
handle.Completed += obj => operationDictionary.Add(location.PrimaryKey, obj);
loadOps.Add(handle);
}
yield return Addressables.ResourceManager.CreateGenericGroupOperation(loadOps, true);
Ready.Invoke();
}
void Start()
{
Ready.AddListener(OnAssetsReady);
StartCoroutine(LoadAndAssociateResultWithKey(keys));
}
private void OnAssetsReady()
{
float x = 0, z = 0;
foreach (var item in operationDictionary)
{
Debug.Log($"{item.Key} = {item.Value.Result.name}");
Instantiate(item.Value.Result,
new Vector3(x++ * 2.0f, 0, z * 2.0f),
Quaternion.identity, transform);
if (x > 9)
{
x = 0;
z++;
}
}
}
private void OnDestroy()
{
foreach (var item in operationDictionary)
{
Addressables.Release(item.Value);
}
}
}
로드 메서드는 ResourceManager.CreateGenericGroupOperation
을 사용하여 그룹 작업을 생성합니다. 이렇게 하면 모든 로드 작업이 완료된 후에도 메서드를 계속할 수 있습니다. 이 경우 메서드는 다른 스크립트에 로드된 데이터를 사용할 수 있음을 알리기 위해 Ready
이벤트를 디스패치합니다.