[Part1] 14.언리얼 오브젝트 관리 2 - 패키지UE5/이득우의 언리얼 프로그래밍 공부 노트2024. 3. 13. 18:14
Table of Contents
📦패키지
언리얼 오브젝트 패키지
- 단일 언리얼 오브젝트가 가진 정보는 저장할 수 있지만, 오브젝트들이 조합되어 있다면?
- 저장된 언리얼 오브젝트 데이터를 효과적으로 찾고 관리하는 방법은?
- 복잡한 계층 구조를 가진 언리얼 오브젝트를 효과적으로 저장과 불러들이는 방법을 통일해야함
- 언리얼 엔진은 이를 위해 패키지(
UPackage
)단위로 언리얼 오브젝트를 관리함. - 패키지의 중의적 개념
- 언리얼 엔진은 다양한 곳에서 단어 "패키지" 를 사용하고 있음
- 언리얼 오브젝트를 감싼 포장 오브젝트를 의미함. (이번 강의의 주제)
- 또한 개발된 최종 컨텐츠를 정리해 프로그램으로 만드는 작업을 의미함 → 예) 게임 패키징
- DLC와 같이 향후 확장 컨텐츠에 사용되는 별도의 데이터 묶음을 의미하기도 함 → 예) pkg파일
구분을 위해 언리얼 오브젝트 패키지로 부르는 것도 고려
패키지(Pacakge)와 에셋(Asset)
- 언리얼 오브젝트 패키지는 다수의 언리얼 오브젝트를 포장하는데 사용하는 언리얼 오브젝트.
- 모든 언리얼 오브젝트는 패키지에 소속되어 있음 → 예) Transient Package
- 언리얼 오브젝트 패키지의 서브 오브젝트를 에셋(Asset) 이라고 하며 에디터에는 이들이 노출됨
- 구조상 패키지는 다수의 언리얼 오브젝트를 소유할 수 있으나, 일반적으로는 하나의 에셋만 가짐
- 에셋은 다시 다수의 서브오브젝트를 가질 수 있으며, 모두 언리얼 오브젝트 패키지에 포함됨.
- 하지만 에디터에는 노출되지 않음
💾에셋 참조와 로딩
에셋 정보의 저장과 로딩 전략
- 게임 제작 단계에서 에셋 간의 연결 작업을 위해 직접 패키지를 불러 할당하는 작업은 부하가 큼
- 에셋 로딩 대신 패키지와 오브젝트를 지정한 문자열을 대체해 사용. → 이를 오브젝트 경로라고 함
- 프로젝트 내에 오브젝트 경로 값은 유일함을 보장함
- 그렇기에 오브젝트 간의 연결은 오브젝트 경로 값으로 기록될 수 있음
- 오브젝트 경로를 사용해 다양한 방법으로 에셋을 로딩할 수 있음
- 에셋의 로딩 전략
- 프로젝트에서 에셋이 반드시 필요한 경우 ⇒ 생성자 코드에서 미리 로딩
- 런타임에서 필요한 때 바로 로딩하는 경우 ⇒ 런타임 로직에서 정적 로딩
- ↳ 동기 로딩이라서 프로세스가 잠깐 멈추게 됨
- 런타임에서 비동기적으로 로딩하는 경우 ⇒ 런타임 로직에서 관리자를 사용해 비동기 로딩
오브젝트 경로(Object Path)
- 패키지 이름과 에셋 이름을 한 데 묶은 문자열
- 에셋 클래스 정보는 생랼할 수 있음
- 패키지 내 데이터를 모두 로드하지 않고 오브젝트 경로를 사용해 필요한 에셋만 로드할 수 있음
⇒ `{에셋클래스정보}'{패키지이름}.{에셋이름}` 또는 `{패키지이름}.{에셋이름}`
에셋 스트리밍 관리자(Streamable Manager)
- 에셋의 비동기 로딩을 지원하는 관리자 객체
- 컨텐츠 제작과 무관한 싱글턴 클래스에
FStreamableManager
를 선언해두면 좋음- ↳
GameInstance
는 좋은 선택지
- ↳
FStreamableManager
를 활용해 에셋의 동기/비동기 로딩을 관리할 수 있음- 다수의 오브젝트 경로를 입력해 다수의 에셋을 로딩하는 것도 가능함.
이번강의에서 기억할 내용
- 데이터 에셋을 패키지화 시켜서
.uasset
으로 저장시키는 방법 (에셋 데이터 관리)
에셋을 로딩하는 방법들
패키지를 이름으로 로드하고 에셋을 이름으로 패키지에서 로드
UPackage* StudentPackage = ::LoadPackage(nullptr, *PackageName, LOAD_None); // 패키지를 로드 StudentPackage->FullyLoad(); UStudent* TopStudent = FindObject<UStudent>(StudentPackage, *AssetName);
패키지이름과 에셋이름을 한번에 파라미터로 넘겨서 바로 에셋을 로드 (TopSoftObjectPath 사용)
const FString TopSoftObjectPath = FString::Printf(TEXT("%s.%s"), *PackageName, *AssetName); UStudent* TopStudent = LoadObject<UStudent>(nullptr, *TopSoftObjectPath);
생성자에서 에셋을 로드 → 게임 시작되는 시점에 메모리에 올라와야하는 에셋의 경우 사용
const FString TopSoftObjectPath = FString::Printf(TEXT("%s.%s"), *PackageName, *AssetName); static ConstructorHelpers::FObjectFinder<UStudent>UASSET_TopStudent(*TopSoftObjectPath); // 로드에 성공한 경우 true if (UASSET_TopStudent.Succeeded()) { ... }
비동기로 에셋 로드 →
FStreamableManager
클래스 사용. 핸들은FStreamableHandle
const FString TopSoftObjectPath = FString::Printf(TEXT("%s.%s"), *PackageName, *AssetName); Handle = StreamableManager.RequestAsyncLoad(TopSoftObjectPath, [&]() { if (Handle.IsValid() && Handle->HasLoadCompleted()) { // 오브젝트를 UStudent로 변환 UStudent* TopStudent = Cast<UStudent>(Handle->GetLoadedAsset()); if (TopStudent) { PrintStudentInfo(TopStudent, TEXT("AsyncLoad")); Handle->ReleaseHandle(); Handle.Reset(); } } } );
'UE5 > 이득우의 언리얼 프로그래밍 공부 노트' 카테고리의 다른 글
[Part2] 1.언리얼 엔진 게임 제작 기초 (1) | 2024.03.24 |
---|---|
[Part1] 15.언리얼 빌드 시스템 (0) | 2024.03.15 |
[Part1] 13.언리얼 오브젝트 관리 1 - 직렬화 (1) | 2024.03.12 |
[Part1] 12.언리얼 엔진의 메모리 관리 (0) | 2024.01.28 |
[Part1] 11.언리얼 컨테이너 라이브러리(2)-구조체와 Map (1) | 2023.12.31 |