
- 개발 초기 단계(프로토 타입 만드는 과정)에서는 처음부터 Asset Bundle을 만들어서 사용하진 않는다. 예를 들어, Asset Bundle을 서버에 올려놓고 쓰지 않는다.
- 이유는 그걸 구축하는데 시간이 오래걸린다. 빠른 프로토타이핑을 하기 위해서 Resource폴더에 다 때려 박는다.
- 프로토타입 이후 Resource 폴더에 있었던 에셋들을 분리해서, Asset Bundle로 빼내기도 한다.
- 자꾸 에셋 위치를 바꿀 때마다, 프로게이머는 코드를 변경해야 한다.
Addressable은 오브젝트의 위치만 알고 있으면 된다. 알고 있으면 항상 접근 가능하다.

각 에셋 별로 Addressable을 줄지 안줄지 선택 가능하다. 위 오브젝트 사진 참고
에셋에 Addressable을 주게 될 경우, 해당 에셋은 Addressable 시스템을 갖게 된다.
에디터에서 AssetGroup의 빌드(컴파일) 하게 되면 Addressable 에셋들의 각각 AssetBundle을 만들어지게 된다.
디바이스(모바일)에서는 AssetBundle을 요청할 때, 카탈로그와 프로바이더가 들어가게 된다. 내가 요청하는 에셋과 Addressable의 매핑 정보이다. 즉, Address를 가지고 요청을 해도 해당 에셋을 정확히 로드할 수 있게 된다.



개발자가 게임 장면에 객체인스턴스화하는 방법을 더 많이 제어 할 수 있는 매우 강력한 기능
이는 대규모 세계에서 성능을 개선하고, 메모리를 절약하는데 유용할 수 있지만, 개발자가 클라우드 서버에서 게임 객체를 게임에 로드할 수 있다는 것. 즉, 게임 다운로드 크기가 작아지고 대상 사용자에게 소스가 더 빠르게 전달됨.
또한, 새 업데이트를 푸시할 필요 없이 게임에 동적으로 추가할 수 있다.




public class AddressbleObject : MonoBehaviour
{
//1. 기본적인 객체 인스턴스 방법
[SerializeField]
GameObject Map;
private void Update()
{
if(Input.GetKeyDown(KeyCode.I))
{
Instantiate(Map);
}
}




아래 창은 Addressable에서 사용해야 하는 프리펩이나 에셋들을 저장하는 장소이다.


추가하게 되면 Addressable이 체크 된 것을 볼 수 있음.


해당 맵 프리펩 할당까지 진행

using System.Runtime.InteropServices;
using Unity.VisualScripting;
using UnityEditor.EditorTools;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
// Used for the Hat selection logic
public class AddressbleObject : MonoBehaviour
{
//1. 기본적인 객체 인스턴스 방법
//[SerializeField]
//GameObject Map;
//private void Update()
//{
// if(Input.GetKeyDown(KeyCode.I))
// {
// Instantiate(Map);
// }
//}
//2. Addressable
[SerializeField]
AssetReferenceGameObject DokyoLobbyMap; //⭐0. 에셋 참조 게임 객체 타입으로 선언
private void Update()
{
if(Input.GetKeyDown(KeyCode.I))
{
//1번째 방법 : async(비동기)를 선언하여 에셋을 Ram에 로드하는 것
DokyoLobbyMap.LoadAssetAsync().Completed += OnAddressableLoaded; //⭐1. 에셋 로딩이 완료되었음을 알 수 있도록 Action 델리게이트 선언
}
}
private void OnAddressableLoaded(AsyncOperationHandle<GameObject> handle) //⭐2. 매개 변수로 게임 객체 유형의 비동기 작업 핸들을 받아옴
{
if(handle.Status == AsyncOperationStatus.Succeeded) //⭐3. 비동기 작업 상태(로딩 프로세스) 가 성공적이라면
{
Instantiate(handle.Result); //⭐4. 로딩 프로세스의 결과를 인스턴스화
}
else
{
Debug.LogError("해당 에셋의 로딩이 실패하였습니다.");
}
}
}

using System.Runtime.InteropServices;
using Unity.VisualScripting;
using UnityEditor.EditorTools;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
// Used for the Hat selection logic
public class AddressbleObject : MonoBehaviour
{
//1. 기본적인 객체 인스턴스 방법
//[SerializeField]
//GameObject Map;
//private void Update()
//{
// if(Input.GetKeyDown(KeyCode.I))
// {
// Instantiate(Map);
// }
//}
//2. Addressable
[SerializeField]
AssetReferenceGameObject DokyoLobbyMap; //에셋 참조 게임 객체 타입으로 선언
private void Update()
{
if(Input.GetKeyDown(KeyCode.I))
{
//⭐ 2번째 방법 : Addressable가 관리하는 에셋들은 특별한 게임 객체들이므로, 로딩과 인스턴스화를 동시에 처리할 수 있음
DokyoLobbyMap.InstantiateAsync(); //⭐ 동시에 비동기 로딩과 인스턴스화를 동시에 처리
}
}
}

using System.Runtime.InteropServices;
using Unity.VisualScripting;
using UnityEditor.EditorTools;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
// Used for the Hat selection logic
public class AddressbleObject : MonoBehaviour
{
//2. Addressable
[SerializeField]
AssetReferenceGameObject DokyoLobbyMap; //에셋 참조 게임 객체 타입으로 선언
GameObject instanceReference; //⭐ 0. 인스턴스화 된 오브젝트에 대한 참조(주소)를 저장할 게임 오브젝트 변수 선언
private void Update()
{
if(Input.GetKeyDown(KeyCode.I))
{
DokyoLobbyMap.InstantiateAsync().Completed += OnAddressableInstantiated; //⭐ 1. Addressable의 에셋 인스턴스화가 완료되면 OnAddressableInstantiated 호출
}
else if(Input.GetKeyDown(KeyCode.D))
{
DokyoLobbyMap.ReleaseInstance(instanceReference); //⭐ 5. OnAddressableInstantiated 메서드에서 로딩 프로세스(Addressable의 에셋 인스턴스화) 의 결과를 저장한 오브젝트 메모리 해제
}
}
//올바르게 Addressalbe로 관리 중이였던 에셋들을 삭제 하기 위한 메서드 선언 -> 실질적인 삭제는 아님. 삭제를 하기 위한 메서드라고 생각하면 됨.
private void OnAddressableInstantiated(AsyncOperationHandle<GameObject> handle) //⭐ 2. 매개 변수로 게임 객체 유형의 비동기 작업 핸들을 받아옴
{
if (handle.Status == AsyncOperationStatus.Succeeded) //⭐ 3. 비동기 작업 상태(로딩 프로세스) 가 성공적이라면
{
instanceReference = handle.Result; //⭐ 4. 인스턴스화된 오브젝트의 주소를 오브젝트 변수에 저장
}
}
}

Addressable 인스턴스화

Addressable 인스턴스화 된 오브젝트 삭제(메모리 해제)








유니티에서 이 작업을 쉽게 수행할 수 있으며, 코드를 수정하지 않고도 작동하도록 할 수 있다.




“Build Remote Catalog = 게임 클라이언트 업데이트 없이, 서버에서 최신 리소스를 내려받아 쓸 수 있게 만드는 기능” 이다.


최신 카탈로그를 서버에 업로드 할 수 있게 활성화 하였으니, 에셋 실제 저장 경로와 런타임에서 게임이 에셋을 어디서 불러올지 저장하는 경로를 원격에서 받아 올 수 있게 한다.


Packed Asset에서 Build Path와 Load Path를 각각 Remote.BuildPath와 Remote.LoadPath로 설정 한다.



즉, 에셋들을 서버에 올리고, 실행 시 서버에서 다운로드하여 사용





Defalut LocalGropu의 Build Path와 Load Path를 각각 Remote.BuildPath와 Remote.LoadPath로 설정 한다.






Manage Profilles 클릭

그럼 아래와 같이 창이 뜨는데, Remote.LoadPath 경로에 현재 프로젝트 대쉬보드 경로를 복사하여 작성한다.



Lanch 클릭 시, 50 GB 까지 무료이고 그 이후부터 유료로 결제해야 한다.

CCD (Cloud Content Delivery) 에서 GB가 오르는 조건

GB 계산 방법

유저가 게임을 실행하고 나서, Addressable에 등록된 에셋들을 볼 때 GB가 올라감.

번들 크기 보는 방법

에디터 모드에서 GB 영향 없음

Unity Remote 상관없음


Unity CCD(Cloud Content Delivery) 에서 말하는 버킷(Bucket) 은 콘텐츠를 묶어두는 저장소 단위예요.
쉽게 말하면 파일(에셋 번들, Addressables 빌드 결과 등)을 올려두는 ‘컨테이너’ 라고 생각하면 돼요.

아래처럼 내용들을 적고 Next버튼 클릭

위 버킷 유형은 2가지로 나뉜다.


일단, 일반 버킷 기준으로 Addressable 세팅을 하였기에 일반 버킷으로 진행 후 개발 막바지때 프로모션 버킷으로 변경할 것이다.


아래에 내가 추가하고 싶은 에셋 파일들을 올리면 된다.

하지만, 먼저 Unity에서 먼저 빌드(컴파일)을 하고 빌드 결과물을 버킷에 업로드 해야 한다.






컴파일 도중 에러 발생

AddressableObject 스크립트에서 아래 using문이 컴파일 에러를 발생시켰다. 코드 삭제.

다시 컴파일 해본다. 결과는 성공적이다.




아래 업로드 버튼 클릭




Relese 단계 모두 거치고, Submit 버튼 클릭

프로모션 버킷 또는 실제 서비스 환경에서는 버킷 업로드만 한다고 유저가 바로 다운로드를 할 수 있는 건 아니다. Release를 해야 Catalog가 활성화되고, 유저가 해당 Asset Bundle을 다운로드 할 수 있다.
Release를 해야 공식 배포용으로 지정된다.
일반 버킷에서는 Release는 불 필요하고, Local Build Path나 Regular Bucket에서 테스트 할 때는 안해도 바로 로드 가능하다.





난 DokyoCityLobbyMap 프리펩을 Addressables Groups에 추가했었었다.

아래 사진은 해당 프리펩인데, 프리펩 자식에 있는 표지판을 위치나 회전 등 편집을 하고,

또 다른, 프리펩을 Addressables Groups에 추가했다.

추가하고 나서, 빌드(컴파일)을 해야 하는데, 그 전에, 이전 SeverData 폴더 - Androiod 에 있는 파일들을 삭제 하고, 컴파일을 해야 한다.





아래 파일 클릭.



Addressables에 더 많은 콘텐츠를 추가했기 떄문에, 업로드하는데 시간이 더 오래 걸린다. 모두 업로드가 되었다면 당연히 Release 진행


빌드하게 되면 내가 추가한 프리펩 편집한 내용처럼 프리펩을 볼 수 있을 것이다.