2022. 6. 12. 19:47ㆍTech/Unity
- 목차
서론
이 글은 유니티의 Addressable asset system의 간단한 적용법과 응용했던 내용에 관련된 글입니다. 제가, The pinkfong company 재직 때 직접 작성한 사내 블로그 글을 개인 블로그로 옮긴 것입니다. 아래 이전 글들을 함께 읽으면 좋습니다.
[Unity]Addressable asset 기본 개념
서론 이 글은 유니티의 Addressable asset system의 기본 개념에 관련된 글입니다. 이전 글인 [Unity] Asset bundle 기본 개념과 이어지는 내용이며, Asset bundle의 제약사항을 Addressable asset system에서는..
codinggom-daily.tistory.com
또 한, Unity와 Addressable system에 관한 어느 정도 지식이 있다는 가정 하에 작성해 일부 설명을 간략하게 하거나 생략이 있을 수 있습니다. 또한 아래의 환경이 미리 구축되어 있는 것을 전제로 합니다.
- AWS의 S3 클라우드와 CDN을 이용한 DLC 콘텐츠 관리 및 배포
- 테스트 / 프로덕션 배포 분리
- Addressable Asset unity package 설치 및 활성화
[설치 방법 공식 문서 링크]
Getting started | Addressables | 1.19.19
Getting started Once you have installed the Addressables package in your Unity Project, you can get started. The basic steps to using Addressables include: Make your assets Addressable Reference and load those assets in code using the Addressables API Buil
docs.unity3d.com
개요
Addressable Asset은 유니티에서 사용되는 게임 오브젝트, 이미지, 사운드 클립 등의 Asset들을 번들이라는 일종의 묶음으로 포장(Packaging) 하여 프로젝트(게임, 앱 등) 에서 사용할 수 있도록 해주는 시스템입니다.
이 번들을 사용하는 목적은 앱을 출시 할 때 Built-in 리소스의 용량 절약 등의 이유도 있지만, 대부분 원격 저장소에 번들을 업로드하여 사용자들이 런타임에 다운로드해 사용할 수 있도록 하기 위한 경우가 많습니다. 혹은 별도의 작업 없이 콘텐츠를 추가해주는 경우에도 많이 사용합니다. Steam 같은 게임 플랫폼에서 본 게임 외에, 다운로드 받아 사용하는 의상, 아이템, 퀘스트 등이 있는데 이 또한 같은 방식입니다. 이러한 방식을 DLC (DownLoadable Contents) 라 부릅니다.
이 글은 로컬 탑재가 아닌 Addressable Asset을 The Pinkfong Company의 앱에 적용한 넓은 의미에서 DLC 과정을 다루고 있습니다.
Remote용 번들 Export 하기
로컬 탑재(Built-in)가 아닌 원격에서 다운받아 이용할 번들을 Remote 번들(원격 번들) 이라 표현 합니다. 저장소에 업로드 할 번들을 생성하는 과정을 살펴보겠습니다.
1.Remote용 프로필 준비
Addressable asset bundle을 export하기 위해서는, 프로필의 [자기소개서] 가 필요 합니다. Addressable 메뉴의 Profiles에서 확인/생성/관리 가능하며 다음과 같은 정보를 포함하고 있습니다.
- BuildTarget : 해당 프로필을 사용하는 번들이 사용되는 플랫폼 타겟을 지정합니다. PC/Android/iOS 등 에디터 상 Build setting에 지정된 타겟을 따라갑니다.
- LocalBuildPath / RemoteBuildPath
: 해당 프로필을 사용하는 번들이 Export되어 저장될 경로입니다.
Local의 경우에는 Built-in되는 경로, Remote의 경우에는 임의의 경우로 지정되는게 기본입니다. - LocalLoadPath / RemoteLoadPath
: 해당 프로필을 사용하는 번들이 Load 할 수 있도록 저장된 경로입니다. Local의 경우, 내부 저장소 경로(Built-in)입니다. Remote의 경우에는 번들을 업로드한 서버 저장소가 되는 게 기본입니다. - CatalogVersion : 해당 프로필을 사용하는 번들의 정보가 기재된 Catalog의 버전을 지정합니다. 임의로 생성하여 사용한 변수입니다.
[CatalogVersion]은 기본적으로는 세팅되어있지 않습니다. 임의로 생성한 변수이며, 자세한 내용은 관련 토픽에서 다루겠습니다.
2. 번들로 포장할 Asset 프로필 지정
위처럼 Addressable asset bundle에 사용될 에셋 세팅에 프로필을 연결해주면, 프로필에 등록된 정보를 기반으로 번들이 export 됩니다.
3. Remote용 프로필로 번들 Export
번들을 뽑기 전에, Play Mode Script를 3번째 옵션인 Use Existing Build로 Export해줍니다.
- Use Asset Database (fastest): 최초 한 번 번들을 빌드해 줬다면, 번들에 포함될 에셋들의 정보가 갱신되었더라도 별도 빌드 없이 바로 이용 가능한 설정입니다. 오로지, 에디터에서 테스트할 때만 이용 가능합니다.
- Simulate Groups (advanced): 가상의 번들을 빌드해 해당 번들을 확인하는데 사용합니다.
- Use Existing Build (requires built groups): 실제로 번들을 빌드하고, 번들에 기재된 프로필의 경로에서 Load하여 사용하는 설정 입니다. 즉, 해당 설정으로 세팅해주셔야 에디터에서도 원격에 저장된 번들을 확인할 수 있습니다.
빌드 준비가 되었다면, Clean Build를 원할 경우 Build 메뉴의 Clean Build를 실행해주시면 됩니다. 해당 기능을 수행할 경우, 번들 빌드가 진행되어야 Addressable asset bundle을 이용할 수 있습니다. 번들과 관련된 모든 캐시를 지워주는 기능입니다.
대부분의 경우, Default Build Script를 이용하여 번들을 Export 해줘도 이용에 큰 지장은 없습니다. 위 과정까지 마쳤다면 프로필에 등록된 BuildPath에 Export한 번들을 확인할 수 있고, Play Mode 옵션에 따라 확인 가능해 집니다.
Remote용 번들 업로드 및 배포
해당 내용은 특별한 사항이 없기에 자세하게 다루지 않겠습니다.
1. Export한 번들과 Catalog 모두 S3에 업로드 및 배포

반드시 Make public using ACL 로 올려주셔야, Access 제한 오류가 발생하지 않습니다.
2. 프로젝트에서 Addressable api 초기화 및 번들 다운로드
코드는 다양한 예제 샘플이 있고 상황별로 다르기 때문에 기본적인 것만 다루겠습니다.
3. 다운로드한 Addressable Asset 번들 사용
Remote 번들을 사용하면서 겪었던 상황들
위의 내용은 여러 사례들과 블로그들에 나와있는 내용들과 큰 차이가 없을 수 있습니다. 지금부터는 해당 기능을 적용하면서 발생했던 사례들과 적용한 내용을 적어보려 합니다. 해당 시스템을 구성하고 적용하는 과정에서 비슷한 이슈를 겪는 분이 있다면 관련된 자료가 많지 않으니 참고가 된다면 좋겠습니다. 아무래도 관련 기술이 나온 것이 상대적으로 최근이고, 라이브용 서비스로 적용하는 곳에서 공개된 내용들이 많이 없기 때문인 것 같습니다.
A. Unity syntax를 이용한 임의 변수 활용
- Unity syntax
{UnityEngine.AddressableAssets.Addressables.RuntimePath}/[BuildTarget]
과 같은 값을 볼 수 있습니다. {…} […]의 내용을 Parsing 해서 임의로 값을 교체할 수 있는 기능입니다. 이는 의외로 많은 곳에서 이용중입니다. - {…} : 중괄호 안의 내용은 “런타임” 에 결정되고 활용됩니다.
- […] : 대괄호 안의 내용은 “빌드” 시에 결정되고 활용됩니다.
위와 같은 차이를 보면 {…} 와 […] 의 사용 이유를 이해할 수 있습니다. 예시를 들어보겠습니다. {UnityEngine.AddressableAssets.Addressables.RuntimePath}/[BuildTarget] 에서 {…}의 내용은 각 기기의 데이터가 저장되는 Path이며 기기별로 다양하게 나타납니다. 즉, 해당 기기에 설치되어 실행되기 전에는 알 수 없습니다. 그렇기에 기기에서 앱이 실행되고 기기 정보를 받아온 뒤(런타임에) 이용되어야 합니다.
[BuildTarget]의 경우 Editor의 빌드 플랫폼 설정을 가져옵니다. 즉, 앱이 배포된 이후에는 알 수 없습니다. Editor에서 종속된 설정이기 때문에 빌드시에 확인되고 이용되어야 합니다.
이러한 특징을 이용하여 아래와 같은 상황을 해결하는데 응용했습니다.
- 테스트 / 프로덕션 스테이지를 나누기 위해, 각 스테이지별 RemotePath를 런타임에 바꿀 필요가 있었습니다.
- CatalogVersion과 번들 매칭의 자동화가 필요했습니다.
- Editor 작업에서 수동으로 설정해줘야 하는 부분을 줄이고 싶었습니다.
상황의 이유를 살펴보겠습니다. 새로운 번들에 이상이 있을 경우 라이브 사용자들에게도 영향이 갈 수 있기 때문에, 저장소 자체를 분리할 필요가 있었습니다. 그렇다면 앱은 어떤 저장소를 참조해야 하는지 어떻게 알까요? 런타임에 테스트/프로덕션에 따라 다른 저장소 위치를 참조하면 되는 것 입니다.
특정 방법으로 테스트/프로덕션 상황을 알 수 있다면, 저장소 위치 스위칭은 어떻게 해주지? 라는 고민을 하게 되었습니다. 프로젝트를 별도로 관리해 Addressable asset profile을 따로 나눠주나? 이는 너무 비효율적입니다. 프로젝트간 profile 간 Sync를 맞춰 주는게 휴먼 미스 등의 위험 요소도 많았고, 자동화 작업을 추가하는 것도 효율이 좋지 않았기 때문입니다. 또한 기존에 테스트/프로덕션 인식 기술은 하나의 앱의 런타임 환경에서 확인할 수 있는 구조이기 때문에 함께 맞춰줄 필요도 있었습니다.
이에 하나의 프로젝트와 하나의 프로필로 런타임에 관리를 해보기 위한 방법을 채택할 필요가 있었습니다. 이와 같은 필요 조건에 딱 부합하는 게 Syntax 를 이용하는 방법이었습니다.
{SmartStudy.Addressable.AddressableWrapper.remotePath}/[CatalogVersion]/[BuildTarget]
{…} 안에 들어갈 내용은 특정 class의 static string 값입니다. 즉, 내용을 살펴 본다면 “SmartStudy.Addressable namespace의 AddressableWrapper 라는 class의 remotePath 라는 static string 변수를 런타임에 사용한다”라는 뜻입니다. 앱의 런타임에 isTest 값에 따라 서로 다른 값을 return해주는 remotePath 변수에 각 환경에 맞는 저장소 path를 넣어줌으로써 스테이지 스위칭을 구현했습니다.
Remote 프로필의 [CatalogVersion]은 임의로 생성해서 이용하는 변수라고 위에서 언급한 바 있습니다. […] 안의 내용이니 빌드 타임에 결정되는 값이겠네요. Catalog의 버전에 따라 저장소를 구분하려면, 버전을 수정한 뒤 저장소도 수정할 필요가 있었습니다. 저장소 내부에서도 버전으로 path를 구분하고 있었기에 Catalog의 버전이 바뀌면 참조하는 저장소의 path도 바꿔줘야 했습니다.
ex) v1 catalog : {…}/v1
v2 catalog : {…}/v2
그럼 버전을 바꿀 때마다 runtimePath 를 수동으로 바꿔주어야 하나? 라는 의문이 생기게 되었습니다. 오타가 나거나 수정하는 걸 깜빡하면? 다시 해야하잖아… 그렇기에 여기서도 Syntax를 이용하기로 했습니다.
- Editor에서 catalog version 수정
- 수정된 catalog version을 AddressableWrapper에서 참조
- [CatalogVersion]에 AddressableWrapper.catalogVersion 값 참조
- [RuntimeLoadPath]에서 [CatalogVersion] 값 사용
이런 과정을 거친다면, 필수 수정 과정인 Editor에서 catalog version 수정만 해주면, 그 뒤에는 같은 버전을 사용하는 게 보장이 됩니다.
B. 여러 컴퓨터에서 번들을 빌드했을 때 의존성 문제 발생
하나의 컴퓨터에서 프로젝트를 제작하고, 번들을 Export하고, 앱 빌드해서 업로드 한다면 생기지 않았던 문제였습니다. 하지만, 동일한 프로젝트를 여러 컴퓨터(여러 작업자)와 같이 관리했을 때 발생했던 유감스러운 문제를 다뤄 보려합니다.
Remote용 번들 말고, Local에 빌드되는 기본 Bundle이 있습니다.
[Defalut Local Group]은 다른 임의 생성해서 사용하는 Group들과는 다르게, 기본으로 생성되어 있고 쉐이더 같은 기본 에셋들을 포함하는 그룹입니다. 이 그룹은 앱에 Built-in되어 나갑니다. 그렇기에 다음과 같은 구조에서 별도의 다운로드 없이 이용 가능합니다.
단일 작업자 혹은 번들 Export & 앱 빌드 컴퓨터가 지정되어 있다면 문제가 없겠지만, 여러 작업자가 있을 경우 다음과 같은 현상으로 인해 문제가 발생합니다.
- [Defalut Local Group]의 내용 구성은 바뀌지 않지만, 작업자별로 “체크썸” 이 다릅니다. Export 환경과 작업자별 프로젝트 세팅에 의해 일부 Meta data의 차이가 생겨 발생하는 현상 같습니다.
- Catalog에는 Export를 실행한 사람의 [Defalut Local Group]이 기재됩니다. 이때 그 사람에게서 생성된 Group 의 “체크썸”이 기재됩니다.
- 업로드 된 번들들은 Export한 사람의 “체크썸”을 가지는 [Defalut Local Group]의 번들을 의존하고 있습니다.
- 하지만 Built-in 번들이기 때문에 원격 환경(저장소)에서는 의존성을 확인 할 수 없습니다.
> 번들이 의존하는 타 번들을 함께 원격에서 “다운로드” 하는 게 Addressable asset의 구조입니다. - 의존성 확인을 할 수 없기 때문에 번들 사용시 문제가 발생합니다.
해당 현상을 해결하기 위해서는 Built-in 그룹에 Remote 프로필을 설정하여 함께 원격에 올려주거나, “체크썸” 을 그룹 이름에 붙이지 않는 설정이 필요 했습니다. “체크썸” 을 붙이지 않는 경우, 다른 버전을 업로드 하였을 때 문제가 발생하였기 때문에, 작업자가 [Defalut Local Group]을 함께 저장소에 업로드해 다른 작업자들도 해당 저장소에서 함께 사용하는 방법으로 진행하였습니다.
마무리
- Syntax를 사용한 방법은 기존에 알고 있던 Syntax 방식의 지식과 Addressable profile에 사용된 방식을 보고 영감을 얻었습니다.
- Syntax와 관련된 자료는 많이 존재하지 않았습니다. 기본 튜토리얼이나 문서에서 상세한 설명도 없고, 소개 영상 등에도 등장하는 게 거의 없어 직접 시도해 보는게 많았습니다.
- [Default Local Group]은 개선이 필요해 보입니다. 원래 이렇게 사용하도록 설계된 게 아닐 테니 말이죠.
리소스 출처
[그림 1~2] : 직접 제작한 이미지 입니다.
외 모든 이미지는 작업한 내용들의 일부 스크린샷 입니다.
'Tech > Unity' 카테고리의 다른 글
[Unity]Unity의 il2cpp (0) | 2022.08.09 |
---|---|
[Unity]Unity의 Mono (0) | 2022.08.09 |
[Unity]Addressable asset 기본 개념 (2) | 2022.06.12 |
[Unity]Asset bundle 기본 개념 (2) | 2022.06.12 |
[Unity]UIWebView Deprecated 이슈 해결 법 (0) | 2022.04.13 |