일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Unity
- 필활
- C++ 자료구조
- 이스케이퍼스
- 넥스트에디션
- 공포 방탈출
- 방탈출 추천
- C 자료구조
- 홍대 덤앤더머
- 홍대 방탈출
- 이스케이퍼스 2호점
- 방탈출 후기
- 추천
- 시스템 프로그래밍
- 정렬 알고리즘
- 꽃길
- Android
- 넥스트에디션 2호점
- 강남 방탈출
- 방탈출 리뷰
- C#
- 홍대
- 2021 방탈출 추천
- 윈도우 프로그래밍
- 개발
- PC VR
- 홍대 방탈출 추천
- 방탈출
- 유니티
- 후기
- Today
- Total
행복한 연어의 이야기
(Unity) 유니티 에셋번들 본문
에셋이란 ?
코드에서 변경하는 자원들 (보통 리소스 폴더에 있는 것들 - 프리팹, 사운드, 텍스쳐 등등 )
에셋번들이란 ?
위에서 설명한 에셋들을 가공(?)해서 묶어놓은 것들
에셋번들을 사용한다란 ?
리소스 폴더가 아닌 따로 지정한 경로(서버도 될 수 있음)에 있는 에셋들을 가져와서 사용하는 방법 (보통 모바일게임에서 게임 다운로드 후 접속하면 추가 다운로드를 하는 경우가 있는데 서버에서 에셋들을 추가 다운로드를 하는 것)
에셋번들을 사용하는 이유 ?
여러가지 이유가 있는데 기본적으로는 앱의 용량을 줄이기 위해서고 추가적으로는 업데이트가 용이 하기 떄문(서버에 에셋번들을 올려 받게 해두면 업데이트시 어플을 재설치할 필요없이 서버에 있는 에셋만 바꾸면 된다.)
1. 에셋번들의 2가지 구성요소
- 해더
- 에셋번들의 식별자. 에셋번들이 압축된 상태인지 아닌지, 매니페스터 같은 에셋번들 정보 (매니페스트는 오브젝트의 이름이 키로 저장되어있는 검색 테이블)
- 세그먼트
- 테이블의 각 엔트리(entry)는 에셋번들의 데이터 세그먼트에서 해당 오브젝트의 위치를 찾을 수 있는 인덱스를 제공한다.
(대부분 균형 검색 트리 사용(balanced search tree), Windows 와 OSX계열 (IOS포함)플랫폼은 레드 블랙트리 사용)
- 테이블의 각 엔트리(entry)는 에셋번들의 데이터 세그먼트에서 해당 오브젝트의 위치를 찾을 수 있는 인덱스를 제공한다.
*) 압축포맷
LZMA - 모든 에셋이 직렬화 한 다음, 전체 바이트 배열 압축, 전체 에셋번들 압축해제 필요
LZ4 - 에셋번들 내의 에셋을 개별적으로 압축, 개별오브젝트의 압축 해제 가능, 유니티 권장 압축방식
2. 에셋번들 압축하기
- BuildAssetBundleOptions.None
- LZMA 압축포맷 사용
- 파일 크기는 가장 작다. 전체를 압축 해제 하기때문에 압축 해제에 시간이 조금 더 걸린다.
- BuildAssetBundleOptions.UncompressedAssetBundle
- 데이터가 전혀 압축되지 않음
- 파일 크기가 가장 크다. 비교적 압축해제 속도가 빠르다.
- BuildAssetBundleOptions.ChunkBasedCompression
- LZ4 압축 포맷 사용
- 파일 크기 보통, 압축 해제속도 보통이다. 부분적으로 압축을 해제 한다.
3. 에셋번들 로딩 하기
- AssetBundle.LoadFromMemoryAsync
- 사용 권장 X
- 이렇게 불러온 에셋은 메모리에 총 3번 복사돠가 때문에 사용하지 말자 - 아주 오래된 방식
- AssetBundle.LoadFromFile - 로컬영역에 있는 에셋을 불러올때
- 사용 권장 O
- 하드디스크나 로컬 저장소에서 비압축 에셋번들을 로딩하기 위해 설계됨
- LZMA 압축방식의 압축해제를 지원하기 않음
- LZMA 압축방식 일시 번들을 메모리에 로드하기 전에 압축이 해제됨
- 5.3 이하 버전에서는 사용 불가 5.4 이상 버전만 사용가능
- WWW.LoadFromCacheOrDownload - 서버에 있는 에셋을 불러올때
- 5.2이하 버전에서 사용 O
- 원격 서버 및 로컬 저장소에서 오브젝트를 로드 할때 유용
- 에셋번들의 크기가 크면 메모리 오버해드가 일어남 (최대 몇 메가 바이트)
- 호출할 때 쓰레드가 생성되기 때문에 동시에 호출 조심
- UnityWebRequest (AssetBundleDownloadHandler) - 서버에 있는 에셋을 불러올때
- 5.3이상 버전에서 사용 O
- 원격 서버 및 로컬 저장소에서 오브젝트를 로드 할때 유용
- WWW.LoadFromCacheOrDownload 와 비슷한 방식으로 캐싱 지원
- 호출할 때 쓰레드가 무한히 생기는 것을 막기 위해서 최대 크기가 고정된 쓰레드 풀을 가지고있음
*) 권장 사항
1-1. 일반적으로 AssetBundle.LoadFromFile 사용 (하드디스크 로컬디스크)
1-2. 에셋번들을 다운로드 하거나 패치해야 하는 경우(원격서버, 로컬서버)에는
버전 5.3 이상 AssetBundleDownloadHandler 사용 / 5.2 이하 WWW.LoadFromCacheOrDownload 사용
2. (1-2) 방법을 사용했을때 적절하게 Dispose 메소드를 호출했는지 확인
3. 에셋번들의 크기가 5MB를 넘지 않도록하는게 좋다.
4. 동시의 2개 이상의 에셋번들을 다운로드 하지 않는게 좋다. (async await 를 사용하기도 한다.)
4. 에셋번들에서 에셋 로딩하기
-
방법
-
LoadAsset
-> 아래에 해당하지 않는 경우 사용 -
LoadAllAsset
-> 에셋번들내 대부분의 오브젝트들을 로드 할때만 사용 -
LoadAssetWithSubAssets
-> 애니메이션이나 스프라이트 아틀라스(다수의 스프라이트)를 사용하는 FBX 같은
여러 내장 오브젝트를 포함하는 복합에셋인 경우 사용- 로드해야하는 에셋의 수가 많고 한번에 로드해야하는 숫자가 에셋번들이 가진 전체 콘텐츠의 2/3 미만인 경우 에셋번들을 여러개의 작은 번들로 분리하고 LoadAllAssets을 사용하는 것을 고려해 보는 것도 좋다.
- Async를 붙이는 비동기와 안 붙이는 동기와의 메모리 효율성 차이점이 5.2 버전 이후 부터는 사라졌다. 상황에 맞춰 동기 비동기 사용하면 된다.
-
-
에셋번들 의존성
- 부모에셋번들이 로드 될때 자식에셋번들을 자동으로 로드해주지않는다.
- 1번 에셋보다 2번 에셋을 먼저 로드 하라는 말이 아니라 (자동으로 해주지도 않는다.)
1번 에셋 A 오브젝트를 로드하기전에 명시적으로 B 머테리얼이 있는 2번 에셋을 로드해야된다.
-
에셋번들 매니패스트
- 에셋번들을 빌드 할때 유니티는 각 에셋번들의 의존성 정보를 포함하는 오브젝트를 직렬화한다.
- AssetBundleManigaest.GetAllDependencies
-> 모든 의존성 정보 반환, 자식정보와 자식의 자식 등 정보 도 포함 - AssetBundleManifest.GetDirectDependencise
-> 바로 하위의 자식정보만 반환
-
권장사항
- 사용자가 프로그램의 성능이 중요한 부분에 진입하기 전에 가능한한 많은 오브젝트를 로드 하는것이 좋다. (캐싱해 두는 것도 좋은 방법)
5. 설치 후 다운로드 (로드된 에셋 번들 관리)
- AssetBundle이 LZMA 압축파일인 경우 향후 로딩속도를 높이기 위해서 LZ4로 압축 혹은 비압축상태로 캐시에 저장 된다.
- 캐시가 가득차면 가장 오랫동안 사용되지 않은 AssetBundle을 캐시에서 제거한다.
- 에셋번들을 로드하고 언로드 할 시기를 아는 것이 중요하다. (잘못 언로드 하면 오브젝트가 중복으로 저장되거나 텍스쳐가 누락되는 안좋은 상황이 발생한다.)
- AssetBundle.Unload(bool value) 안에 true를 넣어 주는게 기본적으로 가비지가 생길 확률이 적다.(각 에셋종속성에 대해 잘 파악하고 있어야 한다.)
6. 중복
- 에셋 중복
- 서로 다른 에셋 번들에 할당되어 있는 두 개의 오브젝트 모두 공통 종속성 오브젝트에 대한 레퍼런스가 포함되어 있는 경우, 해당 종속성 오브젝트가 두 에셋 번들에 모두 복사된다. (이렇게 되면 총 에셋번들의 크기가 커진다.)
- 종속성을 공유하지 않도록 한다.(공유되는 종속성이 많은 프로젝트에서는 실용적이지 않다.)
- 모든 종송된 에셋이 자체적인 에셋번들에 내장되어 있어록 한다. (중복될 위험은 사라지지만 복잡성이 발생한다.)
- 에셋 번들에 할당되지 않은 종속성을 공유하지 않도록 보장하는 에디터 스크립트를 작성해서 모든 프로젝트에서 사용하는 것이 좋다.
- 스프라이트 아틀라스 중복
- 동일한 스프라이트 아틀라스 안에 사용되는 스프라이트 들은 모두 동일한 에셋 번들에 할당해야한다.
7. 패치 시스템
- 패치 시스템에서 필요한 정보
- 현재 다운로드된 에셋번들과 각각의 버전정보 리스트
- 서버에 있는 에셋번들과 각각의 버전 정보 리스트
- 순서
- 서버 측 에셋번들 리스트를 다운받고 로컬에 있는 에셋번들 리스트를 비교한다.
- 버전정보가 변경된 에셋번들은 로컬에서 지운다.
- 로컬영역에 없는 에셋번들을 다운 받는다.
- 방법
- 에셋번들 파일리스트에 JSON 같은 표준데이터 포맷을 사용하고 체크섬 컴퓨팅에는 MD5같은 C#을 사용한다.
8. 캐싱
- UnityWebRequest API를 통해 다운로드 된 AssetBundle을 캐시하는데 사용 가능한 캐싱 시스템이 있다. (AssetBundle 내부 X, AssetBundle 시스템으로 생성 X)
- 마지막 번호를 계속 추척하며 번호가 일치하지 않거나 캐시된 AssetBundle 이 없으면 새로 다운로드 한다.
- 캐싱 시스템은 AssetBundle의 파일 이름으로만 식별되며 URL로 구분되지 않는다. (여러장소에 저장할 수 있다, 이름이 같으면 같은 AssetBundle로 인식한다.)
- AssetBundleManifest.GetAssetBundleHash() 사용은 추천하지 않는다. - 추정값을 제공할 뿐 실제 hash 연산을 하지 않는다.
9. 사용 방법
- UnityWebRequest.GetAssetBundle(String BundleURL, int version) 함수를 이용하면 이름 그대로 캐시로부터 로드 or 다운로드
- 로드 = 프로젝트 내부에 url의 에셋번들과 이름이 같고 버젼이 같은 에셋번들이 존재
- 다운로드 = 존재 하지 않으면 URL로 이동하여 에셋번들을 다운로드하여 캐싱
- 한번 더 UnityWebRequest.GetAssetBundle(String BundleURL, int version) 호출하여 캐싱된 에셋을 로드
- LoadAssetSync(비동기)로 로드하면 여러 에셋을 동시에 로드할 수 있습니다.
ex) 예제
UnityWebRequest request = UnityWebRequest.GetAssetBundle(URL,0)
AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);
bundle.LoadAsset("Cube");
* 웹서버에 저장해둔 에셋번들의 링크를 BundleURL에 넣기
- LoadAssetSync(비동기)로 로드하면 여러 에셋을 동시에 로드할 수 있습니다.
10. 쉽게 빌드 하는 방법인 Assetbundle Browser
- window -> Assetbundle Browser 를 킨다.
- Configure 탭을 눌러 사용할 에셋들을 드래그로 올린다.
- Build 탭을 눌러 Build Target을 플래폼에 맞추고 (현재 나의 사용 플래폼은 Standalone Windows 64)
아래 Ouput Path 에 경로를 지정해준다. (현재 나의 경로는 Assets/_AssetBundle) Assets 폴더에 _AssetBundle 폴더가 없을 경우 알아서 생성된다. - 아래 Build 버튼을 눌러준다. (경로에 파일을 생성한다.)
- 사용방법은 Configure로 돌아와서 오른쪽에 보면 [Asset] , [Bundle], [Size] 가 보이는데 이 string 정보를 토대로 스크립트에서 아래와 같이 적용하면 된다.
AssetBundle bundle = AssetBundle.LoadFromFileAsync(에셋번들 경로 + [Bundle])
//ex)에셋번들 경로 (Path.Combine(Application.dataPath, "_AssetBundle", [Bundle]))
var asset = bundle.LoadAsset< 불러올 타입 ex) GameObject, Sprite 등 >([[Asset]]); - 주의 사항으로는
- AssetBundle.LoadFrodmFileAsync 이게 비동기로 이뤄지기 때문에 async await 를 사용하는걸 추천한다. (Async await Task 공부해보자)
- 스크립트를 제외한 씬, 프리팹, 텍스쳐 등을 수정했다면 (스크립트도 public 연결등 무언가 바뀌었다면) AssetBundle Browser에 들어가서 다시 Build 버튼을 눌러줘야 바뀐정보다 저장이 된다.
참고 링크
유니티 메뉴얼 링크
https://docs.unity3d.com/kr/2018.2/Manual/AssetBundles-Browser.html
'IT > Unity' 카테고리의 다른 글
(Unity) 유용한 Mathf 함수들 (0) | 2020.02.25 |
---|---|
(Unity) 유니티 웹캠 화면을 가져오는 방법 (0) | 2020.02.24 |
(Unity) 유니티 쉐이더 분석 (0) | 2020.02.04 |
(Unity) 유니티 UI 관련 최적화 방법들 (2) | 2020.01.31 |
(Unity) 유니티 최적화 방법들 (0) | 2020.01.30 |