에셋 번들 (Pro 만 지원)

에셋번들은 사용자가 원하는 에셋을 담아 모아 내보내기를 할 수 있는 파일들입니다. 이 파일들은 당사의 압축 포맷을 사용하였고 사용자 어플리케이션으로 요청에 따라 설치할 수 있습니다. 이 기능을 사용하면 사용자는 모델, 텍스처, 오디오클립 등 심지어는 장면(scene) 전체를 사용 될 해당 장면(scene)에서 분리하여 스트리밍 할 수 있습니다. 그 파일들은 사용자 어플리케이션으로 콘텐츠를 쉽게 다운로드 받을 수 있도록 설계하였습니다.

에셋 번들은 유니티가 인식할 수 있는 어떤 타입의 에셋이든 포함할 수 있으며, 타입은 파일이름 확장자에 따라 결정됩니다. 사용자가 바이너리 맞춤 정보가 있는 파일을 포함하고 싶다면, 사용자는 그 파일의 확장자를 ".bytes" 라고 하여야 합니다. 유니티는 해당 파일을 TextAssets 타입으로 들여오기를 실행 할 것입니다.

에셋 번들의 사용법을 보여주는 샘플 코드를 보려면 AssetBundles Example Project을 참조하십시오.

에셋 번들의 생성

사용자가 에셋 번들을 구성하려면 다음 3가지 클래스 매소드를 사용합니다: BuildPipeline.BuildAssetBundle, BuildPipeline.BuildStreamedSceneAssetBundle 그리고BuildPipeline.BuildAssetBundleExplicitAssetNames..

  • _BuildPipeline.BuildAssetBundle_ 는 어떠한 타입의 에셋이라도 AssetBundles 을 사용하여 만들 수 있습니다.
  • 사용자가 장면(scene)만을 포함하여 데이터가 생기는 데로 스트리밍하고 로딩 하고 싶다면, _BuildPipeline.BuildStreamedSceneAssetBundle_을 사용하면 됩니다.
  • _BuildPipeline.BuildAssetBundleExplicitAssetNames_ 은 BuildPipeline.BuildAssetBundle과 같으나 해당 프로젝트의 맞춤 문자열 ID(이름)를 명시할 수 있는 매개변수가 추가되어 있습니다.

에셋 번들 다운로드

에셋버들을 다운 받으려면 WWW.LoadFromCacheOrDownload을 사용을 권합니다. 다운로드가 완료되면 assetBundle 속성을 사용하여 에셋번들을 추출 할 수 있습니다. 예를 들면:

string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";
IEnumerator Start () {
    // Start a download of the given URL
    WWW www = WWW.LoadFromCacheOrDownload (url, 1);
 
    // Wait for download to complete
    yield return www;
 
    // Load and retrieve the AssetBundle
    AssetBundle bundle = www.assetBundle;
}

사용자가 @@.assetBundle성을 사용하면 다운로드 된 데이터가 추출되고 에셋번들이 생성됩니다. 이 시점에서 사용자는 번들에 포함된 오브젝트를 사용할 준비가 완료 됩니다. LoadFromCacheOrDownload를 사용하면 에셋번들이 캐시에 존재하지 않거나 혹은 존재하지만 요청한 버전보다 하위 버전과 연결되어 있다면, 해당 에셋번들을 다운로드 받을 것 있습니다. 그렇지 않다면 에셋 번들은 캐시에서 로딩 될 것 입니다.

번들에서 오브젝트를 로딩 혹은 언로딩

다운로드 받은 데이터에서 에셋 번들을 생성하고 나면, 사용자는 다음 세가지 매소드을 사용하여 오브젝트들을 로딩할 수 있습니다: AssetBundle.Load, AssetBundle.LoadAsync 그리고AssetBundle.LoadAll.

  • _AssetBundle.Load_은 이름 ID을 매개변수로 사용하여 로딩할 것입니다. 해당 이름은 프로젝트 뷰에서 확인할 수 있습니다. 사용자는 선택적으로 오브젝트 타입을 Load 매소드의 매개변수로 전달하여 해당 오브젝트가 특정한 타입으로 로딩되게 할 수 있습니다.
  • _AssetBundle.LoadAsync_는 위에 설명한 Load 매소드와 같이 동작하나 에셋이 로딩 되는 동안 주 스레드를 막지 않을 것 입니다. 이 매소드를 사용하면 대량의 에셋을 한꺼번에 받는 동안 사용자 어플리케이션이 일시 중지 되는 것을 방지할 수 있습니다
  • _AssetBundle.LoadAll_는 사용자의 에셋번들에 담긴 모든 오브젝트를 로딩할 것 입니다. AssetBundle.Load와 함께, 사용하자는 타입에 따자 특정 타입의 오브젝트를 걸러낼 수 있습니다.

에셋을 언로드 하려면 사용자는 AssetBundle.Unload을 사용하면 됩니다. 이 매소드는 Boolean 매개 변수를 받아 유니티에게 다운 받은 번들에서 모든 데이터(로딩된 에셋 오브젝트 포함)를 언로드 할지 아니면 압축된 데이터 만을 언로드 할지를 말해 줍니다. 사용자 어플리케이션이 에셋 번들에서 오브젝트 일부만을 사용하고 일부 메모리를 비워두고 싶다면, false 값을 전달하여 메모리로부터 압축데이터를 언로드 할 수 있습니다. 해당 에셋 번들에서 모든 것을 완전히 언로드하고 싶다면, true을 전달하여 에셋 번들에서 받은 에셋은 지워버릴 수 있습니다.

에셋 번들 내 오브젝트 리스트

사용자는 AssetBundle.LoadAll을 사용하여 해당 에셋번들에 포함된 모든 오브젝트 리스트를 추출할 수 있습니다. ID 리스트를 바로 가져오는 것은 가능하지 않지만, 통상 사용하는 우회적인 방법은, TextAsset 알려진 이름을 부여하여 에셋번들 내에 있는 에셋의 이름들을 담도록 하는 것 입니다.

에셋번들에서 오브젝트의 인스턴스화

에셋번들에서 오브젝트를 다운받고 나면, 사용자는 Instantiate을 사용하여 오브젝트를 사용자 장면(scene)로 인스턴스화 할 수 있습니다.

string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";
IEnumerator Start () {
    // Start a download of the given URL
    WWW www = WWW.LoadFromCacheOrDownload (url, 1);
 
    // Wait for download to complete
    yield return www;
 
    // Load and retrieve the AssetBundle
    AssetBundle bundle = www.assetBundle;
 
    // Load the GameObject
    GameObject go = bundle.Load("myGameObject", typeof(GameObject)) as GameObject;
 
    // Instantiate the GameObject
    Instantiate(go);
}

다운 받은 에셋번들 관리

사용자가 다운받은 에셋번들 리스트를 자동으로 받을 수 있는 방법은 제공되지 않습니다. 사용자는 스크립트로 에셋번들 오브젝트와 해당 URL에 대한 조회정보를 저장하여 추적할 수 있습니다.

에셋번들에 바이너리 데이터 저장 및 로딩

첫 번째 단계는 사용자의 바이너리 파일을 ".bytes" 확장자로 저장하는 것 입니다. 유니티에서 이 파일은 TextAsset 취급됩니다. 사용자가 에셋번들을 구축할 때 해당 파일은 TextAsset 파일로 포함 됩니다. 사용자가 에셋번들을 사용자 어플리케이션에 다운로드 하고 나면 TextAsset 오브젝트를 가져오면, TextAsset의 .bytes 속성을 사용하여 바이너리 데이터를 추출 할 수 있습니다.

string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";
IEnumerator Start () {
    // Start a download of the given URL
    WWW www = WWW.LoadFromCacheOrDownload (url, 1);
 
    // Wait for download to complete
    yield return www;
 
    // Load and retrieve the AssetBundle
    AssetBundle bundle = www.assetBundle;
 
    // Load the TextAsset object
    TextAsset txt = bundle.Load("myBinaryAsText", typeof(TextAsset)) as TextAsset;
 
    // Retrieve the binary data as an array of bytes
    byte[] bytes = txt.bytes;
}

에셋번들에 스크립트 포함하기

에셋 번들은 TextAssets 타입으로 스크립트를 포함 할 수는 있으나 실제로 실행 가능한 코드가 되는 것은 아닙니다. 사용자가 에셋번들에 사용자 어플리케이션에서 실행 가능한 코드를 포함하고 싶다면, 어셈블리 코드로 미리 컴파일 하여 Mono Reflection 클래스 (주: Reflection은 iOS에는 없음)를 사용하여 로딩하여야 합니다. 어셈블리 코드는 보통 타입이 C# IDE (예를 들면 Monodevelop, Visual Studio) 혹은 해당 mono/.net 컴파일러를 사용하는 아무 텍스트 편집기로 만들 수 있습니다.

string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";
IEnumerator Start () {
    // Start a download of the given URL
    WWW www = WWW.LoadFromCacheOrDownload (url, 1);
 
    // Wait for download to complete
    yield return www;
 
    // Load and retrieve the AssetBundle
    AssetBundle bundle = www.assetBundle;
 
    // Load the TextAsset object
    TextAsset txt = bundle.Load("myBinaryAsText", typeof(TextAsset)) as TextAsset;
 
    // Load the assembly and get a type (class) from it
    var assembly = System.Reflection.Assembly.Load(txt.bytes);
    var type = assembly.GetType("MyClassDerivedFromMonoBehaviour");
 
    // Instantiate a GameObject and add a component with the loaded class
    GameObject go = new GameObject();
    go.AddComponent(type);
}

에셋의 의존관계 관리

번들 내의 에셋은 다른 에셋과 의존관계에 있을 수 있습니다. 예를 들어, 모델은 물질(material)을 포함하고 그것은 다시 텍스처와 그림자를 활용할 수 있습니다. 번들에는 이러한 에셋의 의존성을 에셋과 함께 포함할 수 있습니다. 하지만, 각자 다른 번들의 여러 에셋이 다른 에셋의 공통 세트에 의존할 수 도 있습니다.(예를 들면, 다른 번들에 있는 빌딩들의 여러 다른 모델들이 같은 텍스처를 가질 경우) 만일 오브젝트가 공유 의존하는 것을 각 번들마다 복사본을 만들어 보관한다면, 해당 번들이 로딩 될 때마다 불필요한 에셋이 생성되고, 그것은 메모리의 낭비를 초래할 것 입니다.

이러한 낭비를 피하고자, 공유 의존사항을 분리하여 독립된 하나의 번들에 넣고, 그것이 필요한 번들의 에셋에서 필요할 때 단순히 조회할 수도 있습니다. 첫째, 조회 속성은 BuildPipeline.PushAssetDependencies을 실행하여 사용가능 하도록 설정해 두어야 합니다. 그 후에 해당 조회 의존사항을 포함하는 번들을 구축하여야 합니다. 다음은, 첫째 번들의 에셋을 조회하는 번들을 구축하기 전에 PushAssetDependencies 을 다시 실행하여야 합니다. PushAssetDependencies 을 추가로 실행하면 추가적인 단계의 의존사항을 도입할 수 있습니다. 해당 조회 레벨은 스택에 저장되어 그에 상응하는 BuildPipeline.PopAssetDependencies을 사용하여 해당 레벨로 돌아갈 수 있습니다. 구축 전에 사용하는 초기 push를 포함하여 push 와 pop 실행을 통해 균형을 맞추어야 합니다.

시 시에는 사용자는 해당 의존사항을 조회하는 다른 번들보다 먼저 의존사항을 포함하는 번들을 로딩해야 합니다. 예를 들면, 공유하는 텍스처를 포함하는 번들을 먼저 로딩하고 그 다음 해당 텍스처를 조회하는 물질(material) 번들을 로딩하여야 합니다.

다른 게임에 사용자 에셋번들 재 사용이 가능한가요?

에셋번들을 사용하면 다른 게임간에 콘텐츠를 공유할 수 있습니다. 다만 사용자 에셋번들 안에 GameObject가 조회하는 에셋은 모두 에셋번들에 포함하거나 사용자 어플리케이션에 존재하여야 합니다 (현재 장면(scene)에 이미 로딩되어야 함). 조회한 에셋이 사용자가 구축하는 에셋번들에 반드시 포함되게 하려면 BuildAssetBundleOptions.CollectDependencies옵션을 전달하면 됩니다.

에셋번들의 에셋을 어떻게 확인하나요?

사용자가 에셋번들을 구축할 때, 해당 에셋은 내부적으로는 확장자 없이 이름으로 식별됩니다. 예를 들어 사용자 프로젝트 폴더에 있는 "Assets/Textures/myTexture.jpg"는 디폴트 매소드를 사용하면 "myTexture" 확장자로 식별하고 로딩합니다. 사용자는 에셋번들을 구축할 때 BuildPipeline.BuildAssetBundleExplicitAssetNames을 사용하여 사용자의 ID (문자열) 리스트를 제공함으로써 더 많은 권한을 가지고 원하는 대로 구축할 수 있습니다.

에셋으로부터 오브젝트 비동기 로딩하기

사용자는 AssetBundle.LoadAsync을 사용하여 오브젝트를 비동기적으로 로딩하여 사용자 어플리케이션에 고장 상황을 줄일 수 있습니다.

using UnityEngine;
 
IEnumerator Start () {
	// Start a download of the given URL
	WWW www = WWW.LoadFromCacheOrDownload (url, 1);
 
	// Wait for download to complete
	yield return www;
 
	// Load and retrieve the AssetBundle
	AssetBundle bundle = www.assetBundle;
 
	// Load the object asynchronously
	AssetBundleRequest request = bundle.LoadAsync ("myObject", typeof(GameObject));
 
	// Wait for completion
	yield return request;
 
	// Get the reference to the loaded object
	GameObject obj = request.asset as GameObject;
}

에셋 번들은 다른 플랫폼에 호환 가능합니까?

에셋번들은 일부 플랫폼 간에 호환이 가능합니다. 다음 테이블을 가이드라인으로 사용하세요.

_에셋번들의 플랫폼 간 호환성_
독립형 웹재생기 iOS Android
편집기 Y Y Y Y
독립형 Y Y
웹 재생기 Y Y
iOS Y
Android Y

에셋번들을 어떻게 캐시에 저장합니까?

사용자는 WWW.LoadFromCacheOrDownload을 사용하여 사용자 에셋 번들을 디스크에 자동저장 할 수 있습니다. 하지만 웹재생기는 총 50MB(모든 웹 재생기간에 공유)으로 제한 되어 있다는 것을 명심하십시오. 만일 사용자가 추가 저장 공간이 필요하다면, 사용자 게임을 위한 별도 캐싱 라이선스를 구매할 수 있습니다.

콘텐츠 보호

유니티에서 AssetBundle.CreateFromMemory을 사용하면 byte[] 열에서 에셋번들 오브젝트를 생성할 수 있습니다. 사용자는 이것을 이용하면 전송 전에 해당 에셋번들을 암호화하고 실행 시에 복호하여 보안을 증가할 수 있습니다.

string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";
IEnumerator Start () {
    // Start a download of the encrypted assetbundle
    WWW www = new WWW (url);
 
    // Wait for download to complete
    yield return www;
 
    // Get the byte data
    byte[] encryptedData = www.bytes;
 
    // Decrypt the AssetBundle data
    byte[] decryptedData = YourDecryptionMethod(encryptedData);
 
    // Create an AssetBundle from the bytes array
    AssetBundle bundle = AssetBundle.CreateFromMemory(decryptedData);
 
    // You can now use your AssetBundle
}