Total: Today: Yesterday:
개발/Unity | 2020. 6. 10. 12:11 | Posted by 자수씨

어드레서블에 대한 이해를 하고자 해보았으나 실제 사용하는 방법은 약간 차이가 있다.

일단 하던 번역은 마무리하고 실제 사용 전략에 대해 정리할 예정이다.

2020/06/09 - [개발/Unity] - Addressable Assets development cycle (1)
2020/06/10 - [개발/Unity] - Addressable Assets development cycle (2)

컨텐츠 업데이트 빌드 (Building for content updates)

컨텐츠 업데이트를 빌드하려면 다음을 수행한다.

  1. 유니티 에디터에서 Addressable Groups window 를 연다 (Window > Asset Management > Addressables > Gruops)
  2. Addressable Groups window 에서 탑 메뉴의 Build > Update a Previous Build 를 선택한다.
  3. 빌드 데이터 파일 (Build Data File) 다이얼로그 팝업이 열리면 addressable_content_state.bin 파일을 선택한다.

빌드를 통해 컨텐츠 카탈로그, 해시 파일 및 에셋번들이 생성된다.

생성된 컨텐츠 카탈로그는 선택된 애플리케이션 빌드의 카탈로그와 동일한 이름을 가지며 이전 카탈로그 및 해시 파일을 겹쳐 쓴다. 애플리케이션은 새 카탈로그가 사용가능한지 판별하기 위해 해시 파일을 로드한다. 시스템은 애플리케이션과 함께 제공되거나 이미 다운로드 된 기존 번들에서 수정되지 않은 에셋을 로드한다.

시스템은 addressables_content_state.bin 에서 컨텐츠 버전 문자열과 위치 정보를 사용하여 에셋 번들을 생성한다. 업데이트 된 컨텐츠를 포함하지 않는 에셋 번들은 업데이트를 위해 선택된 빌드의 파일 이름과 동일한 이름을 사용하여 작성된다. 에셋 번들에 업데이트 된 컨텐츠가 포함된 경우 원래 파일과 공존할 수 있도록 업데이트가 된 컨텐츠를 포함하는 새 에셋 번들이 새로운 파일 이름으로 작성된다. 새 파일 이름을 가진 에셋 번들만 컨텐츠를 호스팅 하는 위치로 복사되어야 한다.

또한 시스템은 변경할 수 없는 컨텐츠에 대한 에셋 번들을 빌드하지만 어드레서블 에셋 항목이 참조하지 않으므로 컨텐츠 호스팅 위치에 업로드할 필요는 없다.

새 플레이어를 빌드하고 컨텐츠를 업데이트 하는 (예: 플레이어 코드, 어드레서블) 빌드 스크립트를 변경해서는 안된다. 애플리케이션에서 예기치 않은 동작이 발생될 수 있다.

 

 

런타임 시 컨텐츠 업데이트 확인 (Checking for content updates at runtime)

새로운 어드레서블 컨텐츠 업데이트가 있는지 정기적으로 확인하기 위해 사용자 정의 스크립트를 추가할 수 있다. 다음 함수 호출을 사용하여 업데이트를 시작한다.

public static AsyncOperationHandle<List<string>> CheckForCatalogUpdates(bool autoReleaseHandle = true)

리턴 값의 List<string> 은 수정된 위치 ID 목록이 포함된다. 이 ID를 필터링하여 특정 ID 만 업데이트하거나 완전히 UpdateCatalogs API 로 전달할 수 있다.

새로운 컨텐츠가 있는 경우 업데이트를 수행할 수 있는 버튼을 사용자에게 제공하거나 자동으로 수행할 수 있다. 오래된 에셋이 릴리즈되었는지 확인하는 것은 개발자의 책임이다.

카탈로그 목록은 null이 될 수 있으며, 필요한 경우 다음 스크립트는 업데이트가 필요한 모든 카탈로그를 업데이트한다.

public static AsyncOperationHandle<List<IResourceLocator>> UpdateCatalogs(IEnumerable<string> catalogs = null, bool autoReleaseHandle = true)

리턴 값은 업데이트 된 위치 목록이다.

 

 

컨텐츠 업데이트 예 (Content update examples)

이 예제에서 제공된 애플리케이션은 다음 그룹을 인식한다.

Local_Static Remote_Static Remote_NonStatic
AssetA AssetL AssetX
AssetB AssetM AssetY
AssetC AssetN AssetZ

참고: Local_StaticRemote_StaticCannot Change Post Release 그룹의 일부이다.

이 버전은 라이브 버전이므로 디바이스에 Local_Static 를 가지고 있는 플레이어가 있고 원격 번들 중 하나 또는 둘 모두가 로컬로 캐시되어 있을 수 있다.

각 그룹에서 하나의 에셋 (AssetA, AssetL, AssetX) 을 수정한 다음 Check for Content Update Restrictions 를 실행하면 로컬 어드레서블 설정의 결과는 아래와 같다.

Local_Static Remote_Static Remote_NonStatic content_update_group (non-static)
    AssetX AssetA
AssetB AssetM AssetY AssetL
AssetC AssetN AssetZ  

참고: 준비 작업은 실제로 Cannot Change Post Release 그룹을 편집하므로 직관적이지 않을 수 있다.그러나 핵심은 시스템이 위의 레이아웃을 빌드하지만 이러한 그룹에 대한 빌드 결과를 버리는 것이다. 따라서 플레이어의 관점에서 다음과 같이 정리된다.

 

Local_Static
AssetA
AssetB
AssetC

Local_Static 번들은 변경할 수 없는 플레이어 장치에 이미 있다. 이 이전 버전 AssetA 는 더 이상 참조되지 않는다. 대신 플레이어 장치에 죽은 데이터로 남아있게 된다.

 

Remote_Static
AssetL
AssetM
AssetN

Remote_Static 번들은 변경되지 않는다. AssetM 이나 AssetN 이 플레이어 장치에 아직 캐시되지 않은 경우 요청 시 다운로드 된다. AssetA 와 같이 이전 버전 AssetN 은 더 이상 참조되지 않는다.

 

Remote_NonStatic (old)
AssetX
AssetY
AssetZ

Remote_NonStatic 번들은 이제 오래되었다. 서버에서 삭제할 수 있으며 이 시점부터는 다운로드 되지 않는다. 캐시가 되더라도 결국 캐시에서 삭제된다. AssetAAssetL 처럼 이전 버전 AssetX 는 더 이상 참조되지 않는다.

 

Remote_NonStatic (new)
AssetX
AssetY
AssetZ

이전 Remote_NonStatic 번들은 해시 파일로 구별되는 새 버전으로 대체된다. 수정된 버전은 AssetX 가 새 번들로 업데이트 된다.

 

content_update_group
AssetA
AssetL

 

이전 content_update_group 번들은 전진 참조(referenced moving forward)될 수정된 에셋으로 구성되어 있다.

위의 예는 다음과 같은 의미를 갖는다.

  1. 변경된 로컬 에셋은 사용자 장치에서 영원히 사용되지 않은 상태로 유지된다.
  2. 사용자가 비정적(non-static) 번들을 이미 캐시한 경우 변경되지 않은 에셋 (예: AssetY, AssetZ) 을 포함하여 번들을 다시 다운로드해야 한다. 이상적으로 사용자는 번들을 캐시하지 않았으므로 새로운 Remote_NonStatic 번들을 다운로드하면 된다.
  3. 사용자가 이미 Static_Remote 번들을 캐시한 경우 업데이트 된 에셋만 다운로드하면 된다. ( 이 경우 AssetLcontent_update_group 을 통해). 이 경우에는 이상적이다. 사용자가 번들을 캐시하지 않은 경우 수정되지 않은 번들을 통해 content_update_group 을 통해 새로운 AssetL 과 수정되지 않은 Remote_Static 번들을 통해 현재 없어진 AssetL 을 모두 다운로드 해야 한다. 초기 캐시 상태와 상관없이, 어느 시점에 사용자는 장치에 기능이 없는 AssetL 을 갖게 되며, 액세스하지 않아도 무기한으로 캐시된다.

개발/Unity | 2020. 6. 10. 12:10 | Posted by 자수씨

컨텐츠 업데이트 워크플로우 (Content update workflow)

유니티는 게임 컨텐츠를 두 가지 범주로 구성하는 것을 권장한다.

  • Cannot Change Post Release: 업데이트 하지 않을 것으로 예상되는 정적 컨텐츠
  • Can Change Post Release: 업데이트 될 수 있는 동적 컨텐츠

이 구조에서 Cannot Change Post Release 로 지정된 컨텐츠는 애플리케이션과 함께 제공(설치 즉시 다운로드되어 로드되거나) 되고 매우 작은 번들에 상주한다. Can Change Post Release 로 지정된 컨텐츠는 각 업데이트에 필요한 데이터 양을 최소화하기 위해 작은 번들에 온라인으로 상주한다. 어드레서블 에셋 시스템의 목표 중 하나는 스크립트를 변경하지 않고도 이 구조를 쉽게 작업하고 변경할 수 있도록 하는 것이다.

 

작동 원리 (How it works)

어드레서블은 컨텐츠 카탈로그를 사용하여 로드하는 위치와 방법을 지정하여 각 에셋의 주소를 매핑한다. 앱에 매핑이 변경되는 기능을 제공하려면 원본 앱이 카탈로그의 온라인 사본을 알고 있어야 한다. 이러한 설정을 하기 위해서는 AddressableAssetSettings 인스펙터에서 Build Remote Catalog 설정을 활성화해야 한다. 이를 통해 카탈로그 사본이 지정된 경로에 빌드되어 로드되는 것을 보장한다. 앱이 제공된 이후에는 이 로드 경로를 변경할 수 없다. 컨텐츠 업데이트 프로세스는 파일 이름이 동일한 카탈로그의 새 버전을 작성하여 이전에 지정된 로드 경로에서 파일을 겹쳐 쓴다.

애플리케이션을 빌드하면 고유한 앱 컨텐츠 버전 문자열이 생성되어 각 앱이 로드해야 하는 컨텐츠 카탈로그를 식별한다. 서버는 충돌없이 여러 버전의 앱 카탈로그가 포함될 수 있다. 필요한 데이터는 addressables_content_state.bin 파일에 저장된다. 여기에는 Cannot Change Post Release 로 지정된 그룹에 포함된 모든 에셋에 대한 새시 정보와 함께 버전 문자열이 저장된다. 기본적으로 프로젝트 디렉토리의 Assets/AddressableAssetsData/\<platform\> 에 위치한다.

addressables_content_state.bin 파일에는 어드레서블 시스템의 모든 Cannot Change Post Release 에셋 그룹에 대한 해시 및 종속성 정보가 포함되어 있다. StreamingAssets 폴더에 빌드된 모든 그룹은 Cannot Change Post Release 로 지정되어야 하지만 대규모 원격 그룹도 이러한 지정에 이점을 가질 수 있다. 다음 단계 (아래에 설명된 컨텐츠 업데이트 준비)에서 이 해시 정보는 Cannot Change Post Release 그룹에 변경된 자산이 포함되어 있는지 여부를 결정하므로 해당 에셋을 다른 곳으로 이동해야 한다.

 

고유 번들 ID (Unique Bundle IDs)

에셋 번들을 메모리에 로드할 때 유니티는 동일한 내부 이름으로 두 개의 번들을 로드할 수 없도록 강제한다. 이로 인해 런타임 시 번들 업데이트에 제한이 있을 수 있다. 현재 어드레서블은 초기화 외부에서 카탈로그 업데이트를 지원하므로 이미 로드된 컨텐츠를 업데이트 할 수 있다.

이 작업을 수행하려면 두 가지 중 하나가 발생해야 한다. 한 가지 옵션은 카탈로그를 업데이트하기 전에 모든 어드레서블 컨텐츠를 언로드하는 것이다. 두 번째 옵션은 업데이트 된 에셋번들에 고유한 내부 식별자가 있는지 확인하는 것이다. 이를 통해 새 번들을 로드할 수 있으며 이전 번들은 여전히 메모리에 있게 된다. 두 번째 옵션을 활성화하는 옵션은 AddressableAssetSettings 인스펙터에서 "Unique Bundle IDs" 를 켜는 것이다. 이 옵션의 단점은 번들을 종속성 체인으로 재구성해야 한다는 것이다. 한 그룹에서 매터리얼을 변경한 경우 기본적으로 매터리얼 번들만 다시 작성하면 되지만 "Unique Bundle IDs" 옵션이 활성화되면 해당 매터리얼을 참조하는 모든 에셋을 리빌딩해야 한다.

 

컨텐츠 업데이트 준비 (Preparing for content updates)

Cannot Change Post Release 그룹에서 에셋을 수정한 경우 Check for Content Update Restrictions 명령을 실행해야 한다. 이 명령을 통해 수정된 에셋이 Cannot Change Post Release 그룹에서 제거되어 새 그룹으로 이동한다. 새 에셋 그룹을 생성하려면 아래와 같다.

  1. 유니티 에디터에서 Addressable Groups window 를 연다. (Window > Asset Management > Addressables > Groups)
  2. Addressable Groups window 에서 메뉴바의 Tools > Check for Content Update Restrictions 를 선택한다.
  3. 빌드 데이터 파일 (Build Data File) 다이얼로그 팝업이 열리면 addressable_content_state.bin 파일을 선택한다.

이 데이터는 애플리케이션이 마지막으로 빌드 된 이후 수정된 에셋 또는 종속성을 결정하는데 사용된다. 시스템은 컨텐츠 업데이트 빌드를 준비하기 위해 이러한 에셋을 새 그룹으로 옮긴다.

참고: 이 명령은 모든 변경 사항이 Can Change Post Release 그룹으로 제한된 경우 아무 작업도 수행하지 않는다.

중요: 준비 작업을 실행하기 전에 버전 관리 시스템을 분기하는 것이 좋다. 준비 작업은 컨텐츠 업데이트에 적합한 방식으로 에셋 그룹을 재정렬한다. 분기는 다음에 새 플레이어의 제공 시점에 원하는 컨텐츠 배열로 돌아갈 수 있도록 한다.

개발/Unity | 2020. 6. 9. 13:03 | Posted by 자수씨

영여 실력이 번역할 정도는 아니지만 내용 파악을 위해 진행한다.

 

 

Addressable Assets (이하 어드레서블 에셋) 의 주요 이점은 컨텐츠의 배열, 빌드 그리고 로드하는 방법을 분리하는 것이다. 전통적으로 이러한 개발 측면에서는 이런 것들이 밀접하게 연관되어 있었다.

전통적인 에셋 관리

Resource 디렉토리에 컨텐츠를 배열하면 기본 애플리케이션에 내장되며 리소스에 대한 경로를 파라미터로 사용하는 Resources.Load 메소드를 사용하여 컨텐츠를 로드해야 한다. 다른 곳에 저장된 컨텐츠를 접근하려면 직접 참조나 asset bundle (이하 에셋 번들) 을 사용한다. 에셋 번들을 사용하는 경우 리소스 로드와 구성 전략을 함께 묶어 경로 별로 다시 로드한다. 에셋 번들이 원격 환경에 있거나 다른 번들에 종송된 경우 모든 번들의 다운로드, 로드 및 언로드를 관리하는 코드를 작성해야 한다.

어드레서블 에셋 관리

에셋에 주소를 부여하면 프로젝트의 위치나 에셋 빌드 방법과 상관없이 해당 주소를 사용하여 로드할 수 있다. 어드레서블 에셋의 경로나 파일이름을 문제 없이 변경할 수 있다. 또한 로딩하는 코드 변경 없이 리소스 폴더 또는 로컬 빌드 대상에서 다른 빌드 위치 (원격 환경 포함) 로 어드레서블 에셋을 이동할 수 있다.

에셋 그룹 스키마 (Asset Group schemas)

스키마는 일련의 데이터를 정의한다. 인스펙터에서 스키마를 자산 그룹에 연결할 수 있다. 예를 들어 packed 모드로 빌드할 때 BundledAssetGroupSchema 스키마가 첨부된 그룹은 에셋 번들의 소스로 작동한다. 새로운 그룹을 정의하는데 사용하는 템플릿으로 스키마 집합을 결합할 수 있다. AddressableAssetsSettings 인스펙터를 통해 스키마 템플릿을 추가할 수 있다.

빌드 스크립트 (Build scripts)

빌드 스크립트는 프로젝트 내에 IDataBuild 인터페이스를 구현한 ScriptableObject 에셋으로 표시된다. 사용자는 자신만의 빌드 스크립트를 생성하고 인스펙터를 통해 AddressableAssetsSettings 객체에 추가할 수 있다. Addressable Groups window (Window > Asset Management > Addressables > Groups) 에서 빌드 스크립트를 적용하려면, 플레이 모드 스크립트(Play Mode Script)와 드롭다운 옵션을 선택한다. 현재 전체 애플리케이션 빌드를 지원하기 위해 구현된 세 가지 스크립트와 에디터에서 반복하기 위한 세 가지 플레이 모드 스크립트가 있다.

플레이 모드 스크립트 (Play mode scripts)

어드레서블 에셋 패키지에는 앱 개발 속도를 높이는 플레이 모드 데이터를 만드는 데 도움을 주는 세 가지 빌드 스크립트가 있다.

에셋 데이터 베이스 사용 (Use Asset Database, faster)

빠른 모드 (BuildScriptFastMode) 를 사용하면 게임 흐름을 진행하면서 빠르게 실행할 수 있다. 빠른 모드는 분석이나 에셋 생성 없이 빠른 반복을 위해 에셋 베이터베이스를 이용하여 에셋을 직접 로드한다.

그룹 시뮬레이션 (Simulate Group, advanced)

가상 모드 (BuildScriptVirtualMode) 는 에셋 번들을 생성없이 컨텐츠를 레이아웃과 종속성을 위한 컨텐츠를 분석한다. 마치 에셋 ResourceManager 가 번들을 통해 로드 된 것 처럼 에셋 데이터베이스에서 로드한다. 게임 플레이 중 번들이 언제 로드 또는 언로드되는지는 Addressable Event Viewer window (Window > Asset Mangement > Addressables > Event Viewer) 에서 에셋 사용량을 확인할 수 있다.

가상모드를 사용하면 로드 전략을 시뮬레이션하고 컨텐츠 그룹을 조정하여 제품 릴리즈에 적합한 균형을 찾을 수 있다.

기존 빌드 사용 (Use Existing Build, requires built groups)

압축 재생 모드 (BuildScriptPAckedPlayMode) 는 이미 구축된 에셋 번들을 사용한다. 이 모드는 배포된 애플리케이션 빌드와 가장 일치하지만 별도의 단계로 데이터를 빌드해야 한다. 에셋을 수정하지 않으면 이 모드는 플레이 모드로 들어갈 때 데이터를 처리하지 않기 때문에 가장 빠르다. Build > New Build > Default Build Script 를 선택하거나 게임 스크립트의 메소드를 사용하여 Addressable window (Window > Asset Management > Addressables > Groups) 에서 AddressableAssetSettings.BuildPlayerContent() 메소드를 이용하여 이 모드의 컨텐츠를 빌드해야 한다.

분석 및 디버깅 (Analysis and debugging)

기본적으로 어드레서블 에셋은 경고/에러에 대해 기록만 한다. 상세 로그를 활성화 하기 위해서는 Player settings window (Edit > Project Settings... > Player) 을 열고 Other Settings > Configuration 섹션으로 이동한 후 Scripting Define Symbols 필드에 ADDRESSABLES_LOG_ALL 를 추가한다.

초기화 객체 (Initialization objects)

어드레서블 에셋 설정에 객체를 첨부하고 런터임에 초기화 프로세스로 전달할 수 있다. CacheInitializationSettings 객체는 런타임 시 유니티의 캐싱 API 를 제어한다. 자체 초기화 객체를 만드려면 IObjectInitializationDataProvider 인터페이스를 구현하는 ScriptableObject 를 만든다. 이는 런타임 데이터로 직렬화된 ObjectInitializationData 를 생성을 담당하는 시스템의 Editor 구성요소이다.

커스터마이징 URL 평가 (Customizing URL Evaluation)

런타임 시에 에셋 (일반적으로 에셋 번들) 의 경로 또는 URL 을 커스터마이징 해야 하는 몇 가지 시나리오가 있다. 가장 일반적인 예는 서명된 URL 을 생성하는 것이다. 다른 하나는 동적 호스트 결정일 수 있다.

아래 코드는 모든 URL 에 쿼리 문자열을 추가하는 예이다.

//Implement a method to transform the internal ids of locations
string MyCustomTransform(IResourceLocation location)
{
    if (location.ResourceType == typeof(IAssetBundleResource) && location.InternalId.StartsWith("http"))
        return location.InternalId + "?customQueryTag=customQueryValue";
    return location.InternalId;
}

//Override the Addressables transform method with your custom method.  This can be set to null to revert to default behavior.
[RuntimeInitializeOnLoadMethod]
static void SetInternalIdTransform()
{
    Addressables.InternalIdTransformFunc = MyCustomTransform;
}

※ Android 플랫폼에서 비디오 파일을 로드할 목적으로 비디오 파일을 어드레서블 파일에 번들로 묶을 경우 CacheInitializationSettings 객체를 생성하고 해당 객체에 Compress Bundles 를 비활성화한 후 ddressableAssetSettings 객체의 초기화 객체 목록에 추가한다. (아직 없는 경우)

 

 

참고자료: https://docs.unity3d.com/Packages/com.unity.addressables@1.9/manual/AddressableAssetsDevelopmentCycle.html

 

Addressable Assets development cycle | Addressables | 1.9.2

Addressable Assets development cycle One of the key benefits of Addressable Assets is decoupling how you arrange, build, and load your content. Traditionally, these facets of development are heavily tied together. Traditional asset management If you arrang

docs.unity3d.com