프로그래밍/Unity, MAUI, Mono

[Unity] 어드레서블(Addressable) 빠르게 사용해 보기 (2/4) - 동기(Sync)로 리소스를 로드(Load)하고 사용하기

당근천국 2024. 6. 28. 15:30

어드레서블(Addressable)은 비동기(Async)로 사용하는 것이 기본이지만 동기(Sync)로도 사용할 수 있습니다.

규모가 크지 않은 프로그램에서는 굳이 비동기로 리소스를 처리할 이유가 없으므로 동기로 사용하는 방법부터 알아보겠습니다.

 

어드레서블에서 리소스를 읽어 들이는 건(Load)메모리에 올리는 작업이 아닙니다.

스크립트에서 유니티의 프리팹을 사용할 때와 똑같습니다.

개체 읽어 들이는 과정과 개체를 화면에 표시('계층 구조'에 추가)하는 단계를 따로 처리해야 하는 것과 같습니다.

 

어드레서블에서 리소스를 사용하는 사이클은 크게 3부분으로 나눕니다.

1) 리소스 로드

2) 리소스 사용하여 인스턴스 만들기

3) 인스턴스 해제

 

연관글 영역

 

 

0. 리소스 준비 

프리팹은 아래와 같이 등록되어 있습니다.

 

원하는 리소스를 한 개만 로드하려는 경우 해당 리소스의 경로(Path)를 알고 있어야 합니다.

 

 

 

1. 리소스 불러오기(Load) 

한 개의 리소스를 불러올 때는 'Addressables.LoadAssetAsync'를 사용합니다.

 

이 함수는 비동기 함수지만 동기로 사용할 수 있습니다.

어드레서블에서 지원하는 'WaitForCompletion'는 메서드를 이용하면 됩니다.

//프리팹 로드 시작
AsyncOperationHandle<GameObject> loadAsset 
    = Addressables.LoadAssetAsync<GameObject>(sKeyPath);
GameObject loadGO = loadAsset.WaitForCompletion();

if (loadAsset.Status == AsyncOperationStatus.Succeeded)
{
}
else
{
    throw new System.Exception("프리팹 로드 실패 : " + sKeyPath);
}

(참고 : github - dang-gun/UnitySamples/AddressableSamples/Addressable_OneSync.cs )

 

1번 줄, 2번 줄 : 어드레서블에 에셋을 로드 요청을 만듭니다.

이때 읽어 들일 리소스의 경로(Path) 정보를 전달해 줍니다.

Addressables.LoadAssetAsync는 비동기 함수이므로 아직 동작하지 않습니다.

(이 메서드가 끝나고 라이프 사이클에 따라 동작합니다.)

 

 

4번 줄 : '.WaitForCompletion()'를 호출하여 위에서 만든 요청을 동기로 바로 호출하여 결과를 받습니다.

 

6번 줄 : '.Status'를 통해 어드레서블에 에셋을 로드 요청이 성공했는지 확인 할 수 있습니다.

 

 

로드된 'GameObject'를 따로 저장해놨다가 직접 사용할 수 있습니다.

하지만 이렇게 사용하면 어드레서블의 자원 관리기능 밖에서 사용하는 것이라 자원 해제시 문제가 될 수 있습니다.

 

어드레서블의 자원 관리기능을 사용하려면 'GameObject'를 따로 저장해둘 필요는 없습니다.

 

 

 

2. 리소스 사용하기 

유니티에서 로드된 리소스의 인스턴스를 만들어 '계층 구조'에 추가할 때 'UnityEngine.Instantiate'를 사용합니다.

 

어드레서블에서는 'Addressables.InstantiateAsync'를 사용합니다.

이 메서드를 통해 생성된 인스턴스의 개수가 어드레서블에서 관리된다고 합니다.

//프리팹의 인스턴스를 생성하여 개층 구조(화면)에 추가한다.(= 메모리에 로드)
AsyncOperationHandle<GameObject> prefabNew
    = Addressables.InstantiateAsync(sKeyPath, v3Start, Quaternion.identity);

//생성 시도
GameObject newGO = prefabNew.WaitForCompletion();

if (prefabNew.Status == AsyncOperationStatus.Succeeded)
{//생성 성공
}
else
{
    throw new System.Exception("프리팹 인스턴스 생성 실패 : " + sKeyPath);
}

(참고 : github - dang-gun/UnitySamples/AddressableSamples/Addressable_OneSync.cs )

 

1번 줄, 2번 줄 : 어드레서블에 에셋을 로드 요청을 만듭니다.

게임 오브젝트 대신 경로(Path)를 준다는 것외에는 'UnityEngine.Instantiate'와 거의 비슷합니다.

Addressables.InstantiateAsync는 비동기 함수이므로 아직 동작하지 않습니다.

(이 메서드가 끝나고 라이프 사이클에 따라 동작한다.)

 

6번 줄 : 위에서 만든 요청을 바로 실행시킵니다.

요청이 성공하면 '계층 구조'에 추가되고 화면에 표시됩니다.

 

8번 줄 : '.Status'를 통해 어드레서블에 에셋을 생성 요청이 성공했는지 확인 할 수 있습니다.

 

 

생성된 개체는 따로 저장해 두어야 자원을 해제할 때 사용할 수 있습니다.

 

 

3. 인스턴스 해제(Release) 

유니티에서 생성된 인스턴스를 해제하려면 'UnityEngine.Destroy'를 사용합니다.

어드레서블을 사용할 때는 'Addressables.ReleaseInstance'를 사용합니다.

 

동작은 'UnityEngine.Destroy'와 동일합니다.

대신 어드레서블이 관리하는 리소스 정보를 갱신하게 됩니다.

Addressables.ReleaseInstance([생성된 인스턴스]);

(참고 : github - dang-gun/UnitySamples/AddressableSamples/Addressable_OneSync.cs )

 

 

 

 

마무리 

테스트 프로젝트 : github - dang-gun/UnitySamples/AddressableSamples

 

유니티에서는 비동기를 동기로 처리하는 방식을 .NET에서 일반적인 사용하는 방법으로 사용하면 안 되는 경우가 있습니다.

이 경우가 그랬습니다 ㅜㅡ

한참 동작을 안 해서 고생했는데...... 어드레서블 자체 메서드를 사용하니까 한 번에 되네요 ㅎㅎㅎㅎ