게임 엔진/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;
    }