[Unity] 어드레서블(Addressable) 빠르게 사용해 보기 (3/4) - 비동기로 리소스를 로드(Load)하고 사용하기
어드레서블(Addressable)은 비동기(Async)로 사용하는 것이 기본입니다.
문제는 프로젝트가 크지 않다면 이득이 크지 않은데 그에 비해 코드가 복잡해진다는 단점 있습니다.
어드레서블에서 리소스를 사용하는 사이클은 크게 3부분으로 나눕니다.
1) 리소스 로드
2) 리소스 사용하여 인스턴스 만들기
3) 인스턴스 해제
0. 리소스 준비
프리팹은 아래와 같이 등록되어 있습니다.
원하는 리소스를 한 개만 로드하려는 경우 해당 리소스의 경로(Path)를 알고 있어야 합니다.
비동기로 사용하는 경우 함수가 끝나고 유니티의 라이프사이클에 따라 동작 순서가 달라집니다.
그래서 비동기 처리가 끝나면 동작할 함수를 따로 만들어서 관리해야 합니다.
(이런 이론적인 내용은 여기서 다룰 게 아니라서 그냥 넘어갑니다 ㅎㅎㅎㅎ)
1. 리소스 불러오기(Load)
한 개의 리소스를 불러올 때는 동기와 마찬가지로 'Addressables.LoadAssetAsync'를 사용합니다.
대신 이 함수는 비동기로 동작하는 함수이므로 로드가 끝났을 때 동작할 '.Completed'이벤트를 연결해 주어야 합니다.
//프리팹 로드 시작
Addressables.LoadAssetAsync<GameObject>(sKeyPath).Completed
+= (handle) =>
{
if(handle.Status == AsyncOperationStatus.Succeeded)
{
//프리팹 저장
GameObject loadGO = handle.Result;
Debug.Log("GameObject 로드 성공!");
}
else
{
throw new System.Exception("프리팹 로드 실패 : " + sKeyPath);
}
};
(참고 : github - dang-gun/UnitySamples/AddressableSamples/Addressable_OneAsync.cs)
2번 줄, 3번 줄 : 람다식으로 'Completed'이벤트를 연결합니다.
매개변수인 'handle'로 읽어 들인 결과가 넘어옵니다.
5번 줄 : '.Status'를 통해 어드레서블에 에셋을 로드 요청이 성공했는지 확인 할 수 있습니다.
8번 줄 : 'handle.Result'를 통해 로드된 리소스를 받을 수 있습니다.
유의 사항은 동기 때와 똑같습니다.
하지만 이렇게 사용하면 어드레서블의 자원 관리기능 밖에서 사용하는 것이라 자원 해제시 문제가 될 수 있습니다.
2. 리소스 사용하기
동기와 마찬가지로 어드레서블의 'Addressables.InstantiateAsync'를 사용합니다.
이 메서드를 통해 생성된 인스턴스의 개수가 어드레서블에서 관리된다고 합니다.
위에서와 마찬가지로 '.Completed'이벤트를 연결하여 사용합니다.
Addressables.InstantiateAsync(sKeyPath, v3Start, Quaternion.identity).Completed
+= (handle) =>
{
if (handle.Status == AsyncOperationStatus.Succeeded)
{
//생성된 개체 로드
GameObject newGO = handle.Result;
}
else
{
throw new System.Exception("프리팹 인스턴스 생성 실패 : " + sKeyPath);
}
};
(참고 : github - dang-gun/UnitySamples/AddressableSamples/Addressable_OneAsync.cs)
1번 줄 : 어드레서블에 에셋을 로드 요청을 만듭니다.
어드레서블에서 생성한 경로(Path)를 전달해야 합니다.
2번 줄 : 매개변수인 'handle'로 읽어 들인 결과가 넘어옵니다.
4번 줄 : 'handle.Status'로 생성이 성공했는지 알 수 있습니다.
7번 줄 : 'handle.Result'로 생성된 개체를 받을 수 있습니다.
생성된 개체는 따로 저장해 두어야 자원을 해제할 때 사용할 수 있습니다.
3. 인스턴스 해제(Release)
어드레서블에서 인스턴스를 해제할 때는 'Addressables.ReleaseInstance'를 사용합니다.
동작은 'UnityEngine.Destroy'와 동일합니다.
대신 어드레서블이 관리하는 리소스 정보를 갱신하게 됩니다.
Addressables.ReleaseInstance([생성된 인스턴스]);
(참고 : github - dang-gun/UnitySamples/AddressableSamples/Addressable_OneAsync.cs)
마무리
테스트 프로젝트 : github - dang-gun/UnitySamples/AddressableSamples
사용 방법은 동기와 크게 다르지 않습니다.
프로젝트가 커진다면 리소스하나의 크기도 커지기므로 이럴 때 동기로 로드하면 랙이 걸릴 수 있습니다.
이럴 때는 비동기로 리소스를 부르고 생성해야 합니다.
필요하다면 로딩 타임을 따로 두고 자주 쓰는 리소스를 미리 불러오는 작업을 해야 하죠.