본문 바로가기
유니티/오류 코드와 잘못된 개념 정리(기록용)

어드레서블 에셋 로드 구현

by fore4022 2024. 7. 30.

  아래의 코드는 빌드 해보기 이전까지 사용했었습니다. 하지만, 어드레서블로 불러온 에셋의 인스턴스를 만들고 Release 하는 동작이 빌드 환경에서 오류가 발생한다는 것을 알았습니다.

 에디터와 달리 빌드 환경에서는 에셋이 Relase 되면, missing이 되어버립니다.


 항상 어드레서블 에셋 사용이 필요할 때마다 일일이 구현하는 번거로움을 줄이고자 LoadToPath, LoadToLable을 만들게 되었다.

본인이 이해한 내용을 바탕으로 만들었기에 성능 최적화나, 모든 경우에 대한 오류의 대응이 미흡할 수 있다. 본인도 사용하면서 수정하거나, 조금이라도 더 최적화를 한다면, 여기의 내용도 그때 그때 수정할 것이다.


using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using Object = UnityEngine.Object;
public class Util
{
    public static async Task<T> LoadToPath<T>(string path) where T : Object
    {
        AsyncOperationHandle<T> handle = Addressables.LoadAssetAsync<T>(path);

        await handle.Task;

        T result = handle.Result;

        Addressables.Release(handle);

        return result;
    }
    public static async Task<List<T>> LoadToLable<T>(string lable) where T : Object
    {
        AsyncOperationHandle<IList<T>> handle = Addressables.LoadAssetsAsync<T>(lable, null);	

        await handle.Task;

        List<T> resultList = new List<T>();

        foreach(T result in handle.Result)
        {
            resultList.Add(result);
        }

        Addressables.Release(handle);

        return resultList;
    }
}
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
public class Test_LoadToPath : MonoBehaviour
{
    private GameObject obj;

    private async void Start()
    {
        await Addressables.InitializeAsync().Task;

        obj = await Util.LoadToPath<GameObject>("test");
    }
    private void Update()
    {
        Debug.Log(obj);
    }
}// 실행 결과 : 즉시 obj에 test라는 경로를 가진 에셋이 할당되지 않아서, NullReference 오류가 발생한다. 어드레서블 에셋이 불러와진 후에는 obj에 정상적으로 경로에 맞는 에셋이 들어가, 로그를 통해서 정상적으로 불러와졌음을 알 수 있다
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
public class Test_LoadToLable : MonoBehaviour
{
    private List<GameObject> objList;

    private async void Start()
    {
        await Addressables.InitializeAsync().Task;

        objList = await Util.LoadToLable<GameObject>("testLable");
    }
    private void Update()
    {
    	foreach(GameObject gameObject in objList)
        {
        	Debug.Log(gameObject);
        }
    }
}//실행 결과 : 즉시 obj 리스트에 testLable이라는 레이블을 지닌 에셋들이 할당되지 않아서, NullReference 오류가 발생한다. 어드레서블 에셋이 불러와진 후에는 obj 리스트에 정상적으로 지정한 레이블을 가지는 에셋들이 들어가, 로그를 통해서 정상적으로 불러와졌음을 알 수 있다.
using System.Collections;
using UnityEngine;
public class Test : MonoBehaviour
{
    private GameObject go;

    private string path;

    private void Start()
    {
        StartCoroutine(TestCoroutine());
    }
    private async void Load()
    {
        go = await Util.LoadToPath<GameObject>(path);
    }
    private IEnumerator TestCoroutine()
    {
        Load();

        yield return new WaitUntil(() => go != null);
        
        Debug.Log("test");
    }
}//실행 결과 : 코루틴 내에서 Load()의 실행이 끝날 때까지 기다린다. 실행이 끝나면서 go가 null이 아니게 되면서 로그가 출력된다.


 아직 많이 부족한 코드이니, 틀린 점이나 개선 여지가 있는 것을 지적해주세요.

 오늘도 방문해 주셔서 감사합니다.

 

최근 수정 날짜 : 2024.9.3