[ * 필자 Unity 버전 == 2020.3.6f1 ]
Addressable Asset System (2018.2 이상의 버전부터 지원)
- Assets을 좀 더 효율적으로 관리하기 위해 새롭게 나온 시스템
[새로운 시스템이나 Asset Bundle을 기반으로 작동]
- Address를 이용하여 에셋의 관리, 로딩, 빌드가 통합된 시스템이다.
- 모든 동작이 비동기로 구현된다.
여러 장점들
- 에셋 빌드와 배포의 단순화
[직접 레퍼런스, Resources 폴더, 에셋 번들 등을 사용한 에셋 접근 방법이 통합되기 때문에 편리해짐]
- 효율적 에셋 관리
[종속성이 어떻게 되어있는지, 메모리 로드, 언로드 현황이 어떤지를 볼 수 있음]
- 런타임 중 에셋 관리가 편함
- 에셋들의 의존 관계를 알아서 확인하여 리소스 로드할 때 의존된 리소스를 같이 로드한다.
[번들이 분리되어 있어도 의존된 번들을 같이 로드해 줌]
- 개발의 편의성(개발 시간 단축)
[개발 상황에 따른 코드 변경이 없음 (주소로 지정되기 때문에 코드 변경사항이 많이 줄어든다.)]
[Editor 상에서 여러 Addressable Build mode를 제공하여 개발의 편의성을 준다.]
[번들을 실제 사용하여 테스트할 수도 있고 빌드를 바로 안 해도 가상으로 번들이 빌드 되어있다고 가정하고 테스트할 수도 있다.]
- Editor에서 Local Hosting을 사용 가능하다. -> Remote 환경을 테스트할 수 있다.
-요약-
Resources 폴더의 장점(사용의 편의성) +
에셋 번들의 장점(에셋을 빌드와 따로 구분하여 빌드 초기 용량 낮춤 등등) +
개발 편의성
Addressable을 사용하기 위해 PackageManager에서 Addressable을 install 한다.
Addressable 등록은 매우 간편하다.
unity Editor
- Window - Asset Management - Addressables - Groups에서 Addressable로 등록한 Asset들을 확인할 수 있다.
등록한 에셋들은 처음에는 Default Local Group에 등록이 된다.
[여기서 각 그룹들을 하나의 에셋 번들로 봐도 무방하다.]
왼쪽 상단의 Create을 통해(Create -> Group -> Packed Assets) 새로운 그룹을 만들 수 있으며 Group을 통해 에셋을 자유롭게 분류할 수 있다.
그룹들을 보면
Built in Data
- 우리가 이미 알고 있는 system인데
Resources 폴더, 실제 build 시 들어가는 씬의 정보를 볼 수 있다.
중요한 부분은 그 뒤부터 있는
Default Local Group과 새로 만든 RomoteHairs라는 그룹이다.
Default Local Group
- 처음 생성 시 바로 만들어지는 것이고 실제 빌드 시 내가 직접 가지고 있는 (Streaming asset과 같은) 에셋
- 에셋에 addressable을 지정하면 먼저 Default Local Group에 들어가진다.
RemoteHairs
- 서버에서 불러드릴 에셋들이다.
RemoteHairs 그룹의 경우는 제가 직접 만든 그룹이고 서버에서 받아올 에셋들만 분류해뒀다.
=> 그룹은 본인이 자유롭게 지정하되 일단 Local과 Remote로 나누는 게 좋지 않을까 싶다.
그 뒤 사용하고자 하는 Asset의 인스펙터창을 보면
요로코롬 Addressable 체크박스가 새로 생긴 걸 확인할 수 있고 그냥 체크하면 등록이 된다.
[혹은 사용하고자 하는 Asset을 아래 보이는 Group 창에 드래그 앤 드뢉~ 을 해도 된다.]
이 address를 이용하여 asset의 위치에 상관없이 참조할 수 있다.
-> Addressable 옆에 있는 Input 란에는 그 Asset에 대한 이름을 기입하면 된다
(Default로는 Path가 지정되는데 사실 원하는 방식으로 바꿔도 된다. But 원하는 방식으로 지정할 경우 이 부분이 지정한 Asset을 찾는 주소가 되기 때문에 중첩이 되지 않도록 해야 함)
Play Mode Script의 경우는
이렇게 3 가지로 분류되는데
Use Asset Database - 실제 그룹화된 애들이 에셋 번들로 묶여있어도 따로 에셋 번들을 만들지 않고 에셋들을 직접 읽어서 빠르게 실행할 수 있음 But 실제 타깃 플랫폼의 런타임에서는 문제가 생길 수도 있다. (당연)
Simulate Groups - 에셋 번들을 만들지 않았어도 에셋 번들을 만든 것처럼 작동한다.
Use Existing Build의 경우 실제 Addressable을 build해야 사용 가능 -> 실제 에셋 번들을 만들어서 작동한다.
Build의 경우
요로코롬 있는데
New Build -> Default Build Script가 있는데 이게 Addressable에서 기본적으로 제공해 주는 Build system이다.
[API 함수를 이용하여 Default 빌드도 가능 -> AddressableAssetSettings.BuildPlayerContent()]
사실 빌드 스크립트는 개발자가 별도로 코딩하여 빌드 시스템을 구축할 수도 있긴 하다 함..
Update a Previous Build
- 이미 빌드 된 번들들을 업데이트하고 싶을 때
Clean Build
- 이미 빌드 된 번들들을 다 지우고 새로이 빌드 할 때
Lables의 경우
Addressable Asset의 Path 바로 오른쪽을 보면 볼 수 있다.
그룹화된 에셋들을 실제 빌드 하면 에셋 번들로 빌드가 되는데 그 그룹 중에서도 Lable을 나누어주면 실제로 로드할 때 한 그룹을 다 읽을 수도 있지만 Lable을 통해 필터링해서 원하는 그룹을 고른 뒤 그중에서도 원하는 Lable에 해당하는 에셋들만 따로 불러올 수 있다.
그룹에 관한 정보는
Assets 폴더 안에 AddressableAssetsData 폴더에서 확인할 수 있다.
AssetGroups 안에 폴더에서 각 그룹에 대한 세팅을 할 수 있으며, 아래쪽에 AddressableAssetSettings에서 Addressable의 전반적인 세팅이 가능하다.
- Window - Asset Management - Addressables - Addressables EventViewer는 profiler의 기능을 한다고 생각하면 된다.
Addressalbe을 통해 생성된 오브젝트들이 메모리상에서 어떻게 돌아가고 있는지를 확인할 수 있다.
즉 에셋들의 로드, 언로드 상황을 볼 수 있다.
그으으런데 이 상황들을 보려면 반드시 AddressableAssetSettings - General에서
Send Profiler Events를 체크해 줘야 한다.
- Window - Asset Management - Addressables - Analyze를 통해 종속성 문제 등 여러 가지를 확인할 수 있고 Fix Selected Rules를 통해 어느 정도 수정도 가능하다.
코드로 Addressable을 사용할 때는 기본적으로
위 녀석들 중 상위 2개는 using 해야 한다.
가장 아래의 경우 따로 다른 테스트를 하다 사용하게 되었는데 나중에 사용하다 보면 다른 부분도 using 하겠죠?
using UnityEngine.ResourceManagement.AsyncOperations;의 경우는 비동기 방식으로 사용하기 위함이다. 이따 함수들도 몇 볼 텐데 함수에 Async가 보통 붙을 텐데 이것을 안 붙이면 동기 방식이기 때문에 유니티에서도 사용하지 말라고 권장한다.
그리고 Async 함수를 사용해야. Completed라는 콜백을 받을 수 있는데 이게 참 뒤에 글을 다 보면 편할 것이다.
[비동기 방식이기 때문에 처리 결과를 반환하는 콜백 함수를 받을 수 있는 것]
이제 기본적으로 알아야 될 함수들
Get DownloadSizeAsync를 통해 다운로드 될 사이즈를 알 수 있다.(0 초과이어야 다운 받을 게 있는 것이다.)
-> DownloadDependenciesAsync를 통해 리소스를 다운로드할 수 있음
근데 이걸 굳이 호출하지 않아도 아래 보이는 LoadAssetAsync를 사용하고, 로드할 에셋이 Remote 이면 알아서 다운로드해서 로드까지 한다. 그럼에도 위 함수가 있는 이유는 당연히 리소스 들을 미리 다운로드할 수도 있어야 하기 때문이다.[다운로드해야 하는 번들이나 Asset의 크기가 클 경우를 생각해야 하기 때문임 (Text 같이 작은 것들이야 바로 로드해도 되겠지만.)]
그리고 Handle.PercentComplete를 통해 0 ~ 1까지 다운로드한 퍼센트를 알 수 있다.
위 함수를 통해 다운로드한 에셋을 로드 할 수 있음
for 문안에 LoadAssetAsync 구현 부분을 보면 뒤에. Completed가 있는데 LoadAssetAsync 함수가 완료되고 나서 하고 싶은 일을 람다식을 이용해서 진행할 수 있다. 어우 편해..
로드도 했겠다 Instantiate로 생성만 해주면 끝나긴 한다.
그런데 요건 사실
요런 식으로 로드와 생성을 동시에 해버릴 수도 있다.
[Addressables.LoadAssetAsync<GameObject>("Address").Completed += obj => GameObject = obj.Result; //로 로드한 뒤 Instantiate(GameObject); 이렇게 생성도 가능]
address는 말 그대로 Addressable Asset의 Adress이다.
끝부분의 current_Hair는 그냥 GameObject인데 생성한 오브젝트를 GameObject로 선언해서 사용하려고 한 부분인데 다른 여러 방식으로도 사용 가능하다.
그리고 로드를 했으면 당연히 언로드도 해야 한다. (메모리에 올렸음 당연히 내려야겠죠?)
언로드의 경우는 ReleaseAsset(), ReleaseInstance()이 있는데
LoadAsset()을 했을 경우는 ReleaseAsset()
Instantiate()을 했을 경우는 ReleaseInstance()를 사용하면 된다.
위의 본인이 작성한 코드를 메모리에서 내릴 때는
Addressables.ReleaseInstance(current_Hair);
이런 식으로 작성해도 된다.
또는 여러 방식들이 있겠지만 그냥 Destroy() 함수를 통해 에셋을 지우고 그 에셋의 스크립트에 OnDestroy()를 사용해서 Addressables.ReleaseInstance(gameobject);를 사용해도 된다.
만들고자 하는 방식에 따라 여러 방식으로 구현이 가능하다. [결국 Release만 해주면 되니까]
이 함수는
실제로 미리 다운로드해둔 리소스 캐시를 비울 때 사용하는 함수인데
사용하기 위해서는 실제로 지금 사용 중인 Addressable asset들을 모두 메모리에서 내리고 사용해야 한다.
이 부분은
요로코롬 유니티에서 제공해 주는 함수를 사용해서도 할 수 있다.
그런데 이 캐시는 어디에 있는지 궁금할 텐데 window 플랫폼일 경우는
C:\Users\사용자 이름\AppData\LocalLow\Unity 안에 보면 Unity에서 빌드 시 사용한 Company 이름이 보일 텐데 그 안에 들어가서 보면 본인이 받은 캐시(번들들이 풀려서 다운된 파일, 번들이 아님)들을 확인할 수 있다.
Addressable을 사용하는 가장 큰 이유는 순수 본인 생각으로 서버에서 번들을 가져와서 사용하기 위함이라 생각한다. (이게 초기 용량 관리, 메모리 관리 등 기본적인 부분이라 생각한다.)
일단 새롭게 개념을 좀 잡고 가야 한다.
- 서버에서부터 사용할 Addressable Asset을 로드하는 것은 단지 하나의 에셋을 로드하는 것이 아니라 그 에셋이 포함된 번들 자체를 로드합니다.
- 위에 함수에 관해 알아볼 때 DownloadDependenciesAsync를 이미 봤지만 DownloadDependenciesAsync의 경우는 번들을 모두 다운로드하는 것이고 LoadAsset을 통해서는 하나의 번들만 다운로드할 수 있다.
-DownloadDependenciesAsync(레이블)을 통해서는 지정된 레이블만 다운로드할 수 있다.
(물론 그 지정된 레이블의 에셋의 번들을 다운로드하는 것)
그렇기에 이제 좀 중요한 부분인데
본인이 생선 한 Group들 중 Remote 형식으로 바꿀 그룹이 존재할 텐데 Assets 폴더 안에 AddressableAssetsData - AssetGroups 안에서 본인의 생성한 그룹을 클릭 뒤 세팅을 바꿔줘야 한다.
제 경우는 RemoteHairs라는 Group을 Remote로 사용할 것이기 때문에 이 그룹의 세팅을 변경해 주었습니다.
뭐 사실 대단하게 변경할 것도 없고 Build Path, Load Path 부분이 초기에는 Local 세팅으로 되어있을 건데 걍 Remote로만 바꿔주면 된다.
그 뒤에 AddressableAssetSettings도 바꿔줘야 한다.
Remote 환경을 구축하기 위해 Build Remote Catalog를 체크하고 Path를 Remote로 바꿔주면 된다.
일단 요기 세팅 부분에서 좀 볼 게 있는데
General에서 Unique Bundle IDs는 default로 체크가 되어있긴 한데 절대 안 푸는 게 좋다.
- 번들 아이디는 빌드 할 때마다 변경되는데 이걸 체크 안 하면 빌드 할 때마다 바뀐 파일과 안 바뀐 파일을 분류해서 관리할 수 없음 뭔 말이냐면 원래 a가 있는데 빌드하고 b가 추가됐을 뿐인데 a를 또 받게 되는 것
여기서 Catalog 부분은 내가 생각해도 굉장히 중요한데
https://blog.naver.com/cdw0424/221756844361
감귤오렌지 님이 정말 이쁘게 정리해 주셨다.
Group 메뉴에서 Create 바로 오른쪽에 보면 Profile 이란 메뉴가 있다. 클릭해서 Manage Profiles을 들어가 보면
요런 창을 볼 수 있는데 이 부분에 각종 Load, Build의 경로를 설정할 수 있다.
본인은 AWS에서 S3를 사용 중인데 구글 클라우드를 사용해도 무관하다.
(둘 다 무료로 어느 정도 사용 가능하니 연습으로 참 좋다.)
아마존이나 구글이나 클라우드 만드는 건 검색하면 쉽게 나오니 생략하고
[ 아 그렇지만 중요한 건 접근성인데 버킷 만들 때 서버에 접근 가능하도록만 설정해 주면 됨]
새로운 버킷을 만들고 그 안에 본인이 제작한 Addressable을 Build 하여 나온 폴더를 통체로 올려주면 된다.
[폴터들도 접근 가능하도록 설정]
일단 Addressable을 빌드 하게 되면 프로젝트 폴더 내에 ServerData라는 폴더가 생긴다.
(Assets 폴더 안에 생기는 게 아니라 프로젝트 폴더 내에 생깁니다.)
Addressable 빌드 후 생기는 ServerData 폴더 안에는 본인의 프로젝트의 플랫폼 형식의 폴더가 새로 생기게 된다.
본인은 현재 프로젝트가 Android여서 Android 폴더가 생성되었다.
어 쨌 든
이 폴더 안에는 빌드 한 Addressable에 대한 정보들이 담겨있다. Bundle, Hash, Json 파일이 생성될 것인데
가장 중요한 부분은 서버에 이 파일들을 올리는 것이 아닌 빌드 된 폴더 자체를 올려야 한다!
그래서 저는
이렇게 Android 폴더가 올려있지요!
이제 이것들을 사용해야 하는데 이젠 local이 아닌 remote 형식으로 사용해야 하기 때문에 새 Profile을 생성하고 Profile에서 RemoteLoadPath를 새롭게 설정해 줘야 한다.
위 서버 사진에서 Android를 클릭(본인 폴더를) 하면 안에 또 파일이 있을 거고 그걸 또 클릭해서 보면 객체 url을 확인할 수 있을 것인데 그 url에서 상위 폴더 (본인 경우는 Android) 이름이 명시된 부분 앞부분까지 복사하여 RemoteLoadPath에 붙여 넣어주면 된다. 위에 Profile 이미지를 보면 모자이크 처리가 된 부분에 넣어주면 되고 뒤에 [BuildTarget]은 그대로 두면 된다. (이 부분은 Android 면 Android로 Window 면 Window 어쩌구 저쩌구로 platform에 맞게 자동으로 세팅되기 때문에)
이렇게 주소를 세팅해 주면 전에 Profile, AddressableAssetSettings에 설정돼있던 Build Path, Load Path 부분의 주소가 자동으로 바뀔 것이다.
이러면 간단한 준비는 끝났고 코딩을 하면 된다.
그런데 사실 이 부분은 - Window - Asset Management - Addressables - Hosting에서
Remote 환경을 Local로 간단하게 테스트해볼 수 있는데 본인의 현재 프로젝트가 아직 매우 작기 때문에 과감히 생략하고 바로 Remote 환경으로 진행해버렸다. ㅋ..ㅋㅋㅋ
이 뒤 코딩은 원래 하던 방식으로 하면 된다.
꼭 DownloadDependenciesAsync를 통해 리소스를 다운 받지 않고 바로 Instantiate를 해도 알아서 address에 맞는 에셋이 있는 번들을 다운 받고 생성해 주기 때문이다.
+ TIps
1. public AssetReferenceGameObject[] obj;
- 직접 레퍼런스, AssetReference로도 가능, 다만 여러 개 한 번에 레퍼런스 하고 싶을 때는 앞에 와 같은 방식(배열)으로 해도 된다.
2. 같은 Label의 에셋만 다운로드하기 가능
public AssetLabelReference labelTest;
public List<IResourceLocation> List_labelTest;
- using UnityEngine.ResourceManagement.ResourceLocations;가 필요
List<GameObject> list_obj;
Addressables.LoadResourceLocationsAsync(labelTest).Completed += handle => { list_obj; = new List<IResourceLocation>(handle.Result);
//같은 Label이 여러 개임을 가정하고
foreach (var obj in List_labelTest) {
Addressables.InstantiateAsync(obj, transform.position, Quaternion.identity).Completed += (AsyncOperationHandle<GameObject> obj) => { list_obj.Add(obj.Result); };
}
* Manual
https://docs.unity3d.com/Packages/com.unity.addressables@1.18/manual/index.html
위 내용들은
https://www.youtube.com/watch?v=yoBzTpJYN44
https://www.youtube.com/watch?v=EP3pvPAcHSo
https://www.youtube.com/watch?v=3f2XjEGDZ2s&t=4s
https://www.youtube.com/watch?v=qL7PXAFNP5M&list=PLmRK0lH8TNCo7K4xmLpEov4llbVTwf29s&index=5
및 및 여러 구글링을 통해 정리한 자료입니다.
'Unity > 개념 및 분석' 카테고리의 다른 글
Unity JSON 기본 개념 + 사용[JsonUtility + JSON .NET For Unity(newtonsoft.json) + LitJson + MiniJson] 아는 거 다 써버려 (0) | 2021.06.25 |
---|---|
Unity FlowCanvas(in paradoxnotion) Visual Scripting (0) | 2021.06.16 |
Unity Bolt(비주얼 스크립팅) 기본개념 (0) | 2021.06.15 |
Unity Serialization(직렬화) (0) | 2021.05.13 |
Unity AssetBundle 기본 개념 (1) | 2021.04.26 |