Version: 2017.1
Unity 4에서 에셋 번들 생성
레거시 애니메이션 시스템(Legacy Animation System)

Unity 4의 에셋 종속성 관리

Unity 5 이전 버전에서는 에셋 종속성을 에디터 스크립트만으로 정의했습니다(Unity 5에서는 에셋을 특정 번들에 할당하고 종속성을 자동으로 처리하는 툴을 에디터에서 제공합니다). 본 정보는 Unity 4의 레거시 프로젝트 작업을 위해 제공되며 Unity 4 사용자를 염두에 두고 작성되었습니다.

번들의 모든 에셋은 다른 에셋에 종속합니다. 예를 들어, 모델에 텍스처와 셰이더를 이용하는 머티리얼이 포함되어 있는 식입니다. 에셋의 종속성과 함께 해당 번들에 포함시키는 것도 가능합니다. 하지만 서로 다른 번들의 여러 에셋이 모두 공통의 어떤 에셋에 종속하는 경우도 있습니다(가령 여러 다른 건물의 모델이 동일한 벽돌 텍스처를 사용하는 것입니다). 만약 공유된 종속성을 가지는 별도 복사본이 이를 사용하는 오브젝트를 갖는 번들마다 들어가면 번들이 로드될 때 에셋에 불필요한 인스턴스가 생성돼 메모리를 낭비시킵니다.

그런 낭비를 피하기 위해 공유된 종속성을 개별 번들로 나누고 필요로 하는 에셋이 있는 번들에서 단순하게 참조하는 것도 가능합니다. 먼저, BuildPipeline.PushAssetDependencies를 호출하여 참조 기능을 활성화합니다. 그런 다음, 참조된 종속성을 포함하는 번들을 빌드합니다. 그리고 첫 번째 번들의 에셋을 참조하는 번들을 빌드하기 전에 PushAssetDependencies를 한번 더 호출해야 합니다. 추가적인 종속성 단계는 PushAssetDependencies를 추가 호출해서 실현될 수 있습니다. 참조 단계는 스택에 저장되기 때문에 해당 BuildPipeline.PopAssetDependencies 함수를 사용해 한 단계 되돌아갈 수 있습니다. 푸시와 팝 호출은 빌드 전에 발생한 초기 푸시를 포함해서 균형을 맞출 필요가 있습니다.

런타임 시 종속성을 포함하는 번들을 참조하는 다른 번들보다 먼저 해당 번들을 로드할 필요가 있습니다. 예를 들어, 공유된 텍스처를 참조하는 머티리얼이 있는 번들을 로드하기 전에 그 텍스처 번들을 먼저 로드해야 합니다.

에셋(Asset) ID

만약 종속성 연결 관계의 일부인 에셋 번들을 다시 빌드할 필요가 있다고 예상된다면 BuildAssetBundleOptions.DeterministicAssetBundle 옵션을 활성화해 빌드해야 합니다. 이렇게 하면 에셋을 식별하는 데 사용되는 내부 ID 값이 번들을 다시 빌드할 때마다 동일하게 유지됩니다.

에셋 번들을 이 메서드로 빌드할 때 오브젝트에는 에셋 번들 파일 이름, 에셋의 GUID, 에셋의 오브젝트 로컬 ID를 사용해 계산된 32비트 해시 코드가 할당됩니다. 그러므로 다시 빌드할 때 반드시 동일한 파일 이름을 사용해야 합니다. 또한 오브젝트가 많으면 해시 충돌이 일어나 에셋 번들 빌드를 못할 수 있으니 주의하십시오.

셰이더(Shaders) 종속성

셰이더가 BuildPipeline.BuildAssetBundle에서 파라미터로 직접 참조되거나 옵션 BuildAssetBundleOptions.CollectDependencies로 간접적으로 참조될 때마다 셰이더의 코드가 에셋 번들에 포함됩니다. 만약 여러 에셋 번들을 생성하면서 BuildAssetBundle만 사용한다면 참조된 셰이더가 생성된 번들 모두에 포함돼 문제가 생길 수 있습니다. 여러 버전의 셰이더를 믹스하는 충돌이 일어날 수 있으므로 셰이더를 변경한 후 번들 전체를 다시 빌드해야 합니다. 또한 셰이더의 코드는 번들 크기를 증가시킵니다. 이런 문제를 피하려면 BuildPipeline.PushAssetDependencies를 사용해서 단일 번들로 셰이더를 분리하고 해당 셰이더 번들만 업데이트하면 됩니다. 이 워크플로를 달성하는 예로서 필요한 셰이더의 참조를 포함하는 프리팹을 생성할 수 있습니다.

C# 예제

using UnityEngine;

public class ShadersList : MonoBehaviour {
    public Shader[] list;
}


빈 오브젝트를 생성해 스크립트를 할당하고 리스트에 셰이더를 추가한 후 프리팹을 생성합니다(“ShadersList”). 그런 다음 모든 번들을 생성하고 셰이더의 번들을 업데이트 하는 익스포터를 생성할 수 있습니다.

C# 예제

using UnityEngine;
using UnityEditor;

public class Exporter : MonoBehaviour {
    
    [MenuItem("Assets/Export all asset bundles")]
    static void Export() {
        BuildAssetBundleOptions options = 
            BuildAssetBundleOptions.CollectDependencies | 
            BuildAssetBundleOptions.CompleteAssets | 
            BuildAssetBundleOptions.DeterministicAssetBundle;
        
        BuildPipeline.PushAssetDependencies();
        BuildPipeline.BuildAssetBundle(AssetDatabase.LoadMainAssetAtPath("Assets/ShadersList.prefab"), null, "Data/ShadersList.unity3d", options);
            
        BuildPipeline.PushAssetDependencies();
        BuildPipeline.BuildAssetBundle(AssetDatabase.LoadMainAssetAtPath("Assets/Scene1.prefab"), null, "Data/Scene1.unity3d", options);
        BuildPipeline.BuildAssetBundle(AssetDatabase.LoadMainAssetAtPath("Assets/Scene2.prefab"), null, "Data/Scene2.unity3d", options);        
        
        BuildPipeline.PopAssetDependencies();
        BuildPipeline.PopAssetDependencies();
    }
    
    [MenuItem("Assets/Update shader bundle")]
    static void ExportShaders() {
        BuildAssetBundleOptions options = 
            BuildAssetBundleOptions.CollectDependencies | 
            BuildAssetBundleOptions.CompleteAssets | 
            BuildAssetBundleOptions.DeterministicAssetBundle;
        
        BuildPipeline.PushAssetDependencies();
        BuildPipeline.BuildAssetBundle(AssetDatabase.LoadMainAssetAtPath("Assets/ShadersList.prefab"), null, "Data/ShadersList.unity3d", options);
        
        BuildPipeline.PopAssetDependencies();
    }
}


셰이더 번들을 먼저 로드해야 한다는 것을 꼭 기억하십시오. 이 메서드의 한 가지 단점은 오브젝트 양이 클 때 BuildAssetBundleOptions.DeterministicAssetBundle 옵션이 해시 충돌을 일으킬 수 있습니다. 이 경우 빌드가 실패하고 셰이더 번들만 업데이트할 수 없으므로 해당 옵션을 제거하고 에셋 번들 전체를 다시 빌드해야 합니다.

Unity 4에서 에셋 번들 생성
레거시 애니메이션 시스템(Legacy Animation System)