[Unity 강의] 뱀서라이크 강의 - Addressable
카테고리: Class VamSurLike
태그: Addressable, C#, Unity, VamSurLike
리소스 관리
1. 드래그 드롭으로 연결 - 번거롭고 에러가 일어날 수 있다.
2. Resources 폴더를 사용해서 경로로 관리 ex) var a = Resources.Load<GameObject>("Prefabs/Snake_01");
빌드 시 폴더에 사용 안 하는 Resource가 있을 수 있어서 용량이 커질 수 있다.
추가 삭제가 어렵다.
3. Addressable 사용
✔ (프로젝트에선 2,3 번을 섞어서 사용)
Addressable
1. Package Manager에서 Addressable 검색 후 설치
2. Window - Asset Management - Addressable - Group - Create Addressable Setting
3. 등록할 Resource를 Addressable 체크
OR 드래그로 그룹에 등록
4. Path 경로, Addressable Name - 키값(원하는 이름으로 바꿔주기)
- 파일의 위치가 바뀌면 Path 값이 바뀌고 키값을 이용해 찾으면
- 위치가 바뀌어도 키값으로 경로를 찾을 수 있다. -> 관리가 편해진다.
ResourceManager
✔ 필요한 using 추가
✔ Dictionary<String(Addressable Name),Object>
로 리소스 관리.
✔ (Load
Instantiate
Destroy
) 필요한 리소스를 사용할 경우
✔ (LoadAsync
LoadAllAsync
) 게임에 리소스를 비동기 로드
✔ Label을 이용한 여러 리소스 로드
ResourceManager 코드
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using System;
using Object = UnityEngine.Object;
using System.Runtime.InteropServices;
public class ResourceManager
{
Dictionary<string, UnityEngine.Object> _resources = new Dictionary<string, Object>();
public T Load<T>(string key) where T : Object
{
if (_resources.TryGetValue(key, out Object resource))
return resource as T;
return null;
}
public GameObject Instantiate(string key, Transform parent = null, bool pooling = false)
{
GameObject prefabs = Load<GameObject>($"{key}");
if (prefabs==null)
{
Debug.Log($"Failed to load Prefabs : {key}");
return null;
}
GameObject go = Object.Instantiate(prefabs, parent);
go.name = prefabs.name;
return go;
}
public void Destroy(GameObject go)
{
if (go == null)
return;
Object.Destroy(go);
}
#region 어드레서블
public void LoadAsync<T>(string key,Action<T> callback = null) where T : UnityEngine.Object
{
// 캐시 확인.
if (_resources.TryGetValue(key, out Object resource))
{
callback?.Invoke(resource as T);
return;
}
// 리소스 비동기 로딩
var asyncOperation = Addressables.LoadAssetAsync<T>(key);
asyncOperation.Completed += (op) =>
{
_resources.Add(key, op.Result);
callback?.Invoke(op.Result);
};
}
public void LoadAllAsync<T>(string label, Action<string, int, int> callback) where T : UnityEngine.Object
{
// Action<string, int, int> => <Key, loadCount, totalCount> loadCount, totalCount는 유동적 필요x면 없어도된다.
var opHandle = Addressables.LoadResourceLocationsAsync(label, typeof(T));
opHandle.Completed += (op) =>
{
int loadCount = 0;
int totalCount = op.Result.Count;
foreach (var result in op.Result)
{
LoadAsync<T>(result.PrimaryKey, (obj) =>
{
loadCount++;
callback?.Invoke(result.PrimaryKey, loadCount, totalCount);
});
}
};
}
#endregion
}
GameScene 코드에서 Resource활용
public class GameScene : MonoBehaviour
{
void Start()
{
Managers.Resource.LoadAllAsync<GameObject>("Prefabs", (key,count,totalCount) =>
{
Debug.Log($"{key} {count}/{totalCount}");
if (count==totalCount)
{
StartLoaded();
}
});
}
void StartLoaded()
{
// Resources폴더에서 찾는 방식
// var a = Resources.Load<GameObject>("Prefabs/Snake_01");
var player = Managers.Resource.Instantiate("Slime_01.prefab");
player.AddComponent<PlayerController>();
GameObject monsterObjects = new GameObject() { name = "@Monsters" };
var snake = Managers.Resource.Instantiate("Snake_01.prefab", monsterObjects.transform);
var goblin = Managers.Resource.Instantiate("Goblin_01.prefab", monsterObjects.transform);
var joystick = Managers.Resource.Instantiate("UI_Joystick.prefab");
joystick.name = "@UI_Joystick";
var map = Managers.Resource.Instantiate("Map.prefab");
map.name = "@Map";
Camera.main.GetComponent<CameraController>().Target = player;
}
}
Label을 이용한 리소스 로드
✔ 필요할 때 리소스를 불러오지 않고 게임 시작 시 로딩 화면에서 필요한 Resource를 다 불러온다.
✔ Labels를 이용하는 방식 - Labels - (+) Prefabs
✔ 해당 라벨에 포함된 모든 리소스 로드
✔ -> 키값 추출해서 foreach 비동기 로딩
✔ LoadAllAsync
코드
이것저것 메모
폴더를 Addressable
✔ 폴더 자체를 Addressable로 만들 수도 있다.
프리팹 로드 시 포함된 리소스
✔ 프리팹 로드 시 프리팹에 포함된 Sprite도 같이 로드된다.
✔ 하지만 Sprite가 따로 로드가 필요하면 등록해주면 된다.
람다 복습
✔ GameScene - LoadAllAsync 사용하는 부분
✔ 람다 -> 메서드로?
void Start()
{
Managers.Resource.LoadAllAsync<GameObject>("Prefabs", (key,count,totalCount) =>
{
Debug.Log($"{key} {count}/{totalCount}");
if (count==totalCount)
{
StartLoaded();
}
});
}
-----------------------------------------------------------------
private void LambdaTest(string key, int count, int totalCount)
{
Debug.Log($"{key} {count}/{totalCount}");
if (count == totalCount)
{
StartLoaded();
}
}
void Start()
{
Managers.Resource.LoadAllAsync<GameObject>("Prefabs",LambdaTest);
}
잡담, 일기?
데이터로 만들어서 관리가 핵심적이다.
어드레서블 기능이 더 많아서 알아보자.
댓글남기기