
FTableRowBase을 상속받은 클래스를 정의한다.FTableRowBase
- 데이터 테이블의 행(row)에 해당하는 구조체를 정의할 수 있으며, 테이블의 각 열(column)에 해당하는 데이터를 적절한 데이터 타입으로 저장할 수 있습니다.
- 테이블의 Column 값에 알맞은 데이터 타입으로 멤버 변수를 정의해야 합니다.
BlueprintReadWriteUPROPERTY의 값으로 넣어줘야 합니다. => (그래야 파생한 블루 프린트 클래스에서 데이터를 확인할 수 있음)

USTRUCT(BlueprintType)
struct PROJECTXZ_API FItemTable_Module : public FTableRowBase
{
GENERATED_BODY()
public:
FItemTable_Module() { }
FItemTable_Module(int32 _ID, int32 _CATEGORY_ID, FString _ASSETNAME, FString _ASSETPATH, FString _IMAGEPATH)
: ID(_ID), CATEGORY_ID(_CATEGORY_ID), ASSETNAME(_ASSETNAME), ASSETPATH(_ASSETPATH), IMAGEPATH(_IMAGEPATH)
{
}
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Module)
int32 ID;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Module)
int32 CATEGORY_ID;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Module)
FString ASSETNAME;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Module)
FString ASSETPATH;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Module)
FString IMAGEPATH;
};
해당하는 csv 테이블을 임포트 한다.
정의한 데이터 테이블 클래스를 블루 프린트 클래스로 생성한다.


임포트 한 csv 테이블을 블루 프린트에서 읽는다.
- Reimport 버튼을 클릭
- 데이터 값이 잘 들어간 걸 확인할 수 있다 !!

저는 프로젝트에서 사용할 DataManager 클래스를 생성하여, FName 데이터 타입인 RowName 을 인자로 가지는 함수를 만들어, 해당하는 열을 리턴하도록 하는 유틸리티 기능을 구현하였습니다.
UGameInstanceSubsystem 상속받은 클래스로 구현하여, 어디서나 접근 가능하도록 구현하였다.UGameInstanceSubsystem 클래스
UGameInstanceSubsystem은 게임 인스턴스와 함께 생성되고, 게임 전체에서 접근할 수 있는 전역적인 객체입니다.- 특정 레벨에 한정되지 않고 프로젝트 내 어디서나 동일한 인스턴스에 접근 가능하여, 레벨 간의 전환이 이루어져도 데이터 테이블을 계속해서 활용할 수 있어, 데이터 관리에 매우 적합합니다.
DataManager는 시스템 전반에서 자주 사용되는 데이터 관리 기능을 포함하고 있으므로, 이를GameInstanceSubsystem으로 구현하는 것이 적합하다고 판단하였습니다!
FItemTable_Module* UXZDataManager::TryGetModuleAsset(FName RowName) const
{
if ( !ModuleAssetTable )
{
UE_LOG(LogTemp, Warning, TEXT("Item ModuleAsset Table does not exist."));
return nullptr;
}
FItemTable_Module* ModuleAssetTableRow = ModuleAssetTable->FindRow<FItemTable_Module>(RowName, TEXT("Item ModuleAssetTable Lookup"));
if ( ModuleAssetTableRow )
{
UE_LOG(LogTemp, Warning, TEXT("Found Item ModuleAssetTable for RowName: %s"), *RowName.ToString());
return ModuleAssetTableRow;
}
UE_LOG(LogTemp, Warning, TEXT("Could not find Item ModuleAssetTable for RowName: %s"), *RowName.ToString());
return nullptr;
}
LoadObject함수를 통해 동적으로 애셋을 로드할 수 있습니다.
if ( const UXZDataManager* DataManager = UGameInstance::GetSubsystem<UXZDataManager>(GetWorld()->GetGameInstance()) )
{
...
if ( FItemTable_Module* ModuleAsset = DataManager->TryGetModuleAsset(ModuleIDName) )
{
...
UXZAssetManager& AssetManager = UXZAssetManager::GetXZAssetManager();
FSoftObjectPath AssetPath = ModuleAsset->ASSETPATH; // 데이터 테이블의 AssetPath
// Asset Manager, RequestAsyncLoad 함수를 사용하여 비동기 로드 구현
AssetManager.GetStreamableManager().RequestAsyncLoad(AssetPath, FStreamableDelegate::CreateLambda([this, SkeletalMeshComponent, AssetPath]()
{
// 애셋 로드가 끝난 후 실행될 코드
if (USkeletalMesh* SkeletalMesh = Cast<USkeletalMesh>(AssetPath.TryLoad()))
{
SkeletalMeshComponent->SetSkeletalMesh(SkeletalMesh);
...
}
}));
}
}