본문 바로가기
Unity/어드레서블 에셋 시스템

어드레서블 에셋 시스템 - 개념: 어드레서블 API 요약 & 정리

by PlaneK 2020. 6. 29.

요약 

모든 개념을 요약해서 API의 활용에 대해 정리해보자. (어드레서블 버전 1.10.0)

에셋을 로드하는 방법은 크게 4가지 이다.

① 어드레서블 명으로 로드하기

② 레이블로 로드하기

AssetReference 클래스로 로드하기

IResourceLoaction으로 로드하기

IResourceLocation은 카탈로그로부터 얻어온 값으로, 에셋번들의 경로이다. 

우리에게 주어져 있는 정보는 아니다. 위 API를 통해 얻어온다.

(위 API는 경로만 추출할 뿐 에셋을 로드하지 않는다)

방법이 많은 것 같지만 위 4가지는 로드 함수의 인자일 뿐이다. 

로드하는 방법은 단순하다. 로드함수에 4가지 중 하나를 인자로 넣고 호출하면 된다.

GameObject를 생성하는 것으로 예시를 살펴보자.

① 어드레서블 명으로 로드하기

public class AddressablesLoader : MonoBehaviour
{
    public string addressableName = "SomePrefab";
 
    public void LoadPrefab()
    {
        /* GameObject는 Load 보다는 InstantiateAysnc로 직접 생성해야 한다. */
        //Addressables.LoadAssetAsync<GameObject>(addressableName);

       Addressables.InstantiateAsync(addressableName);
    }
}
 

GameObject는 Load하지 않고 InstantiateAsync를 통해 바로 생성하는 것이 낫다.

어드레서블의 Release함수는 Ref Count가 0인지 체크하고 자동해제한다. Ref Count의 대상은 어드레서블로 생성된 개체로 제한된다.

GameObject.Instantiate를 사용하면 Ref Count에 포함될 수 없기 때문에 Release로 인해 씬에 존재하는 개체들이 불안정하게 사라지거나 깨진다.

따라서 게임오브젝트의 에셋을 로드하기보단 바로 생성하는 것이 더 낫다.

② 레이블로 로드하기

public class FilteredReferences : MonoBehaviour
{
    public AssetLabelReference assetLabel;
 
    public void LoadPrefab()
    {
        // 1안, 직접입력
        Addressables.InstantiateAsync("SomeLabel");
        // 2안, AssetLabelReference 사용
        Addressables.InstantiateAsync(assetLabel.labelstring);
        // 3안, 경로 얻어와서 로드하기
        Addressables.LoadResourceLocationsAsync("SomeLabel").Completed +=
            (handle) =>
            {
               var locations = handle.Result;
               Addressables.InstantiateAsync(locations[0]);
            };
    }
}
 

레이블은 위와 같이 3가지 방식으로 사용된다.

1안과 2안은 레이블에 해당하는 에셋 중 하나만 로드한다.

AssetLabelReference를 사용하면 드랍박스로 레이블을 선택할 수 있다.

어드레서블 명과 레이블이 중복되는 것을 피하자.

"Cube"로 로드하면 Capsule.prefab이 로드됐다. 둘 간 우선순위는 없는 것 같다. 랜덤하게 생성됨.

③ AssetReference로 로드하기

public class AddressablesLoader : MonoBehaviour
{
    public AssetReferenceGameObject assetReferenceGameObject;
 
    public void LoadPrefab()
    {
        // 1안, 직접 생성
        assetReferenceGameObject.InstantiateAsync();
        // 2안, guid를 key값으로 함수 호출
        Addressables.InstantiateAsync(assetReferenceGameObject);
    }
}
 

AssetReferenceGameObject를 통해 직접 생성 하거나 guid값으로 생성 함수를 호출한다.

AssetReferenceGameObject를 사용하면 드랍박스로 어드레서블 에셋을 선택할 수 있다.

④ IResourceLoacation으로 로드하기

public class AddressablesLoader : MonoBehaviour
{
    public void LoadPrefab()
    {
        // 1안, 어드레서블 명으로 경로 얻기.
        Addressables.LoadResourceLocationsAsync("SomeAddrsaalbeName").Completed +=
            (handle) =>
            {
               var locations = handle.Result;

               Addressables.InstantiateAsync(locations[0]);
            };

        // 2안, 레이블로 경로 얻기
        Addressables.LoadResourceLocationsAsync("SomeLabel").Completed +=
            (handle) =>
            {
               var locations = handle.Result;

               Addressables.InstantiateAsync(locations[0]);
            };
    }
}
 

LoadResourceLocationsAsync를 통해 IResourceLoaction을 얻을 수 있다. (마찬가지로 key값을 인자로 호출)

얻은 경로를 인자로 로드 함수를 호출한다.

 

로드 API

로드 함수를 정리해보자.

단일 에셋 로드

Addressables.LoadAssetAsync<TObject>('key' 또는 'IResourceLocation') : 에셋을 메모리에 로드.

Addressables.InstantiateAsync('key' 또는 'IResourceLocation') : 에셋을 게임오브젝트로 생성한다.

Addressables.LoadSceneAsync('key'  또는 'IResourceLocation') : 씬을 로드한다.

AssetReference.LoadAssetAsync<TObject>() : 에셋 레퍼런스로 에셋을 메모리에 로드한다.

AssetReference.InstantiateAsync() : 에셋 레퍼런스로 게임오브젝트를 생성한다.

AssetReference.LoadSceneAsync() : 에셋 레퍼런스로 씬을 로드한다.

다수 에셋 로드

Addressables.LoadAssetsAsync<TObject>('key' 또는 'IResourceLocation', 'Action<TObject> callback') : key에 해당하는 에셋들을 모두 로드한다. (callback은 각 개체가 로드될 때마다 호출된다.)

모든 로드 함수는 위 AsyncOperationHandle<TObject> 구조체를 반환한다. 프로퍼티 중 제일 많이 쓰이는 것들을 정리했다.

 

언로드 API

언로드 API를 정리해보자.

Addressables.ReleaseAsset('AsyncOperationHandle' 또는 'object')
                                                                             <-> Addressables.LoadAssetsAsync

Addressables.ReleaseInstance('AsyncOperationHandle' 또는 'object')
                                                                             <-> Addressalbes.InstantiateAsync

Addressables.UnloadSceneAsync('AsyncOperationHandle' 또는 'SceneIsntance')
                                                                             <-> Addressables.LoadSceneAysnc

AssetReference.ReleaseAsset() <-> AssetReference.LoadAssetAsync

AssetReference.ReleaseInstance() <-> AssetReference.InstantiateAsync

AssetReference.UnLoadScene() <-> AssetReference.LoadSceneAsync() 

Addressalbes.InstantiateAsync로 생성된 함수는 반드시 Addressables.ReleaseInstance로 해제해준다.

ㆍDestroy('object') <-> GameObject.Instantiate(...)

GameObject로 생성된 게임오브젝트는 어드레서블로 해제할 수 없으니 Destroy를 사용한다.

 

Release를 호출하면 ref count가 0인지 확인하고 자동 해제된다.

어드레서블의 머티리얼은 Cube가 참조하고 있다. 따라서 머터리얼의 ref count는 1이다.

그런데 머티리얼을 Release하니까 그대로 해제되버려서 깨져버린 상태다.

그 이유는 해당 Cube는 어드레서블이 아닌 GameObject.Instantiate을 통해 생성됐기 때문이다.

Release함수는 어드레서블로 생성된 개체들만 ref count로 취급하기 때문에 위 Cube는 ref count의 대상이 아닌 것이다.

때문에 ref count를 유의하고 어드레서블로 생성하는 것이 낫다.

 

기타 API

기타 API를 정리해보자.

아래 API들은 에셋을 메모리에 로드하진 않지만 다른 리소스들을 메모리에 할당한다.
("그런데 Release해줄만큼 크기가 크진 않은 것 같다.")

Addressables.LoadResourceLocationsAsync('key') : key에 해당하는 에셋들의 경로(IResourceLocation)를 가져온다. 메모리에 에셋을 로드하진 않는다.

Addressables.GetDownloadSizeAsync('key') : 캐시 폴더에 해당 에셋 번들이 있는지 체크한다. 있으면 0을 반환하고 없으면 해당 에셋 번들의 사이즈를 반환한다.

Addressables.DownloadDependenciesAsync('key') : 해당 에셋이 의존하는 모든 에셋의 번들 파일을 다운받는다. 메모리에 에셋을 로드하진 않는다. "PreLoad(미리 다운받기)에 사용된다"

Addressables.DownloadDependenciesAsync('key')

Dependencies는 프로젝트 뷰에서 리소스를 우클릭하면 볼 수 있다. 

메뉴를 선택하면 해당 프리팹이 사용하고 있는 에셋들이 모두 셀렉트 된다.

Prefab_Cube를 인자로 함수호출 시 'Asset/Materials/blue.mat'에 대한 번들 파일이 있는지 없는지 체크한다. 번들파일(DefaultLocalGroup_Hash.bundle)이 없으면 다운받는다.

 

댓글