이어지는 섹션에서는 에셋 번들을 사용하는 프로젝트에서 흔히 발생하는 몇 가지 문제에 대해 설명합니다.
Unity의 에셋 번들 시스템은 오브젝트가 에셋 번들에 빌드될 때 해당 오브젝트의 모든 종속성을 발견합니다.이는 에셋 데이터베이스를 사용하여 수행됩니다.이 종속성 정보는 에셋 번들에 포함될 오브젝트 세트를 결정하는 데 사용됩니다.
에셋 번들에 대한 할당은 에셋 수준에서 이루어집니다.에셋 번들에 명시적으로 할당된 에셋 내부의 오브젝트는 해당 단일 에셋 번들에만 빌드됩니다.BuildPipeline.BuildAssetBundles의 어떤 서명이 호출되는지에 따라, 에셋의 AssetImporter.assetBundleName 프로퍼티를 비어 있지 않은 문자열로 설정하거나 이것을 AssetBundleBuild.assetNames에 나열함으로써 에셋이 “명시적으로 할당됩니다”.
에셋 번들에 명시적으로 할당되지 않은 에셋의 일부인 오브젝트는 해당 오브젝트를 참조하는 오브젝트가 포함된 각 에셋 번들에 포함됩니다.
즉, 두 개의 다른 오브젝트가 두 개의 다른 에셋 번들에 할당되었지만 둘 다 공통 종속성 오브젝트에 대한 레퍼런스가 있는 경우 해당 종속성 오브젝트가 두 에셋 번들 모두에 복사됩니다.중복된 종속성도 인스턴스화되므로 종속성 오브젝트의 두 사본은 다른 식별자를 가진 다른 오브젝트로 간주됩니다.이렇게 하면 애플리케이션의 에셋 번들의 총 크기가 증가합니다.또한 애플리케이션이 두 부모를 모두 로드하는 경우 오브젝트의 서로 다른 두 사본이 메모리에 로드됩니다.
이 문제는 아래의 몇 가지 방법으로 해결할 수 있습니다.
서로 다른 에셋 번들에 내장된 오브젝트가 종속성을 공유하지 않도록 합니다. 종속성을 공유하는 오브젝트는 종속성 중복 없이 동일한 에셋 번들에 포함시킬 수 있습니다.
종속성을 공유하는 두 에셋 번들이 동시에 로드되지 않도록 에셋 번들을 분할합니다.
모든 종속성 에셋이 자체적인 에셋 번들에 내장되도록 합니다. 그러면 에셋이 중복될 위험이 완전히 배제되지만, 애플리케이션이 에셋 번들 간 종속성을 추적해야 하고 AssetBundle.LoadAsset API를 호출하기 전에 올바른 에셋 번들이 로드되는지 확인해야 하는 복잡성이 발생합니다.
오브젝트 종속성은 UnityEditor 네임스페이스에 있는 AssetDatabase API를 통해 추적됩니다.네임스페이스에서 알 수 있듯이 이 API는 런타임이 아닌 Unity 에디터에서만 사용할 수 있습니다.AssetDatabase.GetDependencies는 특정 오브젝트 또는 에셋의 모든 즉각적인 종속성을 찾는 데 사용할 수 있습니다.이러한 종속성에는 자체 종속성이 있을 수 있으므로 재귀적 계산이 될 수 있다는 점에 유의하십시오.에셋을 에셋 번들에 할당하는 것은 BuildPipeline.BuildAssetBundles를 호출할 때 에셋 번들 빌드 구조의 배열을 전달하여 명시적으로 정의하거나, AssetImporter API를 사용하여 쿼리할 수 있습니다.에셋 번들의 모든 직접 또는 간접 종속성이 에셋 번들에 할당되거나 두 개의 에셋 번들이 에셋 번들에 할당되지 않은 종속성을 공유하지 않도록 보장하는 에디터 스크립트를 작성할 수 있습니다.
참고:Addressables 패키지로 에셋 번들을 빌드할 때 ‘Addressables Analyze’ 창을 사용하여 중복된 에셋을 발견할 수 있습니다.
이어지는 섹션에서는 에셋 종속성 계산 코드를 자동 생성된 스프라이트 아틀라스와 함께 사용할 경우에 발생할 수 있는 문제점에 대해 설명합니다.
자동 생성 스프라이트 아틀라스는 스프라이트 아틀라스가 생성된 스프라이트 오브젝트가 포함된 에셋 번들에 할당됩니다. 스프라이트 오브젝트가 여러 에셋 번들에 할당된 경우, 스프라이트 아틀라스가 에셋 번들에 할당되지 않고 중복됩니다. 스프라이트 오브젝트가 에셋 번들에 할당되지 않은 경우, 스트라이트 아틀라스도 에셋 번들에 할당되지 않습니다.
스프라이트 아틀라스가 중복되지 않도록 하려면 모든 동일한 스프라이트 아틀라이스 안에 태그된 스프라이트가 동일한 에셋 번들에 할당되는지 확인합니다.
Android 에코시스템에는 매우 다양한 디바이스가 있기 때문에 종종 텍스처를 몇 가지 다른 포맷으로 압축해야 할 필요가 있습니다. 모든 Android 디바이스는 ETC1을 지원하지만, ETC1은 알파 채널이 있는 텍스처를 지원하지 않습니다. 애플리케이션에서 OpenGL ES 2 지원이 필요하지 않은 경우, 모든 OpenGL ES 3 디바이스에서 지원되는 ETC2를 사용하면 문제를 가장 간단하게 해결할 수 있습니다.
대부분의 애플리케이션은 ETC2를 지원할 수 없는 구형 기기에서 제공되어야 합니다.이 문제를 해결하는 한 가지 방법은 에셋 번들 배리언트를 사용하는 것입니다.(다른 옵션에 대한 자세한 내용은 Unity의 Android 최적화 가이드를 참조하십시오.)
에셋 번들 배리언트를 사용하려면 ETC1을 사용하여 완전히 압축할 수 없는 모든 텍스처를 텍스처 전용 에셋 번들에 분리해야 합니다. 그런 다음 DXT5, PVRTC 및 ATITC 같은 제조사별 텍스처 압축 포맷을 사용해 Android 에코시스템의 ETC2 사용 불가 부분을 지원하는 해당 에셋 번들의 배리언트를 충분히 만드십시오. 각 에셋 번들 배리언트에 대해, 포함된 텍스처의 TextureImporter 설정을 배리언트에 해당되는 압축 포맷으로 변경합니다.
런타임 시 다양한 텍스처 압축 포맷 지원 여부를 SystemInfo.SupportsTextureFormat API를 사용하여 인식할 수 있습니다. 이 정보를 사용해 지원되는 포맷으로 압축된 텍스터가 포함되어 있는 에셋 번들 배리언트를 선택하고 로드해야 합니다.
Android 텍스처 압축 포맷에 대한 자세한 내용은 여기에서 확인할 수 있습니다.
에셋 번들을 빌드할 때 Unity는 해당 번들의 정보를 사용하여 컴파일할 셰이더 배리언트를 선택합니다.여기에는 에셋 번들에 있는 씬, 머티리얼, 그래픽스 설정 및 ShaderVariantCollections에 대한 정보가 포함됩니다.
별도의 빌드 파이프라인은 다른 파이프라인과 독립적으로 자체 셰이더를 컴파일합니다.플레이어 빌드와 어드레서블 빌드가 모두 셰이더를 참조하는 경우 Unity는 각 파이프라인에 대해 하나씩 두 개의 셰이더 사본을 컴파일합니다.
이 프로세스에서는 키워드, 텍스처 또는 코드 실행으로 인한 변경 사항과 같은 런타임 정보는 고려하지 않습니다.빌드에 특정 셰이더를 포함하려면 원하는 셰이더가 포함된 ShaderVariantCollection을 포함하거나 그래픽 설정의 항상 포함된 셰이더 목록에 셰이더를 추가하여 수동으로 빌드에 셰이더를 포함하십시오.