섹션 9 : 일반적인 함정

이번 섹션에서는 프로젝트에서 에셋 번들을 사용할 때 일반적으로 발생하는 몇 가지 문제에 대해서 설명할 것이다.

 

에셋 복제(Asset Duplication) - 유니티 5의 에셋 번들 시스템은 오브젝트가 에셋 번들에 내장 되었을 때 객체의 모든 종속성을 발견하게 된다. 이것은 에셋 데이터베이스를 통해서 수행된다. 이 종속성 정보는 에셋 번들에 포함된 오브젝트 집합을 결정하는데 사용된다.

 

에셋 번들에 명시적으로 등록된 객체는 해당 에셋 번들에만 등록된다. 오브젝트의 에셋 임포터의 assetBundleName 속성이 비어있지 않은 문자열로 설정된 경우에만 객체가 "명시적으로 등록"되는 것이다.

 

에셋 번들에 명시적으로 등록되지 않은 오브젝트는 이 것을 참조하는 오브젝트가 포함된 모든 에셋 번들에 등록된다.

 

두 개의 서로 다른 오브젝트가 서로 다른 에셋 번들에 등록되어 있는데, 둘 다 하나의 객체를 참조하고 있다면 그 객체는 두 에셋 번들에 모두 복사된다. 이렇게 중복된 종속성 역시 인스턴스화 되는데, 이러한 인스턴스는 하나의 객체가 아니라 달라진 식별자로 인해 서로 다른 객체로 간주된다. 이로 인해서 응용 프로그램의 에셋 번들의 전체 크기가 증가하게 된다. 또한 응용 프로그램에서 부모를 모두 불러오는 경우 두 개의 오브젝트 사본이 메모리에 불러와진다.

 

이 문제를 해결할 수 있는 몇 가지 방법이 있는데 그것은 다음과 같다 :

1. 서로 다른 에셋 번들에 등록된 오브젝트들이 종속성을 공유하지 않도록해야 한다. 종속성을 공유하는 모든 오브젝트는 동일한 에셋 번들에 배치함으로써 종속성의 복제를 배제할 수 있다.

- 이 방법은 일반적으로 공유 종속성이 많은 프로젝트에서는 사용하기 부적절하다. 편리하고 효율적으로 만들기 위해서 과도하게 자주 다시 빌드하고 다시 다운로드해야 하는 한덩어리의 에셋 번들이 생성될 것이다.

2. 종속성을 공유하는 2개의 에셋 번들이 동시에 불러와지지 않도록 에셋 번들을 세그먼트화해야 한다.

- 이 방법은 레벨 기반 게임과 같은 특정 유형의 프로젝트에 적용할 수 있다. 하지만 여전히 프로젝트의 에셋 번들의 크기가 불필요하게 증가하고 빌드 시간과 로딩 시간이 증가하는 문제가 있다.

3. 모든 종속성 에셋이 자체 에셋 번들에 빌드되었는지 확인해야 한다. 이 방식은 에셋의 복제 위험을 완전히 제거하지만 복잡성 문제를 발생시킨다. 이것을 위해서 응용 프로그램은 에셋 번들 간의 종속성을 추적하고 AssetBundle.LoadAsset API를 호출하기 전에 올바른 에셋 번들이 불러와졌는지 확인해야 한다.

 

유니티 5에서, 오브젝트 의존성은 UnityEditor 네임 스페이스의 AssetDatabase API를 통해서 추적된다. 네임 스페이스의 이름이 의미하듯이 이 API는 유니티 에디터 상에서만 사용할 수 있으며 런타임 시에는 사용할 수 없다. AssetDatabase.GetDependencies는 특정 오브젝트나 에셋의 모든 즉각적인 종속성을 찾는데 사용할 수 있다. 참고로 이러한 종속성에는 자체 종속성이 있을 수 있다. 추가적으로 AssetImporter API를 사용하여 특정 오브젝트가 등록되어 있는 에셋 번들을 쿼리할 수 있다.

 

AssetDatabase와 AssetImporter API를 결합하여 모든 에셋 번들의 직접 또는 간접 종속성이 에셋 번들에 등록되도록 하거나, 두 개의 에셋 번들이 에셋 번들에 등록되지 않은 종속성을 공유하지 않도록하는 에디터 스크립트를 작성할 수 있다. 에셋을 복제하는데 소모되는 메모리 비용을 생각하면 모든 프로젝트에 이러한 스크립트가 있는 것이 좋다.

 

스프라이트 아틀라스 복제(Sprite Atlas Duplication) - 이 섹션에서는 자동으로 생성된 스프라이트 아틀라스와 함께 사용될 때 발생하는 유니티 5의 에셋 종속성 계산 코드의 단점에 대해서 설명한다.

 

자동으로 생성된 스프라이트 아틀라스느느 스프라이트 아틀라스가 생성된 스프라이트 오브젝트를 포함하는 에셋 번들에 등록된다. 만약 스프라이트 오브젝트가 여러 에셋 번들에 등록되어 있다면 스프라이트 아틀라스는 하나의 에셋 번들에 등록되지 않고 복제된다. 스프라이트 오브젝트가 에셋 번들에 등록되지 않은 경우라면 스프라이트 아틀라스는 에셋 번들에도 등록되지 않는다.

 

스프라이트 아틀라스가 중복되지 않도록 하려면 동일한 스프라이트 아틀라스에 태그가 지정된 모든 스프라이트가 하나의 에셋 번들에 등록되어 있는지 확인해야 한다.

 

유니티 5.2.2p3 이전 버전

자동으로 생성된 스프라이트 아틀라스는 에셋 번들에 등록되지 않는다. 그렇기 때문에 구성 스프라이트를 포함하는 모든 에셋 번들 및 해당 구성 스프라이트를 참조하는 모든 에셋 번들에 포함된다. 이 문제 때문에 유니티 스프라이트 패커를 사용하는 모든 유니티 5 프로젝트에 대해서 5.2.2p4, 5.3 또는 최신 버전의 유니티로 업드레이드하는 것을 강력히 권장한다.

 

만약 업그레이드를 할 수 없는 상황에 놓인 프로젝트의 경우에 이 문제에 대한 두 가지 해결 방법이 있다.

1. 쉬운 방법 : 유니티의 내장 스프라이트 패커의 사용을 피할 것. 외부 도구에 의해 생성된 스프라이트 아틀라스는 정상적인 에셋이 될 것이고, 에셋 번들에 적절하게 등록될 수 있다.

2. 어려운 방법 : 자동으로 아틀라스화된 스프라이트를 사용하는 모든 오브젝트를 스프라이트와 동일한 에셋 번들에 등록하라.

- 이렇게 하면 생성도니 스프라이트 아틀라스가 다른 에셋 번들의 간접적인 종속성으로 보이지 않으며 복제되지 않게 된다.

- 이 해결책은 유니티의 스프라이트 패커를 사용하는 워크 플로우를 보존하지만 에셋을 다른 에셋 번들로 분리하는 개발자의 능력을 저하시키며, 아틀라스를 참조하는 컴포넌트에서 데이터가 변경될 때마다 전체 스프라이트 어트리뷰트의 재 다운로드를 강제한다. 아틀라스 자체는 변경되지 않는다.

 

안드로이드 텍스처(Android Texture) - 안드로이드 환경은 기기 별로 매우 세분화되어 있기 때문에, 텍스처를 여러 가지 형식으로 압축해야하는 경우가 있다. 모든 안드로이드 기기가 ETC1을 지원하지만 ETC1은 알파 채널이 있는 텍스처를 지원하지 않는다. 만약 응용 프로그램이 OpenGL ES2 지원이 필요하지 않다면, 이 문제를 해결하는 가장 깔끔한 방법은 모든 안드로이드 OpenGL ES3 장치에서 지원되는 ETC2를 사용하는 것이다.

 

대부분의 응용 프로그램은 ETC2 지원을 사용할 수 없는 구형 기기에서 제공되어야 한다. 이 문제를 해결하는 한 가지 방법은 유니티 5의 에셋 번들 Variants를 사용하는 것이다(다른 옵션에 대한 자세한 내용은 유니티 안드로이드 최적화 가이드를 참조).

 

에셋 번들 Variants를 사용하려면 ETC1을 사용하여 깨끗하게 압축할 수 없는 모든 텍스처를 텍스처 전용 에셋 번들로 분리해야 한다. 그 다음 DXT5, PVRTC, ATITC와 같은 공급 업체별 텍스처 압축 형식을 사용하여 안드로이드 환경 별 비-ETC-가능 슬라이스를 지원하기 위해 이러한 에셋 번들의 충분한 variants를 만들어야 한다. 각 에셋 번들 Variants에 대해 포함된 텍스처의 텍스처 임포터 설정을 Variants에 적합한 압축 포맷으로 변경한다.

 

런타임 시에, SystemInfo.SupportsTextureFormat API를 사용하여 다양한 텍스처 압축 형식에 대한 지원을 감지할 수 있다. 이 정보는 지우너되는 형식으로 압축된 텍스처가 포함된 에셋 번들 Variants를 선택하고 불러오는데 사용해야 한다.

 

안드로이드 텍스처 압축 형식에 대한 자세한 내용은 이곳(here)을 참조하라.

 

iOS 파일 처리 과용(iOS File Handle Overuse) - 이 섹션에서 설명하는 문제는 유니티 5.3.2p2에서 수정되었다. 현재 버전의 유니티는 이 문제의 영향을 받지 않는다.

 

유니티 5.3.2p2 이전 버전에서는 유니티가 에셋 번들이 불러와지는 전체 시간동안 에셋 번들에 대한 열린 파일 핸들을 보유한다. 이것은 사실 대부분의 플랫폼에서는 문제가 되지 않지만, iOS는 프로세스가 동시에 열 수 있는 파일의 핸들 수를 255개까지만 제한하기 때문에 이 한도를 초과하여 에셋 번들을 불러오면 로딩 호출이 "Too Many Open File Handles" 오류와 함께 실패한다.

 

이것은 수백 또는 수천개의 에셋 번들에서 콘텐츠를 나누려는 프로젝트에서 발생하는 일반적인 문제였다.

 

새로운 버전의 유니티로 업그레이드할 수 없는 프로젝트에 대한 임시 해결책은 다음과 같다.

1. 관련된 에셋 번들을 합쳐서 사용중인 에셋 번들의 수를 줄인다.

2. AssetBundle.Unload(false)를 사용하여 에셋 번들의 파일 핸들을 닫고 로드된 오브젝트의 라이프 사이클을 수동으로 관리한다.

 

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

섹션 8 : 에셋 번들을 활용한 패치 시스템

에셋 번들 패치는 새로운 에셋 번들을 다운로드하고 기존 에셋 번들을 교체하는 것처럼 간단하다. WWW.LoadFromCasheOrDownload나 UnityWebRequest를 사용하여 응용 프로그램의 캐시된 에셋 번들을 관리하는 경우 선택한 API의 매개변수에 다른 버전을 전달하면 새 에셋번들이 다운로드 된다.

 

패치 시스템에서 해결해야할 더 큰 문제는 대체할 에셋 번들을 찾아내는 것이다. 패치 시스템에는 2가지의 정보 목록이 필요하다 :

- 현재 다운로드 되어 있는 에셋 번들의 목록과 그 버전의 정보

- 서버에 올라가 있는 에셋 번들의 목록과 그 버전의 정보

 

패치 시스템은 서버 측 에셋 번들의 목록을 다운로드하고 현재 다운로드되어 있는 에셋 번들의 목록과 비교해야 한다. 누락된 에셋 번들이나 버전 정보가 변경된 에셋 번들은 다시 다운로드해야 한다.

 

에셋 번들의 변경 사항을 찾아내는 사용자 정의 시스템을 제작할 수도 있다. 자체적인 시스템을 제작하는 대부분의 개발자는 에셋 번들 파일 정보 목록에 JSON과 같은 업계 표준 데이터 형식을 사용하고 MD5와 같은 체크섬 계산을 하는 표준 C# 클래스를 사용하는 것을 선택한다.

 

유니티는 데이터를 결정적 방식(deterministic manner)으로 정렬하여 에셋 번들을 빌드한다. 그렇기 때문에 커스텀 다운로더가 있는 응용 프로그램에서 차등 패치 시스템을 구현할 수 있다.

 

유니티는 차등 패치를 위한 기본 메커니즘을 제공하지 않으며 WWW.LoadFromCacheOrDownload나 UnityWebRequest도 기본 제공 캐싱 시스템을 사용할 때 차등 패치를 수행하지 않는다. 차등 패치가 필요한 경우에는 커스텀 다운로더를 직접 제작해야 한다.

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

섹션 7 : 에셋 번들 매니저(Asset Bundle Manager)

이곳(here)에서 다운로드 받을 수 있는 에셋 번들 매니저는, 유니티에서 에셋 번들을 효율적으로 사용할 수 있도록 만들기 위해 제작한 도구이다.

 

에셋 번들 매니저 패키지를 다운로드하고 임포트하면 새로운 API 호출이 추가될 뿐만 아니라 일부 에디터 기능이 추가되어 작업과정을 간소화시켜 준다. 이기능은 Assets 메뉴 옵션에서 찾을 수 있다.

새로운 섹션에는 다음과 같은 옵션들이 포함되어 있다.

 

시뮬레이션 모드(Simulation Mode)

시뮬레이션 모드를 활성화 하면 실제로 에셋 번들을 빌드하지 않은 상태에서도 에셋 번들 관리자가 에셋 번들과 함께 작동할 수 있게 된다. 에디터는 에셋 번들에서 등록된 에셋을 확인하고 실제 에셋 번들에서 에셋을 가져오는 대신 에셋을 직접 사용한다.\

 

시뮬레이션 모드를 사용함으로서 얻을 수 있는 가장 중요한 이점은 매번 에셋 번들을 다시 빌드하고 배포할 필요없이 에셋을 수정, 업데이트, 추가 및 삭제를 할 수 있다는 점이다.

 

에셋 번들 배리언트(Variants, 변형)는 시뮬레이션 모드에서 작동하지 않는다. 배리언트(Variants, 변형)를 사용해야 하는 경우에는 로컬 에셋 번들 서버가 필요하다.

 

 

로컬 에셋 번들 서버(Local AssetBundle Server)

에셋 번들 매니저는 에디터나 로컬 빌드(모바일 포함)에서 에셋 번들을 테스트하는데 사용할 수 있는 로컬 에셋 번들 서버를 시작할 수도 있다.

 

로컬 에셋 번들 서버를 작동시키기 위해서 지켜야할 점은 다음과 같이 Assets 폴더와 같은 위치의 프로젝트 루트 디렉토리에 AssetBundles라는 폴더를 만들어야 한다는 것이다 :

폴더를 생성한 이 후에 새로 만들어진 메뉴 옵션에서 Build AssetBundles를 선택하면 에셋 번들이 이 디렉토리에 빌드된다.

 

이제 에셋 번들을 빌드(또는 시뮬레이션 모드를 사용하기로 결정)했고 에셋 번들을 불러올 준비가 되었으니 에셋 번들 매니저를 통해 사용할 수 있는 새로운 API 호출을 살펴보자.

 

 

AssetBundleManager.Initialize()

이 함수는 AssetBundleManifest 객체를 불러온다. 에셋 번들 매니저를 사용해서 에셋에서 불러오기전에 이 함수를 호출해야 한다. 이것은 아주 간단한 예제이며 에셋 번들 매니저를 초기화하는 방법은 다음과 같다.

IEnumerator Start()

{

yield return StartCoroutine(Initialize());

}

 

IEnumerator Initialize()

{

var request = AssetBundleManager.Initialize();

 

if(request != null)

{

yield return StartCoroutine(request);

}

}

에셋 번들 매니저는 Initialize() 중에 불러오는 이 매니페스트를 사용하여 종속성 관리를 비롯한 다양한 기능을 지원한다.

 

 

에셋 불러오기(Loading Assets)

씬에 할당된 에셋 번들 이름이 있는 씬을 불러와야하는 경우 약간 다른 코드 경로를 따라야 한다. 패턴은 비슷하지만 약간의 차이가 있다. 에셋 번들에서 씬을 로드하는 방법은 다음과 같다.

IEnumerator InitializeLevelAsync(string levelName, bool isAdditive)

{

// 에셋 번들로 부터 씬을 불러오기

AssetBundleLoadOperation request = AssetBundleManager.LoadLevelAsync(sceneAssetBundle, levelName, isAdditive);

 

if(request == null)

{

yield break;

}

yield return StartCoroutine(request);

}

보다시피, 씬 불러오기는 비동기적이며 LoadLevelAsync는 씬을 불러오기 위해 StartCoroutine으로 전달되어야하는 로드 조장 요청을 반환한다.

 

 

배리언트 불러오기(Loading Variants)

에셋 번들 매니저를 사용하여 배리언트을 불러와도 씬이나 에셋에서 불러와야 하는 코드는 실제로 변경되지 않는다. 모든 작업을 수행하려면 에셋 번들 매니저의 ActiveVariants 속성을 설정해야 한다.

 

ActiveVariants 속성은 문자열의 배열이다. 에셋에 할당하는 동안 생성한 배리언트의 이름을 포함하는 문자열 배열을 작성하기만 하면 된다. 다음은 HD 배리언트으로 씬 에셋 번들을 불러오는 방법에 대한 예제이다.

IEnumerator InitializeLevelAsync(string levelName, bool isAdditive, string[] variants)

{

// activeVariants를 설정

AssetBundleManager.ActiveVariants = variants;

// 에셋 번들로부터 씬 불러오기

AssetBundleLoadOperation request = AssetBundleManager.LoadLevelAsync(variantSceneAssetBundle, levelName, isAdditive);

 

if(request == null)

{

yield break;

}

yield return StartCoroutine(request);

}

문자열 배열을 전달할 곳은 코드의 다른 부분이다(아마도 버튼 클릭이나 다른 상황). 이것으로 active variants와 일치하는 에셋 번들을 불러오게 될 것이다.

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

섹션 6 : 기본적인 에셋 번들 사용법

유니티 5에서는 에셋 번들을 불러오는데 4가지의 API를 사용할 수 있다. 이 4가지 API의 동작은 에셋 번들이 로드되는 플랫폼과 에셋 번들이 빌드될 때 사용되는 압축방법(Uncompressed, LZMA, LZ4)에 따라 다르다.

 

작업에 사용할 4가지 API는 다음과 같다 :

- AssetBundle.LoadFromMemoryAsync

- AssetBundle.LoadFromFile

- WWW.LoadfromCacheOrDownload

- UnityWebRequest’s DownloadHandlerAssetBundle (Unity 5.3 or newer)

 

AssetBundle.LoadFromMemoryAsync

이 함수는 에셋 번들 데이터가 들어있는 바이트 형식의 배열을 가져온다. (선택사항)원한다면 CRC 값을 전달할 수 있다. 에셋 번들이 LZMA 방식으로 압축되어 있다면 번들을 로딩하는 동안 에셋 번들을 압축 해체해야 한다. LZ4 방식으로 압축된 에셋 번들은 압축되어 있는 상태에서도 로드가 가능하다.

 

다음은 이 메서드를 사용하는 방법의 예시이다.

using System.IO; using UnityEngine; public class AssetBundleLoadExample : MonoBehaviour { IEnumerator LoadFromMemoryAsync(string path) { AssetBundleCreateRequest createRequest = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path)); yield return createRequest; AssetBundle bundle = createRequest.assetBundle; var prefab = bundle.LoadAsset<GameObject>("MyObject");

Instantiate(prefab); } }

하지만 이것이 LoadFromMemoryAsync를 사용하는 유일한 방법은 아니다. File.ReadAllByte(path)는 바이트 배열을 얻은 임의의 절차로 대체될 수 있다.

 

AssetBundle.LoadFromFile

이 API는 로컬 저장소에서 압축되지 않은 에셋 번들을 로드할 때 매우 효율적이다. LoadFromFile은 압축되지 않았거나 청크 기반(LZ4)으로 압축된 번들의 경우 디스크로부터 직접 에셋 번들을 로드해 온다. 이 메서드로 완적히 압축된(LZMA) 에셋 번들을 로드하면 먼저 메모리에 올리기 전에 압축을 해제한다.

 

다음은 LoadFromFile을 사용하는 예제이다 :

using System.IO;
using UnityEngine;

public class LoadFromFileExample : MonoBehaviour
{
void Start()
    {
var myLoadedAssetBundle = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "myassetBundle"));
if (myLoadedAssetBundle == null)
{
Debug.Log("Failed to load AssetBundle!");
return;
}
var prefab = myLoadedAssetBundle.LoadAsset<GameObject>("MyObject");
Instantiate(prefab);
}
}

참고 :: 유니티 5.3 이하의 안드로이드 기기에서는 스트리밍 에셋 경로에서 에셋번들을 로드하려고 할때 이 API가 실패한다. 이는 해당 경로에 압축된 .jar 파일 내에 존재하기 때문이다. 유니티 5.4 이상에서는 Streaming Assets과 함께 이 API 호출을 사용할 수 있다.

 

 

WWW.LoadFromCacheOrDownload

이 API의 사용은 권장하지 않는다.(UnityWebRequest를 사용하라) 이 API는 원격 서버에서 에셋 번들을 다운로드하거나 로컬 에셋 번들을 로드하는데 유용하다. 이것은 구 버전의 API로 UnityWebRequest API를 사용할 것을 권장한다.

 

원격 위치에서 에셋 번들을 로드하면 에셋 번들이 자동으로 캐시된다. 만약 에셋 번들이 압축된 상태라면 작업 스레드에서 에셋 번들의 압축을 해제하여 캐시에 등록한다. 압축이 해제되고 캐시된 에셋 번들은 AssetBundle.LoadFromFile과 똑같이 로드된다.

 

다음은 LoadFromCacheOrDownload를 사용하는 예제이다.

using UnityEngine;
using System.Collections;

public class LoadFromCacheOrDownloadExample : MonoBehaviour
{
IEnumerator Start()
{
while (!Caching.ready)
yield return null;

var www = WWW.LoadFromCacheOrDownload("http://myserver.com/myassetBundle.unity3d", 5);
yield return www;
if (!string.IsNullOrEmpty(www.error))
{
Debug.Log(www.error);
yield return null;
}
var myLoadedAssetBundle = www.assetBundle;

var asset = myLoadedAssetBundle.mainAsset;
}
}

AssetBundle의 바이트를 WWW 객체에 캐싱하는 메모리 오버헤드가 발생하기 때문에 WWW.LoadFromCacheOrDownload를 사용하는 모든 개발자는 AssetBundle의 크기가 몇 메가(원문에서는 a few megabytes) 수준을 넘지 않게 유지하는 것이 좋다. 또한 모바일 기기와 같이 메모리가 제한된 플랫폼에서 작업하는 개발자는 메모리 스파이크를 피하기 위해 코드가 한 번에 하나의 에셋 번들만 다운로드하도록 하는 것이 좋다.

 

만약 캐시 폴더에 추가 파일을 캐시할 여유 공간이 없다면, LoadFromCacheOrDownload는 새 에셋 번들을 저장할 충분한 공각이 확보될 때까지 캐시에서 사용된 시점이 가장 오래된 에셋 번들을 삭제할 것이다. 더 이상 공간을 만들 수 없는 경우(하드 디스크가 가득 찼거나 캐시의 모든 파일이 현재 사용 중인 경우), LoadFromCacheOrDownload는 캐싱을 하지 않고 파일을 메모리에 스트리밍할 것이다.

 

LoadFromCacheOrDownload를 강제하려면 version 매개변수(두 번째 매개변수)를 변경해야 한다. 에셋 번들은 함수로 전달된 버전이 현재 캐시된 에셋 번들의 버전과 일치하는 경우에만 캐시에서 로드된다.

 

 

UnityWebRequest

UnityWebRequest는 에셋 번들을 처리하기 위한 특정 API를 가지고 있다. 먼저 UnityWebRequest.GetAssetBundle을 사용하여 웹 요청을 생성하면, 요청을 반환한 후 요청 객체를 DownloadHandlerAssetBundle.GetContent(UnityWebRequest)로 전달한다. 이 GetContent함수를 호출하면 AssetBundle 객체를 반환한다.

 

AssetBundle.LoadFromFile와 같은 효율성으로 AssetBundle을 로드하기 위해 에셋 번들을 다운로드한 이후에 DownloadHandlerAssetBundle 클래스에서 assetBundle 속성을 사용할 수도 있다.

 

아래의 예제는 두 개의 GameObject가 포함된 에셋 번들을 로드하고 인스턴스화(instantiate)하는 방법을 보여준다.

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

public class UnityWebRequestExample : MonoBehaviour
{
    IEnumerator InstantiateObject()
    {
        string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;
        UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.GetAssetBundle(uri, 0);
        yield return request.Send();

        AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);

        GameObject cube = bundle.LoadAsset<GameObject>("Cube");
        GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");

        Instantiate(cube);
        Instantiate(sprite);
    }
}

UnityWebRequest를 사용하면 개발자가 다운로드한 데이터를 보다 유연하게 처리하고 불필요한 메모리 사용을 없앨 수 있다는 이점이 있다. 이것은 UnityEngine.WWW 클래스보다 최신의 API이다.

 

에셋 번들에서 에셋 불러오기

에셋 번들을 성공적으로 다운로드했으므로, 원하는 에셋을 불러올 차례이다.

 

제네릭 코드의 일부분 :

T objectFromBundle = bundleObject.LoadAsset<T>(assetName);

여기서 T는 불러오려는 에셋의 타입이다.

 

에셋을 불러오는 방법을 결정하는 몇 가지 옵션이 있는데 LoadAsset, LoadAllAsset과 각각에 대응되는 비동기 방식인 LoadAssetAsync, LoadAllAssetAsync가 그것이다.

 

에셋 번들에서 에셋을 동기적으로 불러오는 방법은 다음과 같다.

 

하나의 GameObject를 불러오기 :

GameObject gameObject = loadedAssetBundle.LoadAsset.<GameObject>(assetName);

모든 에셋 불러오기 :

Unity.Object[] objectArray = loadedAssetBundle.LoadAllAssets();

 

LoadAsset과 LoadAllAsset 메서드가 객체 타입이나 객체 배열을 반환한다면 비동기 메서드인 LoadAssetAsync와 LoadAllAssetAsync는 AssetBundleRequest를 반환한다. 불러온 에셋에 액세스하기 전에 비동기 작업이 완료될 때까지 기다려야 한다.

 

단일 에셋 불러오기 :

AssetBundleRequest request = loadedAssetBundleObject.LoadAssetAsync<GameObject>(assetName);

yield return request;

var loadedAsset = request.asset;

모든 에셋 불러오기 :

AssetBundleRequest request = loadedAssetBundleObject.LoadAllAssetAsync();

yield return request;

var loadedAssets = request.allAssets;

에셋이 로드된 이후에는 유니티의 오브젝트와 마찬가지로 사용할 수 있다.

 

 

에셋 번들 매니페스트 불러오기

에셋 번들 매니페스트를 불러오는 것은 애셋 번들을 종속성을 다룰 때 매우 효율적이다.

 

사용가능한 AssetBundleManifest 객체를 얻으려면 그 추가 에셋 번들(폴더에 있는 것과 동일한 이름의 폴더에 있는)을 로드하고 AssetBundleManifest 타입의 객체를 로드해야 한다.

 

매니페스트를 로드하는 작업 자체는 에셋 번들의 다른 에셋과 동일하게 수행된다 :

AssetBundle assetBundle = AssetBundle.LoadFromFile(manifestFilePath);
AssetBundleManifest manifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");

위의 예제에서 매니페스트 객체를 통해 AssetBundleManifest API 호출에 액세스할 수 있다. 여기에서 매니페스트를 사용하면 만든 에셋 번들에 대한 정보를 얻을 수 있다. 이 정보에는 종속성 데이터, 해시 데이터 및 에셋 번들의 배리언트(Variant, 변형) 데이터가 포함된다.

 

이전 섹션에서 에셋 번들의 종속성에 대해서 설명했듯이, 에셋 번들이 다른 에셋 번들에 종속성을 가지고 있다면 원래의 번들에서 에셋을 불러오기 전에 해당 번들을 불러와야 한다. 매니페스트 객체는 로딩 종속성을 동적으로 찾을 수 있도록 해준다. "assetBundle"이라는 이름의 에셋 번들에 대한 모든 종속성을 불러오려고 한다고 가정해보자.

AssetBundle assetBundle = AssetBundle.LoadFromFile(manifestFilePath);

AssetBundleManifest manifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");

string[] dependencies = manifest.GetAllDependencies();

foreach(string dependency in dependencies)

{

AssetBundle.LoadFromFile(Path.Combine(assetBundlePath, dependency);

}

이제 에셋 번들, 에셋 번들 종속성 및 에셋을 불러왔으므로 불러와진 에셋 번들 모두를 관리하는 방법에 대해 이야기해보자.

 

 

불러온 에셋 번들 관리하기 (Managing Loaded Asset Bundles)

유니티는 활성화된 씬에서 오브젝트가 제거되었을때 오브젝트를 자동으로 언로드(Unload)하지 않는다. 에셋 정리는 특정 시간에 자동적으로 이루어지며, 수동으로도 실행될 수 있다.

 

에셋 번들을 로드하고 언로드해야할 때를 아는 것이 중요하다. 에셋 번들을 잘못 언로드하면 메모리 상에서의 오브젝트와 텍스처 누락등의 바람직하지 않은 상황이 발생할 수 있다.

 

에셋 번들 관리에 있어서 이해해야할 가장 중요한 점은 AssetBundle.Unload(bool) 함수를 언제 호출해야 하는가와 함수의 매개변수에 true 혹은 false 어떤 인자를 전달해야 하는가이다. Unload는 에셋 번들을 언로드하는 비정적(non-static)함수이다. 이 API는 호출중인 에셋 번들의 헤더 정보를 언로드 한다. 이 매개변수는 이 에셋 번들로부터 인스턴스화된 모든 오브젝트를 언로드할지에 대한 여부를 나타낸다.

 

에셋 번들로부터 불러온 오브젝트에 대해 AssetBunble.Unload(true)를 사용했는데, 만약 이 오브젝트가 현재 활성화된 씬에서 사용중이라면, 이것은 앞서 이야기 한것처럼 텍스처 누락의 원인이 될 수 있다.

 

아래와 같이 머티리얼 M이 에셋 번들 AB에서 로드되었다고 가정해보자.

만약 AB.Unload(true)가 호출된다면, 활성화된 씬에서 M의 모든 인스턴스는 언로드되고 파괴된다.

 

대신에 AB.Unload(false)를 호출하면 M과 AB의 현재 인스턴스 연결이 끊어진다.

만약 AB.LoadAsset()을 호출하여 AB를 다시 로드한다고 하여도, 유니티는 새로 로드된 머티리얼에 기존에 존재하는 복사본 M을 연결시켜주지 않는다. 그 대신에 M의 2개의 복사본이 로드된다.

일반적으로 AssetBundle.Unload(false)를 사용하면 좋은 상황이 발생하지 않는다. 대부분의 프로젝트는 AssetBundle.Unload(true)를 사용하여 오브젝트를 메모리에 복제하지 않아야한다.

 

대부분의 프로젝트는 AssetBundle.Unload(true)를 사용하고 오브젝트가 중복되지 않도록 보장하는 메서드를 채택해야한다. 두 가지 일반적인 방법은 다음과 같다 :

- 응용 프로그램의 실행 시간 동안에 발생하는 레벨 사이 혹은 로딩 화면과 같이 짧은 틈 사이에 에셋 번들이 언로드되는 지점을 정의한다.

- 개별의 오브젝트에 대해 참조 카운트를 유지하고 모든 구성 오브젝트가 사용되지 않는 경우에만 에셋 번들을 언로드한다. 이 방법을 사용하면 응용 프로그램이 메모리를 복제하지 않고 개별 오브젝트를 언로드하고 다시 로드할 수 있다.

 

응용 프로그램에서 AssetBundle.Unload(false)를 반드시 사용해야만 한다면, 개별 오브젝트는 다음의 2가지 방법으로만 언로드해야 한다.

- 씬과 코드에서 원하지 않는 오브젝트에 대한 모든 참조를 제거해야 한다. 이 작업이 끝나면 Resources.UnloadUnusedAssets 함수를 호출한다.

- 씬을 additive 방식이 아닌 방법으로 로드한다. 그렇게 하면 현재 씬의 모든 오브젝트가 파괴되고 Resources.UnloadUnusedAssets가 자동으로 호출된다.

 

에셋 번들과 종속성 그리고 에셋에 대한 불러오기를 직접 관리하지 않으려고 하는 경우, 에셋 번들 관리자가 필요할 수 있다.

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

섹션 5 : 에셋 번들 종속성

하나 이상의 UnityEngine.Object에 다른 에셋 번들에 있는 UnityEngine.Object에 대한 참조가 포함되어 있으면 에셋 번들이 다른 에셋 번들에 종속될 수 있다. UnityEngine.Object에 에셋 번들에 포함되지 않은 UnityEngine.Object에 대한 참조가 포함되어 있다면 종속성이 발생하지 않는다. 이 경우에는, 에셋 번들을 빌드할 때 번들이 종속되어 있는 오브젝트의 사본이 번들에 복사된다. 여러 번들 내의 여러 오브젝트가 번들에 등록되지 않은 같은 오브젝트를 참조를 포함하면, 해당 오브젝트에 대한 종속성이 있는 모든 번들이 오브젝트의 자체적인 복사본을 만들어 내장된 에셋 번들로 패키지화 한다.

 

에셋 번들에 종속성이 포함되어 있으면 인스턴스화(instantiate)하려는 오브젝트가 로드되기전에 이러한 종속성을 포함하는 에셋 번들을 로드하는 것이 중요하다. 유니티는 종속된 것을 자동으로 로드하려고 시도하지 않는다.

 

다음 예제를 고려해 볼때, 에셋 번들 1의 머티리얼은 에셋 번들 2의 텍스처를 참조한다.

 

 

이 예제에서는, 번들 1의 머티리얼을 로딩하기 이전에 번들 2를 메모리에 로드해 두어야한다. 하지만 번들 1과 번들 2를 로드하는 순서가 중요한 것이 아니고, 번들 1의 머티리얼이 로드되기 전에 번들 2에서 필요한 자원이 로드되어 있어야한다는 점이 중요하다.

 

다음 섹션에서는 이전 섹션에서 다룬 AssetBundleManifest 객체를 사용하여 런타임에 종속성을 결정하고 로드하는 방법에 대해서 설명한다.

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

섹션 4 : 에셋 번들 빌드하기

 

이제 섹션 2에서 에셋 번들을 빌드하기 위한 코드 샘플을 살펴보자. BuildPipeline.BuildAssetBundles 함수에 세 개의 인수를 전달한다. 이 것에 대해서 좀 더 자세히 살펴보자.

 

"Assets/AssetBundles" - 빌드된 에셋 번들이 들어갈 디렉토리이다. 디렉토리의 위치를 원하는 곳으로 변경할 수 있다. 빌드를 시도하기 전에 폴더가 실제로 존재하는지 확인해야 한다.

 

BuildAssetBundleOptions

다양한 효과가 있는 여러가지 다른 에셋 번들 빌드 옵션을 지정할 수 있다. 여기서 모든 옵션에 대한 테이블을 확인할 수 있다 :

https://docs.unity3d.com/ScriptReference/BuildAssetBundleOptions.html

 

필요에 따라 BuildAssetBundleOptions을 자유롭게 조합할 수 있지만, 에셋 번들 압축을 처리하는 세 가지 BuildAssetBundleOptions가 있다.

 

- BuildAssetBundleOptions.None

- BuildAssetBundleOptions.UncompressedAssetBundle

- BuildAssetBundleOptions.ChunkBasedCompression

 

BuildAssetBundleOptions.None 이 번들 옵션은 직렬화된 데이터 파일의 단일 압축 LZMA 스트림인 LZMA 포멧 압축을 사용한다. LZMA 압축을 사용하려면 전체 번들이 사용되기 전에 압축이 풀려있어야 한다. 압축 결과 파일의 용량이 가장 작지만 압축 해제로 인한 로딩 시간이 길어진다. 이 옵션을 사용했을 때 번들의 에셋을 사용하려면 초기에 전체 번들의 압축을 풀어두어야 한다.

 

일단 한번 번들이 압축 해제되면, 번들에서 에셋을 사용하기 전에 전체 번들을 압축 헤제할 필요가 없는 LZ4 압축을 사용해서 디스크에서 재압축된다. 이 옵션은 번들이 하나의 에셋을 사용하기 위해 모든 에셋을 로딩해야하는 에셋이 포함된 경우에 사용하면 가장 적합하다. 캐릭터나 씬의 모든 에셋을 패키징하는 것이 이 옵션을 사용하는 번들의 예시이다.

 

LZMA 압축을 사용하는 것은 파일 크기가 작아서 오프 사이트 호스트에서 에셋 번들을 처음 다운로드하는 경우에만 권장한다. 파일을 다운로드하면 LZ4 압축 번들로 캐시된다.


BuildAssetBundleOptions.UncompressedAssetBundle 이 옵션은 전혀 압축되지 않은 방식으로 번들을 만든다. 그렇기 때문에 파일의 다운로드 용량이 커진다. 하지만 한번 다운로드한 이후에는 로딩 시간이 훨씬 빨라진다.


BuildAssetBundleOptions.ChunkBasedCompression 는 LZ4로 알려진 압축 방법을 사용하기 때문에 LZMA보다 압축 파일의 용량이 커지지만 LZMA와는 달리 전체 번들의 압축이 해제되지 않아도 사용할 수 있다. LZ4는 에셋 번들을 조각 또는 "청크"로 로드할 수 있는 청크 기반 알고리즘을 사용한다. 단일 청크의 압축을 풀면 에셋 번들의 다른 청크가 압축 해제 되지 않아도 포함된 에셋을 사용할 수 있다.

 

ChunkBasedCompression을 사용하면 압축되지 않은 번들에 로딩 시간을 비교할 수 있으므로 디스크 크기가 줄어든다.

 

BuildTarget

BuildTarget.Standalone - 여기서는 이 에셋 번들을 사용하는 대상 플랫폼을 빌드 파이프 라인에 알려준다. 사용가능한 빌드 대상 목록은 다음 링크에서 확인할 수 있다 :
https://docs.unity3d.com/ScriptReference/BuildTarget.html

 

그러나 빌드 타겟에 대한 하드 코딩을 하지 않으려면 "EditorUserBuildSettings.activeBuildTarget"을 자유롭게 이용하면 된다. 그렇게 하면 현재 설정중인 플랫폼을 자동으로 찾고 해당 타겟을 기반으로 에셋 번들을 빌드할 수 있다.

 

빌드 스크립트를 올바르게 설정했다면 번들을 빌드해야한다. 위의 스크립트 예제를 따라한 경우에는 Asset >> Asset Bundles Build를 클릭하여 프로세스를 시작하면 된다.

 

에셋 번들을 성공적으로 빌드했다면 AssetBundles 디렉토리에 예상보다 많은 파일이 있음을 알 수 있다. 설정한 번들의 수보다 2 * (n + 1)개 더 많은 파일이 있을 것인데, BuildPipeline.BuildAssetBundles의 결과물을 정확히 살펴보자.

 

유니티 에디터에서 지정한 모든 번들에 대해 에셋 번들 이름의 파일과 에셋 번들 이름 + ".manifest" 파일이 있을 것이다.

 

생성한 모든 에셋 번들과 이름을 공유하지 않는 추가 번들 및 매니페스트가 있다. 이것들은 (에셋 번들이 내장된 경우) 위치하고 잇는 디렉토리의 이름을 따서 이름이 지어진다. 이것이 매니페스트 번들이다. 이것들에 대해서 더 자세히 이야기할 것이다.

 

에셋 번들 파일

이 파일은 ".manifest" 확장자가 없는 파일이며 실행시에 에셋을 로드하기 위해 불러와야할 파일이다.

 

에셋 번들 파일은 내부적으로 여러 파일을 포함하는 아카이브이다. 이 아카이브의 구조는 일반 에셋 번들인지 씬 에셋 번들인지에 따라 약간 변경될 수 있다. 이것이 일반 에셋 번들의 구조이다.

 

씬 에셋 번들은 일반 에셋 번들에서 씬의 스트림 로딩과 컨텐츠에 최적화되도록 변경된 콘텐츠이다. 아래 이미지는 씬 에셋 번들의 내부 구조를 보여준다.

 

매니페스트 파일

추가 매니페스트 번들을 포함하여 생성된 모든 번들에 대해 연관된 매니페스트 파일이 생성된다. 매니페스트 파일은 텍스트 편집기로 열 수 잇으며 CRC(Cyclic Redundancy Check) 데이터 및 번들에 대한 종속성 데이터와 같은 정보를 포함한다. 일반 에셋 번들의 매니페스트 파일은 다음과 같은 내용이다 :

 

ManifestFileVersion: 0
CRC: 2422268106
Hashes:
 AssetFileHash:
   serializedVersion: 2
   Hash: 8b6db55a2344f068cf8a9be0a662ba15
 TypeTreeHash:
   serializedVersion: 2
   Hash: 37ad974993dbaa77485dd2a0c38f347a
HashAppended: 0
ClassTypes:
- Class: 91
 Script: {instanceID: 0}
Assets:
 Asset_0: Assets/Mecanim/StateMachine.controller
Dependencies: {}

 

여기에는 포함된 에셋, 종속성 및 기타 정보가 표시된다.

 

생성된 매니페스트 번들에는 메니페스트가 있지만 다음과 같이 보일 것이다.

 

ManifestFileVersion: 0
AssetBundleManifest:
 AssetBundleInfos:
   Info_0:
     Name: scene1assetbundle
     Dependencies: {}

 

여기에는 에셋 번들의 관계 및 종속성에 대한 정보가 표시된다. 지금 당장은 이 번들에 AssetBundleManifest 객체가 들어있다고만 이해하면 된다. 이 객체는 런타임에 불러올 번들의 종속성을 파악하는데 매우 유용하다. 이 번들과 매니페스트 객체를 사용하는 법은 섹션 6에서 확인할 수 있다.

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

5.6 문서 초안 : 이 초안 문서는 유니티 5.6에서 업데이트 된 기능에 대한 것이다. 따라서 이 문서의 정보는 최종 릴리즈 전에 변경될 수 있다.

 

                                                                                                                                                                                        

[5.6 초안] 에셋 번들

 

섹션 1 : 개요

 

에셋 번들은 실행 시 로드 할 수 있는 플랫폼 별 에셋(모델, 텍스쳐, 프리팹, 오디오 클립 및 전체 장면까지 포함)을 포함하는 아카이브 파일이다. 에셋 번들은 서로간의 종속성을 나타낼 수 있다. 예를 들어 에셋 번들 A의 머티리얼은 에셋 번들 B의 텍스처를 참조할 수 있다. 네트워크를 통한 효율적인 전달을 위해서, 에셋 번들을 유스 케이스 요구 사항(LZMA 및 LZ4)에 따라 내장된 알고리즘을 선택해서 압축할 수 있다.

 

에셋 번들은 다운로드 할 수 있는 콘텐츠(DLC)의 구성, 초기 설치 용량 감소, 최종 사용자의 플랫폼에 최적화된 에셋 로딩, 런타임 메모리 부족을 해소하는데 사용할 수 있다.

 

에셋 번들에는 무엇이 있는가?

좋은 질문이다. 실제로 "에셋 번들"은 다르지만 관련있는 두가지를 참조한다.

 

첫 번째는 디스크에 있는 실제 파일이다. 이것은 에셋 번들 아카이브를 호출하거나, 이 문서의 짧은 보관용으로만 사용된다. 아카이브는 폴더와 마찬가지로 컨테이너 내부에 추가 파일을 보유하는 컨테이너를 생각할 수 있다. 이러한 추가 파일은 직렬화된 파일(Serialized file)과 리소스 파일, 이 두가지 유형으로 구성된다. 직렬화된 파일에는 에셋이 각각의 객체로 분리되어 이 하나의 파일에 포함된다. 리소스 파일은 특정 에셋(텍스처 및 오디오)에 대해 별도로 저장된 이진 데이터 청크이므로 다른 스레드의 디스크에서 효율적으로 불러올 수 있다.

 

두 번째는 특정 아카이브에서 에셋을 불러오기 위해 코드를 통해 상호작용하는 실제 에셋 번들 객체이다. 이 개체에는 에셋 번들에 추가한 에셋의 모든 파일 경로에 대한 맵이 포함되어 있다. 이 파일의 경로는 파일을 요청했을 때 로드해야되는 해당 에셋에 속한 개체에 대한 것이다.

 

섹션 2 : 에셋 번들 워크플로우

 

 

에셋 번들을 사용하려면 다음의 순서를 따르라. 각 워크플로우에 대한 자세한 내용은 다음 섹션에서 확인할 수 있다.

 

에셋 번들에 에셋 등록

주어진 에셋을 등록하려면 다음 단계를 따라하면 된다.

 

1. 프로젝트 뷰에서 번들에 등록할 에셋을 선택하라.

2. 인스펙터 창에서 개체를 확인하라.

3. 인스펙터 창의 가장 아래쪽에 에셋 번들 및 배리언트을 등록하는 섹션을 볼 수 있다.

 

4. 왼쪽 드롭 다운은 에셋 번들을 등록하고, 오른쪽 드롭 다운은 배리언트(Variants, 변형)을 지정한다.

ex) 하나의 오브젝트가 있는데 이것이 작동하는 방식이 iOS와 안드로이드가 달라서 에셋 번들을 다르게 빌드해야한다던지, 두 장의 텍스쳐를 하나는 고해상도 배리언트로 묶고 하나는 저해상도 배리언트로 묶는다던지 하는 방식으로 사용된다. 단어의 뜻이 명확하게 드러나는 번역 단어가 없다고 생각하기 때문에 이후로는 그냥 배리언트라고 이야기하겠다.

5. 왼쪽 드롭 다운을 선택한다. "None"이라고 표시된 것은 현재 등록된 에셋 번들의 이름을 의미한다.

6. 아직 생성된 애셋 번들이 없다면 위 이미지와 같은 목록을 볼 수 있다.

7. "New..."를 클릭해서 새로운 에셋 번들을 생성한다.

8. 원하는 에셋 번들 이름을 입력한다.

- 애셋 번들 이름은 입력하는 내용에 따라 폴더 구조를 지원한다. 하위 폴더를 추가하려면 폴더 이름에 "/"로 나누어 표시한다.

- 예 : 에셋 번들 이름 "environment/forest"는 envionment 폴더 아래에 forest라는 번들을 생성한다.

9. 에셋 번들 이름을 선택하거나 생성한 후에는 원하는 경우 오른쪽 드롭다운에 대해 이 작업을 반복하면 배리언트 이름을 지정하거나 생성할 수 있다. 배리언트 이름은 에셋 번들을 빌드하는데 필요하지 않다.

 

에셋 번들 등록 및 그에 수반되는 전략에 대한 자세한 내용은 섹션 3을 참조하라.

 

에셋 번들 빌드

 

 

Assets 폴더에 Editor 폴더를 만들고 폴더에 다음 내용이 포함된 스크립트를 생성한다.

 

using UnityEditor;

public class CreateAssetBundles

{

[MenuItem("Assets/Build Asset Bundles")]

static void BuildAllAssetBundles()

{

string assetBundleDirectory = "Assets/AssetBundles";

if(!Directory.Exists(assetBundleDirectory))

{

Directory.CreateDirectory(assetBundleDirectory);

}

// 유니티 5.6에서 BuildTarget.Standalone은

// BuildTarget.StandaloneLinux;
// BuildTarget.StandaloneLinux64;
// BuildTarget.StandaloneLinuxUniversal;
// BuildTarget.StandaloneOSXIntel;
// BuildTarget.StandaloneOSXIntel64;
// BuildTarget.StandaloneOSXUniversal;
// BuildTarget.StandaloneWindows;
// BuildTarget.StandaloneWindows64;

// 등으로 세분화되었다.

BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.Standalone);

}

}

 

이 스크립트는 Assets 메뉴 맨 아래에 해당 태그와 관련된 함수에서 코드를 실행할 "Build Asset Bundles"라는 메뉴 항목을 만든다. "Build Asset Bundles"를 클릭하면 진행 막대(progress bar)와 함께 빌드 대화 상자가 나타난다. 이렇게 하면 에셋 번들의 이름으로 레이블된 모든 에셋을 가져와서 assetBundleDirectory에 정의된 경로의 폴더에 넣는다.

 

이 코드의 기능에 대해서 더 자세한 내용은 섹션 4에서 볼 수 있다.

 

별도의 저장소에 번들을 업로드

이 단계는 각 사용자에게 고유한 단계이며 Unity 측에서 수행 방법을 알려줄 수는 없다. 에셋 번들을 타사 호스팅 사이트에 업로드하려는 경우 이 단계에서 수행하면 된다. 엄격하게 지역 개발을 수행하고 에셋 번들을 모두 디스크에 저장하려면 다음 단계로 건너뛴다.

 

에셋과 에셋 번들 로딩

로컬 저장소에서 에셋을 로드하려는 사용자는 AssetBundles.LoadFromFile API에 관심을 가질 것이다. 다음을 보라 :

 

using System.IO;

public class LoadFromFileExample : MonoBehaviour
{
    void Start()
    {
        var myLoadedAssetBundle = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "myassetBundle"));
        if (myLoadedAssetBundle == null)
        {
            Debug.Log("Failed to load AssetBundle!");
            return;
        }
        var prefab = myLoadedAssetBundle.LoadAsset<GameObject> ("MyObject");
        Instantiate(prefab);
    }
}

 

여기서 LoadFromFile은 번들 파일의 경로를 사용한다.

 

에셋 번들을 직접 호스팅하고 게임에 다운로드 해야하는 경우 UnityWebRequest API를 사용해야 한다. 다음은 그 예시이다 :

 

using UnityEngine.Networking;

 

IEnumerator InstantiateObject()
{
      string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;

UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.GetAssetBundle(uri, 0);
yield return request.Send();
       
AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);

GameObject cube = bundle.LoadAsset<GameObject>("Cube");
GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");

Instantiate(cube);
Instantiate(sprite);

}

 

여기서 GetAssetBundle(string, int)은 에셋 번들의 위치와 다운로드하려는 번들의 버전에 대한 URI를 가져온다. 이 예제에서는 로컬 파일을 가리키고 있지만 URI 문자열은 호스팅된 에셋 번들이 있는 URL을 가리킬 수 있다.

 

UnityWebRequest는 요청으로부터 에셋 번들을 얻는 Asset Bundles, DownloadHandlerAssetBundle을 다루기 위한 특정 핸들을 가지고 있다.

 

사용하는 방법에 관계없이 이제 AssetBundle 객체에 액세스할 수 있다. 이 객체에서 LoadAsset<T>(string)을 사용해야 한다. LoadAsset<T>(string)은 로드하려는 에셋의 Type T와 번들 안에 있는 문자열을 통해서 객체의 이름을 가져온다. 이렇게하면 에셋 번들에서 로드하는 객체가 반환되는데 이 객체는 Unity 내부의 객체처럼 사용할 수 있다. 예를 들어 장면에서 만들려는 GameObject인 경우 Instantiate(gameObjectFromAssetBundle)를 호출하면 된다.

 

에셋 번들을 로드하는 API에 대한 자세한 내용은 섹션 6를 확인하면 된다.

 

섹션 3 : 에셋 번들을 위한 에셋 준비

 

 

에셋 등록 전략

에셋 번들을 사용할때 원하는 번들에 에셋을 자유롭게 등록할 수 있다. 그러나 번들을 설정할 때 고려해야 할 전략이 있다. 이러한 그룹화 전략은 특정 프로젝트에 적합하다. 적합하다고 생각하는 대로 이 전략들을 자유롭게 혼합하고 매치하라.

 

 

Logical Entity Grouping

Logical entity grouping은 에셋을 프로젝트의 기능적 부분에 따라 에셋 번들에 등록하는 방법이다. 여기에는 사용자 인터페이스, 문자, 환경 및 응용 프로그램이 실행되는 동안에 자주 사용되는 섹션이 포함된다.

 

예시:

사용자 인터페이스 화면의 모든 텍스처 및 레이아웃 데이터 번들링

캐릭터/캐릭터 집합에 대한 모든 모델 및 애니메이션 번들링(Charater가 문자인지 캐릭터인지 불명확)

여러 레벨에 걸쳐서 공유되는 배경을 위한 텍스처와 모델 번들링

 

Logical entity grouping는 이러한 방식으로 모든것이 분리된 상태에서 단일 엔티티로 변경할 수 있으며 변경되지 않은 추가 에셋을 다운로드할 필요가 없기 때문에 다운로드 가능한 컨텐츠(DLC)에 이상적이다.

 

이 전략을 올바르게 구현하는데 있어서 가장 큰 트릭은 개발자가 각 번들에 에셋을 등록하는 경우 프로젝트에서 각 에셋을 언제 어디서 사용하는지를 잘 알고 있어야 한다는 것이다.

 

 

Type Grouping

이 전략에서는 오디오 트랙이나 언어 현지화 파일과 같은 유형의 에셋을 단일 에셋 번들에 등록한다.

 

Type Grouping은 여러 플랫폼에서 사용할 에셋 번들을 빌드하기 위한 더 나은 전략 중 하나이다. 예를 들어 오디오 압축 설정이 Windows와 Mac 플랫폼간에 동일하다면 모든 오디오 데이터를 자체적으로 에셋 번들로 압축하고 해당 번들을 재사용할 수 있다. 반면 셰이더는 더 많은 플랫폼 별 옵션으로 컴파일되는 경향이 있으므로 Mac 용으로 빌드한 셰이더 번들은 Windows에서 재사용할 수 없다. 또한 이 방법은 텍스처 압축 형식 및 설정이 코드 스크립트나 프리팹과 같은 것보다 자주 변경되지 않으므로 에셋 번들을 더 많은 플레이어 버전과 호환되도록 만드는데 유용하다.

 

 

Concurrent Content Grouping

Concurrent Content Grouping은 동시에 로드되고 사용되는 자산을 함께 번들링하는 방법이다. 이러한 유형의 번들은 각 레벨에 고유한 캐릭터, 텍스처, 음악 등이 포함된 레벨 기반 게임에 사용되는 것으로 생각할 수 있다. 이러한 에셋 번들 중 하나의 에셋을 사용할 때 나머지 에셋을 동시에 사용해야한다. Concurrent Content Grouping 번들 내의 단일 자산에 대한 종속성을 가지게 되면 로딩 시간이 현저하게 늘어나게 된다. 단일 에셋에 대한 전체 번들을 다운로드해야 한다.


Concurrent Content Grouping 번들의 가장 일반적인 유스 케이스는 Scene을 기반으로 하는 번들이다. 이 등록 전략에서 각 scene 번들은 대부분의 scene 또는 모든 scene에 대한 종속성을 포함해야 한다.

 

프로젝트는 필요에 따라 이러한 전략들을 혼합하여 사용할 수 있어야 한다. 특정 상황에 대해 최적의 에셋 등록 전략을 사용하면 모든 프로젝트의 효율성이 상승한다.

 

예를 들어 프로젝트에서 서로 다른 플랫폼의 UI 요소를 고유한 플랫폼-UI 특정 번들로 그룹화하지만 레벨/scene 별로 대화형 콘텐츠를 그룹화하기로 결정할 수 있다.

 

사용하고자 하는 전략에 관계 없이, 다음과 같은 추가적인 팁이 있다 :

- 자주 업데이트되는 개체와 거의 변경되지 않는 개체를 별도로 에셋 번들로 분할한다.

- 동시에 로드될 수 있는 그룹 객체

-- 모델, 텍스쳐, 애니메이션과 같은

- 여러 에셋 집합에서 여러 객체가 완전히 다른 에셋 집합의 단일 에셋에 종속되어 있는 것을 발견하면 종속 집합을 별도의 에셋 번들로 이동시켜야 한다. 여러 에셋 번들이 다른 에셋 번들의 동일한 에셋 그룹을 참조하는 경우, 중복을 줄이기 위해 이러한 종속성을 공유 에셋 번들로 가져올 가치가 있다.

- 표준 및 고화질 에셋과 같이 두 세트의 개체가 동시에 로드되지 않을 가능성이 있는 경우 해당 개체가 에셋의 에셋 번들에 포함되어 있는지 확인해야 한다.

- 해당 번들의 50% 미만이 동시에 로드되는 경우 에셋 번들을 분리하는 것을 고려해야 한다.

- 소규모(에셋 5~10개 미만)이지만 콘텐츠가 동시에 자주 로드되는 에셋 번들을 결합하는 것을 고려해야 한다.

- 오브젝트 그룹이 단순히 동일한 오브젝트의 다른 버전일 경우, 에셋 번들 배리언트(Variants, 변형)를 고려해야 한다.

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

내장 그래픽 카드와 외장 그래픽 카드가 동시에 장착되어 있는 고사양의 노트북에서 윈도우 10 환경에서 유니티 엔진을 설치하고 사용하는데 문제가 발생했었다. 일단 내가 경험한 유니티 버전은 5.4.1이라 다른 버전에서도 동일한 문제가 발생하는지 모르겠지만 위와 같은 환경에서 약간은 심각한 문제가 발생한다. 그 문제가 무엇이냐면 유니티 작업을 어느 정도 진행하고 있으면 갑자기 화면이 한번 깜빡이고 난 이후에 유니티 화면이 하얗게 변하고 그 뒤로는 유니티 작업을 진행할 수 없게 되는 것이다.

 

이러한 문제는 유니티 재설치, 윈도우즈 포맷, 클린 부팅 등 여러가지 방법으로 해결을 시도해 보았으나 처음엔 멀쩡하다가 똑같은 문제가 지속적으로 발생했다.

 

그리고 한 번은 유니티가 꺼지는 도중에 [응용 프로그램이 그래픽 하드웨어에 액세스할 수 없도록 차단되었습니다.] 라는 경고문도 팝업됬었다.

 

어쨌든 작업을 계속 해야하기 때문에 이 문제를 해결하기 위해 여러가지로 알아본 결과, 문제의 원인은 노트북의 옵티머스 기능이 말썽을 일으킨 것으로 보인다.

 

옵티머스 기능을 통해서 유니티가 외장 그래픽 카드를 통해서 작동하도록 설정되어 있는데, 이것을 내장 그래픽이 작업을 하도록 변경하니 같은 문제가 더 이상 보이지 않는다.

 

해결법

1. NVIDIA 제어판에 들어간다.

 

2. 3D 설정 관리에 들어간다.

 

3. 프로그램 설정 탭으로 들어간다.

4. 사용자 정의할 프로그램 선택에서 유니티 엔진을 선택한다.

5. 이 프로그램에 대한 기본 그래픽 프로세서 선택에서 통합 그래픽을 선택한다.

 

위의 과정을 모두 거치면 유니티 엔진을 내장 그래픽으로 작동하게 될 것이고, 화면 깜빡임 이후에 유니티가 먹통이 되는 현상은 발생하지 않을 것이다.

 

참고

 

{{MetaTags.og.title}}

{{MetaTags.og.description}}

www.nvidia.com

 

 

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

+ Recent posts