내일배움캠프 58일차 - 언리얼 C++ 심화: SoftRef와 동기/비동기로드, DataTable과 DataAsset

에셋을 C++에서 가져오는 방법

1) 프로퍼티 참조
UPROPERTY(EditAnywhere)를 붙여 블루프린트에서 할당하는 방식을 일컫는다.

2) 생성 시간 참조
생성자단계에서 ConstructorHelpers::FObjectFinder<타입>이름(TEXT("경로위치"))를 입력해 지정경로에 오브젝트와 오브젝트 클래스를 찾아서 로드하는 방식. .Successed()로 로드 여부를 확인할 수 있다.

3) 간접 프로퍼티 참조
SoftObjectPtr<Type> 을 사용해 할당하는 방식. 아래에서 설명하도록 한다.

TSoftObjectPtr(소프트 오브젝트 레퍼런스)

TSoftObjectPtr<UStaticMesh> MeshToLoad;
TSoftClassPtr<AActor> MyActor;

하드 레퍼런스(오브젝트 레퍼런스, 클래스 레퍼런스):
 1) 타입 값 처음부터 로드.
 2) 참조된 에셋 바로 사용가능.
 3) 메모리 점유율 상승.

소프트 레퍼런스(소프트 오브젝트 레퍼런스, 소프트 클래스 레퍼런스):
 1) 경로만 가지고 있음.
 2) 로딩 전까지는 메모리 점유하지 않음.
 3) 중간로딩으로 프레임드랍 발생가능성 있음(비동기방식 로드로 해결가능)

동기 로드

메인 스레드에서 로드를 하여 로드 중에는 다른 작업을 멈추므로 프레임드랍이 발생할 수 있다.

 - SoftPtr.IsNull(): 객체가 nullptr인가?
 - SoftPtr.IsValid(): 객체가 로드되어있는가?
 - SoftPtr.LoadSynchronous(): 객체를 동기로드를 한다.

TSoftObjectPtr<UStaticMesh> MySoftMesh를 BP에서 로드하는 코드


비동기 로드

원하는 시점에 서브 스레드로 로드를 하여 게임 진행에 영향을 주지 않으면서 로딩이 끝나면 특정 함수를 호출하는 방식이다.

#include "Engine/AssetManager.h"
#include "Engine/StreamableManager.h"

FStreamableManager& Streamable = UAssetManager::GetStreamableManager();

Streamable.RequestAsyncLoad(
      SoftPtr.ToSoftObjectPath(),
      FStreamableDelegate::CreateUObject(this, 함수)
);




DataTable

구조체를 사용하여 표 형식으로 정리하는 에셋파일. FTableRowBase를 상속한 구조체만 등록이 가능하다.

#include "Engine/DataTable.h"

구조체 코드

해당 구조체를 사용한 DataTable

DataTable을 C++에서 사용할때는 UDataTable* 을 사용하며, 다음과 같이 사용할 수 있다.

GetAllRows: 행 데이터를 전부 가져와 TArray에 저장

DataAsset

DataAsset은 DataTable처럼 정보를 저장하는 에셋이지만 특히 무거운 메쉬, 텍스처, 사운드 등 실제 에셋을 불러올 때 주로 쓴다.

DA를 등록할 때 에셋 매니저에 ID를 등록하여
로드할때 ID를 넘겨 로드한다.


DataTable: 한눈에 보는 표
 - 언제 쓰는가?
 1) 아이템 1,000개의 공격력, 가격, 드랍률 등의 수치 데이터를 한눈에 관리할 때.
 2) 기획자가 엑셀로 데이터를 편집하고 엔진으로 임포트(Import)할 때.
 3) 레벨 1부터 100까지의 경험치 테이블처럼 순차적인 데이터를 관리할 때.
 - 단점
  : 특정 Row 하나만 쓰려고 해도 테이블 파일 전체를 메모리에 올려야함. (개별적 관리 어려움)

DataAsset: 개별 포장된 상품, 하나하나의 독립된 파일
 - 언제 쓰는가?
 1) 런타임 중 특정 아이템만 로드해야 할 때.
 2) 무거운 메쉬, 텍스처, 사운드 등 실제 에셋과 연결되어 비동기로 불러와야할 때
 - 단점
 : 아이템이 1,000개면 파일도 1,000개라, 수치를 한꺼번에 비교하며 수정하기 불편함.

DataTable과 DataAsset은 서로 장단점이 명확하기 때문에 두 개를 섞어서 쓰는 방식을 권장한다.

DataAsset 사용법

1) PrimaryDataAsset 클래스 추가


2)추가한 PrimaryDataAsset 헤더에 해당 코드 사용

FPrimaryAssetID: 에셋 매니저가 특정 파일을 식별하기 위해 넘겨주는 ID.
meta = (AssetBundles = "TEXT"): 특정 그룹의 에셋만을 로드하기 위해 고안된 메타데이터.

FPrimaryAssetType: 에셋의 타입을 알려주며, 프로젝트 세팅에서 아래와 같이 타입을 추가할 수 있다.

프라이머리 에셋타입: 내가 접근할 때 사용할 에셋 타입의 이름
에셋 베이스 클래스: 모아두고자 하는 에셋의 Base 클래스
Directories: 로딩할 에셋이 있는 디렉토리


3) 해당 PrimaryDataAsset을 상속하는 DataAsset을 추가한다.


4) 생성한 DataAsset을 사용하는 액터를 하나 만들어서 비동기로드를 실행한다.

#include "Engine/AssetManager.h"

FPrimaryAssetId ItemToLoad;

UAssetManager& AssetManager = UAssetManager::Get();

AssetManager.LoadPrimaryAsset(ItemToLoad, ※TArray<FName> Bundles, Delegate 함수);

댓글

이 블로그의 인기 게시물

내일배움캠프 사전캠프 - 사전캠프설 연휴 커피 파밍 이벤트 작품 [ EXTREMITY ]

내일배움캠프 29일차 - 커리어데이 2일차 : 클라이언트 프로그래머로서 포트폴리오, 입사준비팁