게임 엔진/Unreal
[Unreal] 테이블 데이터 이용 방법 (DataTable)
AlgorFati
2020. 12. 30. 13:34
Data Table
대량의 데이터를 table 형태로 관리해야하는 상황도 생길 수 있다.
이런 경우 unreal engine의 data table을 사용하면 유용하다.
소스코드
#include "Engine/DataTable.h"
USTRUCT()
struct FPhysicsPoseData : public FTableRowBase
{
GENERATED_USTRUCT_BODY()
UPROPERTY(EditAnywhere)
float x;
UPROPERTY(EditAnywhere)
float y;
UPROPERTY(EditAnywhere)
float z;
UPROPERTY(EditAnywhere)
float quatX;
UPROPERTY(EditAnywhere)
float quatY;
UPROPERTY(EditAnywhere)
float quatZ;
UPROPERTY(EditAnywhere)
float quatW;
};
이제 editor에서 실제 데이터 테이블 에셋 파일을 생성한다.
그 후 콘텐츠 브로우저 -> 신규추가 -> 기타 -> 데이터 테이블 구조체 선택 창이 뜨면 이전에 제작한 class를 선택한다.
그리고 생성된 table에 미리 준비한 .csv파일을 로드한다.
파일 내용 (.csv)
Name, x, y, z, quatX, quatY, quatZ, quatW
a, 1, -1, 0.5, 0, -1, -1.2, 2.2
b, 2, -3, 1.5, 0, -1, -1.6, 3.2
Code에서 Data Table 사용하기
#include "Public/CustomDataAsset.h"
#include "UObject/ConstructorHelpers.h"
...
// load data table
static ConstructorHelpers::FObjectFinder<UDataTable> DataTable(
TEXT("/Game/Data/PhysicsPoseDataTable.PhysicsPoseDataTable"));
if (DataTable.Succeeded())
{
UDataTable* dataTable = DataTable.Object;
TArray<FPhysicsPoseData*> arr;
dataTable->GetAllRows<FPhysicsPoseData>(TEXT("GetAllRows"), arr);
// read data
for (int i = 0; i < arr.Num(); ++i)
{
UE_LOG(LogTemp, Warning, TEXT("row loc : %f %f %f quat : %f %f %f %f"),
arr[i]->x, arr[i]->y, arr[i]->z,
arr[i]->quatX,
arr[i]->quatY,
arr[i]->quatZ,
arr[i]->quatW);
}
// write data
for (int i = 0; i < arr.Num(); ++i)
{
arr[i]->x = 1;
arr[i]->y = 0;
arr[i]->z = 3;
UE_LOG(LogTemp, Warning, TEXT("row loc : %f %f %f quat : %f %f %f %f"),
arr[i]->x, arr[i]->y, arr[i]->z,
arr[i]->quatX,
arr[i]->quatY,
arr[i]->quatZ,
arr[i]->quatW);
}
}
...
Add Item to Table
void UtilsData::WritePoseDataTable()
{
static ConstructorHelpers::FObjectFinder<UDataTable> DataTable(
TEXT("/Game/Data/PhysicsPoseDataTable.PhysicsPoseDataTable"));
if (DataTable.Succeeded())
{
UDataTable* dataTable = DataTable.Object;
int idx = 0;
for (int i = 0; i < AndroidAnimPhysicsData.Num(); ++i)
{
const PhysicsPoseData& poseData = AndroidAnimPhysicsData[i];
float time = poseData.seqTime;
for (int j = 0; j < poseData.data.Num(); ++j)
{
const PhysicsData& data = poseData.data[j];
FName name(*FString::FromInt(idx));
FPhysicsPoseDataTableRow row;
row.time = time;
row.bname = data.bname;
row.boneIdx = data.boneIdx;
row.parentBoneIdx = data.parentBoneIdx;
row.x = data.loc.X;
row.y = data.loc.Y;
row.z = data.loc.Z;
row.quatX = data.rot.X;
row.quatY = data.rot.Y;
row.quatZ = data.rot.Z;
row.quatW = data.rot.W;
row.jointAngX = data.jointAng.X;
row.jointAngY = data.jointAng.Y;
row.jointAngZ = data.jointAng.Z;
row.velX = data.vel.X;
row.velY = data.vel.Y;
row.velZ = data.vel.Z;
row.jointAngVelX = data.angVel.X;
row.jointAngVelY = data.angVel.Y;
row.jointAngVelZ = data.angVel.Z;
row.physicsParentName = data.physicsParentName;
row.physicsParentIdx = data.physicsParentIdx;
dataTable->AddRow(name, row);
idx++;
}
}
}
}
Find Item
FString EnumStr = GameUtils::GetEnumDisplayNameAsString("EMontageAction", Action);
UE_LOG(LogTemp, Error, TEXT("EnumStr : %s"), *EnumStr);
UDataTable* DataTable = MontageManagerInterface->GetMontages(Action);
FMontageActionRow* Item = DataTable->FindRow<FMontageActionRow>(FName(*EnumStr), FString(""));
if (Item != nullptr)
{
OutMontageData = *Item;
return true;
}
else
{
return false;
}