에셋번들(AssetBundle) 로드
에셋번들 로드는 에셋번들에 들어있는 에셋을 불러오는 것을 의미합니다.
에셋번들을 로드하는데에는 여러가지 함수가 있습니다.
[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 스크립트를 빈 게임오브젝트에 추가 후 게임을 플레이합니다.
AssetBundle.Unload(false)의 경우에는 AssetBundle.Unload(true)와는 다르게 함수를 두번 호출하게 했습니다.
그 이유는 AssetBundle.Unload(false)는 한번 에셋번들이 로드되고 난 후 다시 로드될 때 기존에 로드된 에셋은 새로 로드된 에셋과 연결하지 않기 때문입니다. 즉 에셋번들이 다시 로드될 때 기존에 로드된 에셋과 똑같은 복사본을 생성합니다. 같은 에셋번들을 여러번 로드하고 AssetBundle.Unload(false)를 할 경우에는 메모리 중복 문제가 발생하게 됩니다.
AssetBundle.Unload(false)를 사용한 경우에는 Resources.UnloadUnusedAssets()를 호출해서 사용하지 않는 에셋은 언로드 하게 해야합니다.
참고
댓글