유니티 어셋번들 (AssetBundle)
Unity3D 2013. 2. 14. 14:17http://unitykorea.wisaweb.co.kr/board/index.php?db=knowhow&no=2196&mari_mode=view@view
애셋번들(AssetBundle)은 무엇인가요?
유니티에서 애셋(Asset)들을 묶어서 하나로 관리하는 파일을 의미합니다. 다른 사용자에게 다량의 파일을 전송할 때 디렉토리 구조 및 파일들을 모아 하나의 zip파일에 압축하여 전송하듯이, 게임 제작에 사용하는 애셋에 관련된 원본 데이터 및 관련 설정을 모두 포함하여 하나의 파일로 묶어 줍니다.
그렇다면 애셋은 뭔가요?
애셋은 유니티 프로젝트에서 공용으로 사용하는 데이터를 의미합니다. 3D 모델링, 이미지, 사운드, 텍스트 및 스크립트 파일등 모든 데이터가 애셋이 될 수 있습니다. 더 쉽게 설명하면 프로젝트 뷰에 목록이 보이면 이 아이템들이 각각 애셋이라도 생각하셔도 무방합니다. 애셋은 파일 뿐만 아니라 메타 데이터라고 하는 엔진 내에서 데이터 활용을 위해 변환하는 정보도 같이 포함합니다. 그리고 에디터는 각 애셋에 고유한 GUID를 부여하고 관리합니다.
( 참고로 에디터가 자동으로 GUID를 애셋에 부여하기 때문에, 다른 프로젝트의 애셋이 같은 GUID를 생성할 가능성이 있습니다. 이의 충돌을 해결하기 위해 서버쪽에서 통합적으로 GUID를 관리하는 솔루션이 애셋 서버입니다. )
애셋번들은 왜 필요한가요?
유니티에서 게임을 만들고 빌드하면 실행파일과 함께 이를 뒷받침하는 애셋들이 제공됩니다. 이 애셋들은 유니티만의 고유한 포맷으로 압축 및 보안이 적용된 형태로 저장되어 있어서, 빌드 후에는 이를 변경하는 것이 불가능합니다. 애셋번들을 사용하게 되면, 게임에 사용되는 리소스들을 별도로 분리하여 나중에 스트리밍 방식으로 다운로드 받을 수 있도록 관리가 가능해집니다. 에셋번들을 통해 컨텐츠 패치를 수행할 수 있으며, 사이즈에 민감한 모바일의 경우, 초기 버젼은 사이즈를 작게 만들어서 배포하고 추가적으로 필요한 데이터들은 인터넷을 통해 점진적으로 받으면서 서비스할 수 있습니다.
애셋번들은 어떻게 만드나요?
애셋번들은 유니티 에디터 라이브러리의 BuildPipeline 클래스를 통해 제작할 수 있습니다. 유니티 에디터에서 에셋번들을 만드는 메뉴는 없으며,에디터를 확장해서 직접 제작해야 합니다. 일반적으로 아래 샘플 코드와 같이 에디터의 프로젝트 뷰에서 현재 선택된 파일 정보를 나타내는Selection 클래스와 조합해서 사용합니다.
애셋 번들은 만드는 타입에 따라 크게 아래의 3가지로 구분할 수 있습니다.
일반 애셋 번들 : 모든 타입의 애셋을 묶어서 제작할 수 있습니다. BuildPipeline.BuildAssetBundle 함수를 사용합니다. 주 애셋을 지정하는 첫 번째 인자에 특정 애셋을 지정하면, AssetBundle.mainAsset 프로퍼티를 사용하여 바로 가져올 수 있습니다.
스트리밍 씬 애셋 번들 : 씬에 관련된 애셋을 묶어서 저장하며, 이를 사용하면 새로운 씬을 스트리밍으로 로딩할 수 있습니다. BuildPipeline.BuildStreamedSceneAssetBundle 함수를 사용합니다.
이름이 지정된 애셋 번들 : 일반 애셋번들과 동일하지만 각각 애셋에 사용자가 지정한 이름을 지정할 수 있습니다. BuildPipeline.BuildAssetBundleExplicitAssetNames 함수를 사용하며 BuildAssetBundle 함수와의 차이는 주 애셋(Main Asset)을 지정하는 기능이 없으며, 대신 사용자가 지정한 이름의 배열을 지정할 수 있습니다.
애셋 번들은 제작 옵션을 여러가지로 설정할 수 있는데, 설정할 수 있는 옵션들은 다음과 같습니다.
CollectDependencies : 특정 애셋에 연관된 다른 애셋을 모두 포함시킵니다.
CompleteAssets : 애셋이 속하는 게임 오브젝트와 관련된 모든 애셋을 포함시킵니다.
DisableWriteTypeTree : 유니티 버젼 정보이 달라도 애셋의 정보를 올바르게 인식할 수 있는 타입트리(TypeTree) 정보를 제거하여 애셋번들을 제작합니다.
DeterministicAssetBundle : 애셋번들을 다시 빌드하더라도 처음 애셋번들이 가지고 있던 GUID의 해시 값을 그대로 유지합니다.
UncompressedAssetBundle : 애셋번들을 제작할 때 압축하지 않습니다.
해당 옵션들은 모두 OR 연산에 의해서 복수개 지정이 가능합니다.
마지막으로 플랫폼에 따라 애셋번들간의 호환성이 다르기 때문에 반드시 빌드타겟을 명시해 주어야 합니다.
제작한 애셋번들은 서로 호환되나요?
플랫폼 및 유니티 버젼에 따라 호환성 문제가 일어날 수 있습니다.
스탠드얼론 플랫폼 및 웹 플랫폼으로 제작된 애셋번들들은 서로 호환되지만, 아이폰 및 안드로이드 플랫폼 애셋번들은 다른 플랫폼의 애셋번들과 서로 호환되지 않습니다.
아래는 플랫폼에 따른 호환성을 정리한 표입니다. 예를 들어 웹플레이어, 아이폰, 안드로이드에 모두 호환되는 서비스를 제작할 계획을 가지고 있다면, 총 3가지 종류의 애셋번들을 제작해야 합니다.
그리고 유니티의 버젼에 따라 애셋번들의 호환성도 고려하여야 합니다.
유니티에는 타입트리(Type Tree)라는 데이터가 있는데, 이 데이터가 애셋 번들에 포함되어 있으면 다른 버젼에서 만든 애셋번들을 파악할 수가 있어서 애셋번들을 재활용할 수 있게 됩니다. 하지만 모든 플랫폼 애셋번들에 타입트리 정보가 포함되는 것은 아닙니다. 모바일용 애셋 번들은 처리속도를 위해 타입 트리 정보가 포함되지 않게 설계되어 있어 유니티 버젼이 변경되는 경우 애셋 번들을 다시 빌드해야 합니다. 스탠드얼론 플랫폼은 빌드시 사용자 설정에 따라 타입 트리 정보의 포함 유무를 지정할 수 있으며, 웹 플랫폼은 언제나 타입 트리 정보를 포함합니다.
애셋 번들 이외에 패치를 받을 수 있는 방법은 없을까요?
애셋을 만들어 압축하고 암호화 거는 로직은 유니티만 알고 있기 때문에 공식적으로 애셋 번들이외에 실시간으로 데이터를 패치할 수 있는 방법은 없습니다. 웹의 경우 사용자 스크립트에서 파일을 생성하는 것을 제한하기 때문에, 캐싱 기능을 사용하려면 유니티 웹플레이어가 제공하는 애셋 번들 사용이 필수입니다.
캐싱 기능은 무엇인가요?
이미 만들어진 게임에 인터넷을 통해 신규 컨텐츠를 제공하는 DLC(Downloadable Contents)기능을 구현하거나, MMORPG와 같이 너무 서비스 규모가 크고, 컨텐츠의 업데이트가 자주 발생하는 경우, 기본 실행 파일과 애셋 번들을 조합해서 사용하는데, 이 때 실행할 때 마다 매번 네트웍으로 새로운 컨텐츠를 다운 받게 되면 네트웍의 부하 및 속도의 저하가 발생하게 됩니다. 아래 그림과 같이 한번 다운로드 받은 애셋 번들을 하드디스크에 저장하고, 두 번째 불러올 때는 네트웍이 아닌 하드디스크에서 불러오는 기능이 캐싱입니다.
캐싱 기능은 어떻게 사용하나요?
WWW 클래스에서 제공하는 LoadFromCacheOrDownload 함수를 사용하여 애셋번들의 url, 버젼 정보, 체크섬 정보를 사용하면 자동으로 하드디스크에 지정한 버젼과 url의 애셋번들이 존재하는 경우 하드디스크에서 불러오고 아닌 경우에는 인터넷을 통해서 불러들이게 됩니다.
캐싱 기능과 애셋 번들을 같이 활용하고 싶습니다.
WWW.LoadFromCacheOrDownload 함수는 단순하게 제공받은 버젼정보와 URL만 비교해서 애셋번들이 하드디스크에 있으면 로딩, 없으면 웹에서 다운로드하는 로직을 수행합니다. (내부 로직상 버젼의 숫자는 큰 의미가 없습니다. ) 아래는 애셋번들을 관리하는 간단한 관리자 클래스 예제입니다.
아래는 이를 활용하여 다운로드받는 컴포넌트의 코드입니다.
애셋 번들의 버젼을 관리하여 패치 시스템을 제작하고 싶습니다.
패치 시스템은 위의 기능을 활용하여 직접 만들어야 하는 시스템입니다. 패치 시스템을 구현하려면 클라이언트 버젼에 따라 다운로드 받아야하는 파일들의 목록과 이들이 직접 비교해서 다운을 받는 시스템을 직접 만들어야 합니다.
하나의 예로 패치 목록을 먼저 다운로드 받은 후에, Cache.IsVersionCached 함수를 사용하여 목록의 각 아이템들이 캐시에 있는지 검사한 후, 다운로드를 일괄적으로 진행하는 방법이 있습니다. 이러한 경우 애셋번들의 생성, 제작 및 관리를 위한 CMS(Contents Management System)시스템이 별도로 필요하며, 이러한 시스템은 게임을 제작하는 스튜디오 내의 업무 프로세스와 밀접하게 연관되기 때문에 유니티가 별도로 솔루션을 제공하지는 않습니다.
다운로드 받은 애셋번들은 어떻게 사용하나요?
애셋번들을 다운로드 받으면 WWW클래스의 assetbundle 프로퍼티를 통해 AssetBundle 클래스를사용하여 애셋번들에 접근하여 원하는 애셋을 런타임에서 로딩하는 것이 가능합니다. 아래는 관련 소스입니다.
애셋번들을 통해 스크립트 로직을 업데이트 하고 싶습니다.
유니티에서 스크립트 파일은 컴파일 과정을 거쳐 dll로 제작되며, 이 dll은 항상 초기 설치 파일에 포함되도록 설계되어 있습니다. 이 dll의 일부분을 애셋번들로 빼는 것은 불가능합니다.
스크립트를 사용하는 프리팹의 에셋번들을 제작하는 경우, 코드 자체가 저장되는 것이 아니고 컴포넌트의 클래스 레퍼런스 정보 및 설정 정보만 저장됩니다. 이 정보를 기반으로 프리팹의 스크립트 로직은 메인 프로그램내의 컴파일된 dll가 실행합니다.
다만 dll을 binary 형태로 저장한 후 애셋번들에 포함시키고, 아래 코드와 같이 .NET의 Reflection 기능을 사용하여 실시간으로 불러들이면 스크립트를 사용하는 것이 가능합니다.
하지만 이러한 과정은 복잡하고 불편하며, 가장 큰 문제는 AOT(Ahead of Time) 컴파일로 동작하는 아이폰의 경우 Reflection 기능에 제한이 있는 관계로 아래의 코드의 사용이 불가능합니다.
서비스 관점에서도 클라이언트는 언제나 최신 버젼 및 최신 로직을 동일하게 유지해야 하기 때문에, 초기 설치 파일을 업데이트하는 것이 올바른 방법이라는 의견도 있으니 참고하길 바랍니다.
결론
지금까지 애셋 번들에 대한 개괄적인 내용을 알아봤습니다. 애셋번들은 매우 유용한 기능입니다. 하지만 모든 것을 제공해주는 만능의 툴은 아닙니다. 애셋번들을 사용하여 대규모 혹은 실시간으로 업데이트 되는 서비스를 만들 때 애셋번들의 특성 및 라이선스 관련된 사항들을 미리 숙지하시고 시스템을 설계하여야 합니다. 기타 다양한 애셋번들에 대한 활용법 및 추가적인 설명은 아래 유니티 홈페이지 링크를 참고하세요.
http://docs.unity3d.com/Documentation/Manual/AssetBundlesIntro.html
http://docs.unity3d.com/Documentation/Manual/AssetBundlesIntro.html
AssetBundles (Pro only)
AssetBundles are files which you can export from Unity to contain assets of your choice. These files use a proprietary compressed format and can be loaded on demand by your application. This allows you to stream in content, such as models, textures, audio clips, or even entire scenes separately from the scene in which they will be used. AssetBundles have been designed to simplify downloading content to your application. AssetBundles can contain any kind of asset type recognized by Unity, as determined by the filename extension. If you want to include files with custom binary data, they should have the extension ".bytes". Unity will import these files as TextAssets.
When working with AssetBundles, here's the typical workflow:
During development, the developer prepares AssetBundles and uploads them to a server.
Building and uploading asset bundles
- Building AssetBundles. Asset bundles are created in the editor from assets in your scene. The Asset Bundle building process is described in more detail in the section for Building AssetBundles
- Uploading AssetBundles to external storage. This step does not include the Unity Editor or any other Unity channels, but we include it for completeness. You can use an FTP client to upload your Asset Bundles to the server of your choice.
At runtime, on the user's machine, the application will load AssetBundles on demand and operate individual assets within each AssetBundle as needed.
Downloading AssetBundles and loading assets from them
- Downloading AssetBundles at runtime from your application. This is done from script within a Unity scene, and Asset Bundles are loaded from the server on demand. More on that in Downloading Asset Bundles.
- Loading objects from AssetBundles. Once the AssetBundle is downloaded, you might want to access its individual Assets from the Bundle. More on that in Loading Resources from AssetBundles
See also:
- Frequently Asked Questions
- Building AssetBundles
- Downloading Asset Bundles
- Loading Asset Bundles
- Keeping track of loaded AssetBundles
- Storing and loading binary data
- Protecting content
- Managing Asset Dependencies
- Including scripts in AssetBundles
Page last updated: 2012-10-10
'Unity3D' 카테고리의 다른 글
Selection (0) | 2013.02.14 |
---|---|
어셋번들 (AssetBundle / BuildPipeline) 생성 (1) | 2013.02.14 |
EditorUtility.OpenFolderPanel (0) | 2013.02.14 |
C# 전처리기 지시문 (0) | 2013.02.12 |
유니티 안드로이드 프로젝트를 이클립스에서 실행하기. (0) | 2013.02.01 |