본문 바로가기

[Unity3D] 에셋번들(AssetBundle) 로드

·
2019. 10. 30. 18:10
반응형

에셋번들(AssetBundle) 로드

출처 :  https://docs.unity3d.com/550/Documentation/Manual/AssetBundlesIntro.html

에셋번들 로드는 에셋번들에 들어있는 에셋을 불러오는 것을 의미합니다.

에셋번들을 로드하는데에는 여러가지 함수가 있습니다.

[Unity3D] 에셋번들(AssetBundle) 빌드 에서 빌드한 에셋번들 파일을 로드하는 예제로 설명하겠습니다.

 

AssetBundle 클래스 사용

AssetBundle.LoadFromMemoryAsync(byte[] binary) 함수는 파일의 바이트 배열을 읽어서 에셋번들을 비동기 방식으로 로드합니다.

 9 : 로드할 에셋번들 경로

11 : 에셋번들로드 코루틴 시작

22 : 경로로부터 모든 바이트를 읽어서 메모리에 비동기로 로드

24 : 바이트를 모두 읽을 때까지 대기

27 : 에셋번들 클래스로 Stone 게임오브젝트 로드

28 : Stone 게임오브젝트 생성

30 : 에셋번들 클래스로 Brick 게임오브젝트 로드

31 : Brick 게임오브젝트 생성

 

LoadAssetBundlesFromMemory 스크립트를 빈 게임오브젝트에 추가 후 게임을 플레이합니다.

 

AssetBundle.LoadFromFile(string path) 함수는 디스크에서 직접 에셋번들을 로드합니다.

압축되지 않은 에셋번들을 로드할 때 유용합니다.

 9 : 파일로부터 에셋번들 로드

17 : 에셋번들 클래스로 Stone 게임오브젝트 로드

18 : Stone 게임오브젝트 생성

20 : 에셋번들 클래스로 Brick 게임오브젝트 로드

21 : Brick 게임오브젝트 생성

 

 LoadAssetBundlesFromFile 스크립트를 빈 게임오브젝트에 추가 후 게임을 플레이합니다.

 

UnityWebRequest 클래스 사용

UnityWebRequest 클래스는 에셋번들을 처리하는 함수를 가지고 있습니다.

에셋번드을 로드하려면 UnityWebRequest.GetAssetBundle을 사용해서 웹 요청을 만들고 요청이 완료되면 요청 오브젝트를 DownloadHandlerAssetBundle.GetContent(UnityWebRequest)로 전달하고 GetContet()를 사용해서 에셋번들을 로드할 수 있습니다. (WWW 클래스를 사용해서도 에셋번들을 로드할 수 있지만 유니티에서 WWW 클래스는 지원 중단할 예정 이므로 WWW 클래스를 사용하는 것 보다 최신 API인 UnityWebRequest 클래스를 사용할 것을 권장합니다.)

 

UnityWebRequest.Send()는 사용되지 않습니다.

14 : 로드할 에셋번들 경로

15 : HTTP GET 메소드를 통해 에셋번들을 다운로드할 UnityWebRequest를 생성

17 : 요청이 완료될 때까지 대기

19 : 요청이 완료된 UnityWebRequest를 DownloadHandlerAssetBundle에 인자로 넘겨준 후 에셋번들 로드

20 : 에셋번들 클래스로 Stone 게임오브젝트 로드

21 : Stone 게임오브젝트 생성

23 : 셋번들 클래스로 Brick 게임오브젝트 로드

24 : Brick 게임오브젝트 생성

 

비동기 방식으로 로드할 경우

20 : Stone 게임오브젝트 AssetBundleRequest 생성

22 : Stone 게임오브젝트가 로드될 때까지 대기

24 : AssetBundleRequest로 Stone 게임오브젝트 로드

25 : Stone 게임오브젝트 생성

27 : Brick 게임오브젝트 AssetBundleRequest 생성

29 : Brick 게임오브젝트가 로드될 때까지 대기

31 : AssetBundleRequest로 Brick 게임오브젝트 로드

32 : Brick 게임오브젝트 생성

 

 LoadAssetBundlesFromUnityWebRequest 스크립트를 빈 게임오브젝트에 추가 후 게임을 플레이합니다.

 

모든 에셋번들 로드

에셋번들을 로드할 때 에셋번들에 포함된 모든 에셋을 로드할 수도 있습니다.

AssetBundle.LoadAllAssets<T>() 함수는 모든 에셋을 로드합니다.

 

로드된 에셋번들 관리

에셋번들을 로드하고 나면 로드된 에셋번들을 언로드해야 합니다.

에셋번들을 언로드하지 않거나 잘못 언로드하면 메모리 중복 혹은 에셋이 누락되는 등의 상황이 발생할 수 있습니다.

따라서 에셋번들을 언로드하는 시점을 잘 설정해야 합니다.

에셋번들을 언로드 하기위해서는 AssetBundle.Unload(bool)을 호출합니다.

 

  • AssetBundle.Unload(true) : 로드된 모든 에셋 및 해당 종속성을 언로드.
  • AssetBundle.Unload(false) : 로드된 모든 에셋을 에셋번들과의 연결을 끊고 에셋번들만 언로드.

설명으로만은 이해가 잘 되지 않기 때문에 이해를 돕기 위해 Unload(true), Unload(false)일 경우의 예를 들어 보겠습니다.

 

AssetBundle.Unload(true)를 호출할 경우

※ 스크립트에 Unload(bool) 하기 전 yield return new WaitForSeconds(0.01f)을 추가하였습니다. 딜레이 시간을 주지 않으면 다음과 같은 에러가 발생합니다. yield return new WaitForSeconds(0.01f)을 추가해도 에러가 발생한다면 시간을 조금 더 여유있게 조절하시면 됩니다.

 

 UnloadTrue 스크립트를 빈 게임오브젝트에 추가 후 게임을 플레이합니다.

Unload(true)를 호출하게 되면 에셋번들도 언로드가 될뿐만 아니라 생성된 모든 인스턴스도 언로드되고 제거됩니다.

생성된 게임오브젝트의 머티리얼도 언로드 되어서 보라색으로 표시됩니다.

 

AssetBundle.Unload(false)를 호출할 경우

 

 UnloadFalse 스크립트를 빈 게임오브젝트에 추가 후 게임을 플레이합니다.

LoadAssetBundleUnloadFalse() 한번 로드시 드로우 콜
LoadAssetBundleUnloadFalse() 두번 로드시 드로우 콜

AssetBundle.Unload(false)의 경우에는 AssetBundle.Unload(true)와는 다르게 함수를 두번 호출하게 했습니다.

그 이유는 AssetBundle.Unload(false)는 한번 에셋번들이 로드되고 난 후 다시 로드될 때 기존에 로드된 에셋은 새로 로드된 에셋과 연결하지 않기 때문입니다. 즉 에셋번들이 다시 로드될 때 기존에 로드된 에셋과 똑같은 복사본을 생성합니다. 같은 에셋번들을 여러번 로드하고 AssetBundle.Unload(false)를 할 경우에는 메모리 중복 문제가 발생하게 됩니다.

 

AssetBundle.Unload(false)를 사용한 경우에는 Resources.UnloadUnusedAssets()를 호출해서 사용하지 않는 에셋은 언로드 하게 해야합니다.

 

참고
 

Unity - Manual: Using AssetBundles Natively

Using AssetBundles Natively There are four different APIs that you can use to load AssetBundles. Their behavior varies based on the platform the bundle is being loaded and the compression method used when the AssetBundles were built (uncompressed, LZMA, LZ

docs.unity3d.com

 

반응형
블로그 이미지
Frontend Engineer

댓글