How to use FindRow in C++?

Hi, im trying to find row from data table that is chosen in blueprint which derived from c++ class.

My enum:

UENUM()
enum class EGridType : uint8
{
	Null = 0 UMETA(DisplayName = "Null"),
	Square = 1 UMETA(DisplayName = "Square"),
	Triangle = 2 UMETA(DisplayName = "Triangle"),
	Hexagon = 3 UMETA(DisplayName = "Hexagon"),
};

USTRUCT()
struct FGridData : public FTableRowBase
{
	GENERATED_USTRUCT_BODY()

	UPROPERTY(EditAnywhere, Category = GridData)
	FName ID;

	UPROPERTY(EditAnywhere, Category = GridData)
	EGridType GridType;
.......

My .cpp file:

GridDataTable = DataTableAsset.Object;

		GridDataTableRow = GridDataTable->FindRow<FGridData>("GridType", UEnum::GetDisplayValueAsText(Shape).ToString());

		if (GridDataTableRow) 
.....

So I do have GridType as the name of the row, and after debugging i can see that im looking for “Square” which is also in Data Table, but it’s not working, I still got nothing, why is that?

.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Engine/DataTable.h"
#include "MyActor3.generated.h"



UENUM()
enum class EGridType : uint8
{
	Null = 0 UMETA(DisplayName = "Null"),
	Square = 1 UMETA(DisplayName = "Square"),
	Triangle = 2 UMETA(DisplayName = "Triangle"),
	Hexagon = 3 UMETA(DisplayName = "Hexagon"),
};

USTRUCT(BlueprintType)
struct FGridData : public FTableRowBase
{
	GENERATED_USTRUCT_BODY()

	UPROPERTY(EditAnywhere, Category = GridData)
	FName ID;

	UPROPERTY(EditAnywhere, Category = GridData)
	EGridType GridType;
};


UCLASS()
class YOUR_API AMyActor3 : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AMyActor3();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;
	
	UPROPERTY(BlueprintReadWrite, EditAnywhere)
	EGridType Shape;

	UPROPERTY(BlueprintReadWrite,EditAnywhere)
	UDataTable* GridDataTable;

	UFUNCTION(BlueprintCallable)
	void GetRow();

	FGridData* GridDataTableRow;
};

.cpp


#include "MyActor3.h"

// Sets default values
AMyActor3::AMyActor3()
{
	PrimaryActorTick.bCanEverTick = true;
}


void AMyActor3::BeginPlay()
{
	Super::BeginPlay();
}

void AMyActor3::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}

void AMyActor3::GetRow() 
{	
	GridDataTableRow = GridDataTable->FindRow<FGridData>("GridType", UEnum::GetDisplayValueAsText(Shape).ToString());	
	if (GridDataTableRow) 
	{				
		GEngine->AddOnScreenDebugMessage(1, 10, FColor::Orange, FString::Printf(TEXT("ID %s, GridType %s"), *GridDataTableRow->ID.ToString(), *UEnum::GetValueAsString(GridDataTableRow->GridType)));
	}	
}

image

1 Like

I understand, many thanks. But I got few question, is there a reason you make it that way?

Why not using FDataTableRowHandle, is it worse?

Why not giving the data table by object finder like this?

static ConstructorHelpers::FObjectFinder<UDataTable>DataTableAsset()

Why called the function in BP not in C++?

No real reason behind calling it from bp. It’s probably just muscle memory from creating so many projects.

Without having another external object to call it, it’s just faster. You usually end up with a bp implementation of the c++ class anyway :slight_smile: . You basically wanted the c++ to execute correctly so that’s where I put my focus.

Datatables are made on the side of the editor. No need to initialize everything a 100% in c++. With time you will find it can have diminishing returns and can be less flexible.

1 Like

I understand, thanks!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.