어드레서블이란?
- 유니티에서 제공하는 에셋 관리 시스템
- 콘텐츠 효율적 관리하고 로드하는 방법을 제공
특징
- 동적 콘텐츠 로딩: 게임 실행중 필요 에셋을 동적으로 로드, 언로드 가능
- 메모리 효율성: 필요 시점에만 메모리에 로드하여 메모리 사용 최적화
- 콘텐츠 주소 체계: 문자열 키를 통해 에셋에 접근할 수 있어 유연한 리소스 관리 가능
질문
Q. 어드레서블이 기존의 리소스 로딩 방식과 가장 크게 다른 점은?
A.기존 리소스시로드, 인스펙터를 이용한 방식과 다르게 동적 로딩이 가능한점
A. 필요하지 않을때 메모리 해제 가능
A. 빌드 시점이 아닌 런타임 로딩 결정 가능
Q.동적 콘텐츠 로딩이 게임 개발에서 왜 중요한 이유?
A. 업데이트나 패치로 유저들에게 바로 콘텐츠 제공이 가능
A. 초기 다운로드 크기 감소
A. 선택적 콘텐츠 다운로드 가능
Q. 어드레서블에서 말하는 '주소 체계'란 무엇을 의미하는가?
A. 경로 의존성(Resources 폴더 안이 아닌 다른 곳에서도 자유롭게 가능)
A. 그룹화와 라벨링을 통해 체계적 관리 가능
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
어드레서블의 필요성
1. 앱 실행 시간, 메모리 문제, 저장공간 등 이점
- 대형 게임에서 모든 콘텐츠를 한번에 빌드에 포함 시키면 빌드 시간을 포함해 앱 실행, 메모리, 저장공간등에 큰 영향을 끼침
- 게임의 경우 초기 로딩 시간이 증가하면 사용자 이탈률이 생길 수 있음
- 저사양 기기 실행 불가능 문제 또는 OOM(Out of Memory)발생 가능성이 있음
2. 원격 업데이트 제공
- 부분적 업데이트로 데이터 사용량 절감
- A/B테스트 용이
- 실시간 콘텐츠 수정 및 패치 가능
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
어드레서블의 기본 구조
1. 어드레서블 그룹(Addressable Group)
2. 어드레서블 에셋(Addressable Asset)
3. 에셋 번들(Asset Bundle)
4. 종속성 관리(Dependency Managerment)
질문
Q. 에셋 번들과 어드레서블의 관계
A. 어드레서블은 에셋 번들의 상위 레벨 추상화 계층
A. 어드레서블은 내부적으로 에셋 번들을 생성하고 관리하여 자동으로 처리해줌
A. 즉, 어드레서블은 에셋 번들을 더 쉽게 사용할 수 있게 해주는 래퍼(Wrapper)라고 볼 수 있음
Q. 종속성 관리의 중요성
A. 예를들어 캐릭터 프리팹이 특정 텍스처나 메테리얼을 참조할 경우 프리팹만 로드하면 텍스처나 메테리얼이 누락될 수 있기 때문에 어드레서블이 종속성을 자동으로 추적하고 관리해줌
A. 중복 로딩 방지로 여러 에셋이 동일한 리소스를 참조할때 한번만 로드 하도록 하여 메모리 효율성에 좋음
A. 다른 에셋에서 사용중인 리소스는 자동으로 보존하며 메모리 누수 방지를 하기 해주기 때문에 언로드 시 안전성이 보장됨
*에셋 번들이란?
- 에셋 압축, 빌드 시점 생성 및 로드 등등 유니티에서 제공하는 가장 기본적인 에셋 패키징 시스템
* 에셋 번들이 있지만 어드레서블을 생겨난 이유?
- 위에서 언급한 종속성 관리 문제, 복잡한 버전 관리, 중복 에셋 발생, 메모리 관리 어려움 등
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
어드레서블 구현 방식
1. 어드레서블 시스템 설정
2. 에셋 마킹
3. 그룹 구성
4. 빌드 설정
질문
Q. 어드레서블로 마킹 한다는 의미는?
A. 주소 체계 활성화 즉 고유(키) 할당
A. 그룹, 라벨 지정 가능
A. 종속성 자동 추적 시작
Q. 어드레서블 빌드와 일반 빌드 차이점?
A. 어드레서블 카탈로그를 생성하여 매핑 정보를 담아 사용
A. 여기엔 종속성 정보, 로딩 경로 정보가 포함되어 있음
A. 종속성 기반 최적화, 중복 제거, 자동 버전 관리 등
Q. 로컬과 원격의 차이
A. 로컬 어드레서블은 앱 빌드에 포함, 즉시 사용, 오프라인 접근, 저장공간을 차지함
A. 원격 어드레서블은 CDN, 서버에서 다운로드 받거나 업데이트 등에 사용됨
실제 코드
// 어드레서블 에셋 로드
public async Task<GameObject> LoadPrefab(string key)
{
var prefab = await Addressables.LoadAssetAsync<GameObject>(key).Task; return prefab;
}
// 그룹별 로드
public async Task LoadGroup(string label)
{
var loadOperation = Addressables.LoadAssetsAsync<GameObject>(label, null);
await loadOperation.Task;
}
질문
Q. 어드레서블 에셋을 로드할 때 왜 비동기(async/await)를 사용하는가?
A. 로드를 이용해 불러와야하기 때문에
A. 메인 스레드 블로킹 방지
A. 대용량 에셋 로딩 시 프레임 드랍 방지 등등
Q. 어드레서블 그룹과 라벨의 차이점?
A. 그룹은 빌드와 배포의 기본 단위이며 물리적으로 분리된 번들로 생성하며 업데이트 단위로 사용됨
A. 라벨은 논리적인 분류 단위이며 여러 그룹에 걸쳐 사용할 수 있고 에셋 검색과 로드에 사용됨
Q. 어드레서블 카탈로그가 하는 역할?
A. 에셋 주소와 실제 위치 매핑
A. 종속성 정보 저장
A. 버전 정보 관리
A. 로드 경로 정보 저장
A. 그룹과 라벨 정보 관리
// 그룹 예시: 한 번의 다운로드로 모든 캐릭터 에셋을 받음
public async Task DownloadCharacterGroup()
{
await Addressables.DownloadDependenciesAsync("CharacterGroup");
}
// 라벨 예시: 여러 그룹에 걸쳐 있는 튜토리얼 관련 에셋만 로드
public async Task LoadTutorialAssets()
{
await Addressables.LoadAssetsAsync<GameObject>("Tutorial", null);
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
어드레서블 캐싱 시스템
1. 메모리 캐싱
- 자주 사용디는 에셋 메모리 유지
- 참조 카운팅 기반 관리
- 메몰 부족 시 자동 해제
2. 디스크 캐싱
- 다운로드 된 에셋 번들 저장
- 재다운로드 방지
- 캐시 크기 제한 설정 가능
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
로컬과 Resources의 차이점
1. 메모리 관리 측면:
- Resources는 로드 후 수동으로 메모리 해제를 관리해야 함
- 어드레서블은 참조 카운팅 기반의 자동 메모리 관리 제공
- 언제든지 필요한 시점에 메모리에서 해제 가능
2. 빌드 최적화:
- Resources는 모든 에셋이 하나의 큰 번들로 빌드됨
- 어드레서블은 그룹별로 개별 번들로 빌드되어 초기 로딩 속도 향상
- 사용 시점에 따라 로딩 시점 최적화 가능
3. 종속성 관리:
- Resources는 종속성 관리를 수동으로 해야 함
- 어드레서블은 자동으로 종속성을 추적하고 관리
- 누락된 참조 방지
4. 유지보수 용이성:
- Resources는 폴더 구조에 종속적
- 어드레서블은 라벨과 그룹으로 유연한 관리 가능
- 프로젝트 구조 변경에 더 유연하게 대응 가능
예시:
[게임 시작 시]
- Resources: UI번들(1GB) 전체를 읽어야 함
- 어드레서블: 로그인 UI번들(10MB)만 읽음
[게임 진행 중]
- Resources: 이미 모든 UI가 메모리에 로드됨
- 어드레서블: 상점 진입 시 상점 UI번들(100MB)만 추가로 로드
결론 - 로컬 어드레서블을 사용하더라도
- 초기 로딩 속도 향상
- 메모리 사용량 최적화
- 필요한 에셋만 선택적 로드
중요사항
- 로컬로 사용하면 저장 공간을 차지하는 것은 맞지만 메모리 공간은 로드할때만 사용한다는 점!
예시:
게임 전체 용량: 1GB (저장 공간)
- UI 번들: 200MB
- 캐릭터 번들: 300MB
- 맵 번들: 500MB
실제 메모리 사용:
- 게임 시작 시: UI 번들만 200MB 메모리 사용
- 캐릭터 선택 시: +300MB 추가
- 불필요한 UI 해제 시: -200MB
'유니티 > 최적화' 카테고리의 다른 글
[최적화] Assembly Defintion (0) | 2025.01.13 |
---|---|
[최적화] 스크립터블 오브젝트 (0) | 2025.01.12 |
[최적화] 오브젝트 풀링 (0) | 2025.01.10 |