샘플 프로젝트
https://github.com/Unity-Technologies/Addressables-Sample
등장 배경
어드레서블은 에셋번들을 토대로 설계된 시스템이다.
완전히 새롭게 만들어진 것이 아니라 에셋번들의 편의성을 개선하기 위해 등장한 시스템이다.
등장 배경에는 에셋번들의 장점에도 불구하고 리팩토링과 커스텀 프로그래밍을 요구하는 단점이 있었다.
에셋번들의 장점
에셋번들은 말 그대로 에셋(콘텐츠)을 특정 규모로 번들링 또는 그룹화하는 것이며 앱 설치로부터 에셋을 분리시킨다. 이에따라...
ㆍ초기 빌드 볼륨을 최소화할 수 있다.
ㆍ에셋별 동적 로드를 통해 메모리 관리가 가능하다.
ㆍ에셋을 Remote 서버(CDN; Contents Delivery Network)로부터 제공할 수 있다.
ㆍ빌트인 에셋으로부터 필요한 에셋을 업데이트하는 증분(Incremental) 업데이트가 가능하다. "DLC"
배경: https://blogs.unity3d.com/kr/2019/07/15/addressable-asset-system/
vs 에셋번들
에셋번들과 어드레서블의 가장 큰 차이는 저장소로부터 에셋을 가져오는 방식이다.
어드레서블은 에셋에 Address를 부여하는데, 이 Address로 에셋들을 참조한다.
에셋 번들은 중개자 없이 경로를 통해 가져오는 방식인데, 어드레서블은 address라는 중개자를 통해 가져온다. 모든 번거로운 일은 address가 대신 해준다.
에셋번들
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
31
32
33
|
using UnityEngine;
using UnityEngine.UI;
public class AssetBundleRef: MonoBehaviour
{
[SerializeField] private string _bundleName;
[SerializeField] private Image _img0;
[SerializeField] private Image _img1;
private GameObject _go;
private AssetBundle _assetBundle;
// 로컬 저장소로부터 에셋 로드
private void OnEnable()
{
_assetBundle =
// 에디터 path = "[프로젝트 디렉토리]\Assets\StreamingAssets/test"
// 런타임 path = "[앱 설치 디렉토리]\[프로젝트명]_Data\StreamingAssets/test"
AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + _bundleName);
_img0.sprite = _assetBundle.LoadAsset<Sprite>("Apple");
_img1.sprite = _assetBundle.LoadAsset<Sprite>("Banana");
var prefab = _assetBundle.LoadAsset<GameObject>("SomePrefab");
_go = Instantiate(prefab, transform);
}
// 에셋 언로드
private void OnDisable()
{
_assetBundle.Unload(true);
}
}
|
에셋번들의 사용 예시를 보자.
저장소로부터 에셋번들과 에셋을 각각 '경로'와 '파일명'의 string으로 매칭시킨다.
이는 변경에 취약하다. 문자열의 오타로 인해 매칭이 끊어져버릴 수 있기 때문이다.
이를 보완하기 위해 구조 개선 프로그래밍이 필요하다. 개발자가 사용을 꺼리는 이유가 여기에 있다.
어드레서블
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
31
32
33
34
35
36
37
|
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.UI;
public class AddressablesManager : MonoBehaviour
{
[SerializeField] private Image image;
[SerializeField] private AssetReference assetReference;
[SerializeField] private AssetReferenceGameObject assetReferenceGameObject;
[SerializeField] private AssetReferenceSprite AssetReferenceSprite;
public void AddressablesPrefab()
{
// 메모리 로드 구문 없이 바로 Instantiate
Addressables.InstantiateAsync(assetReferenceGameObject);
}
public void AddressablesScene()
{
// 메모리 로드 구문 없이 바로 씬 로드
assetReference.LoadSceneAsync(UnityEngine.SceneManagement.LoadSceneMode.Additive);
}
public void AddressablesSprite()
{
// 메모리에 로드 후 콜백 호출
AssetReferenceSprite.LoadAssetAsync().Completed += OnSpriteLoaded;
}
// 콜백 함수
private void OnSpriteLoaded(AsyncOperationHandle<Sprite> handle)
{
image.sprite = handle.Result;
}
}
|
어드레서블은 AddressableAssets.AssetReference와 같은 클래스를 통해 직접 참조한다.
매칭 과정이 없기 때문에 변경 시 따르는 코드 수정 작업도 필요 없다.
어드레서블 창에서 모든 에셋 그룹을 확인할 수 있고 편집할 수 있어서 에셋 관리가 용이하다.
종속성(의존성, Dependancy) 관리도 자동으로 해주기 때문에 동일 에셋의 중복 번들링을 피할 수 있다. 즉, 에셋이 속할 수 있는 에셋 그룹은 단 하나로 유일하다.
메모리 언로드 함수
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
using UnityEngine;
using UnityEngine.AddressableAssets;
public class SelfDestruct : MonoBehaviour
{
[SerializeField] private float lifetime = 2f;
private void Start()
{
// 지연 후 함수 호출
Invoke("Release", lifetime);
}
void Release()
{
// Instantiate <-> ReleaseInstance
Addressables.ReleaseInstance(gameObject);
}
}
|
어드레서블 또한 메모리 해제 함수가 존재한다.
'Instantiate <-> ReleaseInstance' / 'LoadAsset <-> ReleaseAsset'
각 함수에 맞는 해제함수를 사용해야 한다. 그렇지 않으면 Ref Counting에 대한 이슈가 발생한다.
'Unity > 어드레서블 에셋 시스템' 카테고리의 다른 글
어드레서블 에셋 시스템 - 디버깅: 에셋 빌드 에러 DirectoryNotFoundException (0) | 2020.06.26 |
---|---|
어드레서블 에셋 시스템 - 개념: 씬 로드 & 언로드, Component AssetReference (1) | 2020.06.24 |
어드레서블 에셋 시스템 - 개념: 에셋 로드와 생성 및 해제 (2) | 2020.06.24 |
어드레서블 에셋 시스템 - 개념: 어드레서블 에셋, Filtered AssetReference (0) | 2020.06.16 |
어드레서블 에셋 시스템 - 개념: 어드레서블 윈도우, 시스템 동작 플로우 (0) | 2020.06.16 |
댓글