Load a DataTable uasset into function?

Hi there…

I want to create an ActorComponent to deal as an inventory (in Cpp). This currently works… ok. I created the source, and was able to add the Component to my PlayerController (via BP).

Now… I created an FStruct used as a row Data for a DataTable Asset (created via Editor)

Now, I added a function “AddTo”, that takes some parameters… like a FName. This function should load the DataTable (named “DT_Items.uasset” in the “Content\Blueprints” Folder) to read the row with the given FName from it.

And… I don’t know why… But the task to load a specific DataTable as function local variable… and access it… is not well… I would say… NOT documented. I really can’t find something readable and understandable about that topic.

so…

How to get from a:

UDataTable* DT_Object;

To my specific DataTable and read from it?

1 Like

I’ve done a huge project using datatables so I might be able to help, but I dont understand really the question.

To load a datatable into a variable, you must first acquire it from the editor. I built a preloader that loads all my assets when the GameInstance launches. Its quite involved pieve of work, but the crux of it is that im using constructor helpers to load the Datatable into a map I can retreive by reference name. You might find these bits of code relavent…or not depending on how i understood the question. Of course, you need to find a way to call AddAsset with the Name and Path of the Datatable, by clicking on the DT in the editor and right click copy reference…In the end I managed to make a list of DataTable assets to load on startup by making a datatable that stored all the names and paths…the trick was then to bootstrapt the first datatable into the preloader to extract its contents to autoload the other datatables, but in a simple use case, you could hard code it I guess.

	//------------------------------ASSET MAP - CANNOT BE A UPROPERTY()
private:
	static TMap<FName, UDataTable*> MyAssetMap;
	//------------------------------ASSET MAP - CANNOT BE A UPROPERTY()
// -------------------- ADD ASSET - OVERRIDDEN PARENT FUNCTION - START
void UPRE_DataTable::AddAsset(FName TheAssetName, FString TheAssetPath)
{
	ConstructorHelpers::FObjectFinder<UDataTable> ASSET(*TheAssetPath);
	if (ASSET.Object)
	{
		UPRE_DataTable::MyAssetMap.Emplace(TheAssetName, ASSET.Object);
	}
}
// -------------------- ADD ASSET - OVERRIDDEN PARENT FUNCTION - END
		
//-------------------- PUBLIC GETTER - STATIC FUNCTION - START
UDataTable* UPRE_DataTable::GetAssetFromMap(FName TheAssetName)
{
	if (UPRE_DataTable::MyAssetMap.Contains(TheAssetName))
	{
		return UPRE_DataTable::MyAssetMap.FindRef(TheAssetName);
	}

	return UPRE_DataTable::MyAssetMap.FindRef(TEXT("DT_ERROR"));
}
//-------------------- PUBLIC GETTER - STATIC FUNCTION - END

To Get At your data, you need to do something like this

//------------------------------UTILITY FUNCTIONS - START (maybe move to CON_DATATABLE later)
const F_UNIVERSAL_DATA UCON_DTExtraction::GetUnivesalStruct_RowData(UDataTable* TheDataTable, FName TheRowName)//used
{
	F_UNIVERSAL_DATA returnStruct;

	TArray<FName> theRows = TheDataTable->GetRowNames();
	if (theRows.Contains(TheRowName) == false)
	{
		
		returnStruct.UNI_FLAG = "%%ERROR";

	}
	else
	{
		returnStruct = *TheDataTable->FindRow<F_UNIVERSAL_DATA>(TheRowName, "");
	}
	

	return returnStruct;
}
//------------------------------UTILITY FUNCTIONS - END

The problem is, that every time I try to use FObjectFinder, the whole Editor crashes…
Even with this short code:

	UDataTable* DT_Object;
	const FString DT_AssetPath = FPaths::ProjectContentDir() + "/01_Blueprints/DT_Items.uasset";
	ConstructorHelpers::FObjectFinder<UDataTable> ASSET(*DT_AssetPath);
	Message = FText::FromString("No Object Found!");
	if (ASSET.Object)
	{
		DT_Object = ASSET.Object;
	Message = FText::FromString("Object Found!");
	}

And… I need them to be loaded outside a Constructor, too. ConstructorHelpers seems to only work inside a Constructor…

And the Docs are really not helpful… same for nearly all YT Tutorials on the DataTable Topic, since they all want the Ref to a DataTable to be set via a Variable… but I need to call this exact DT_Items.uasset at runtime…

Edit:
I also tried to use SoftObjectPath and TryLoad… but this never loads anything and the Message is always “No Object Found!”.

	UDataTable* DT_Object;
	FSoftObjectPath DT_Loader = FPaths::ProjectContentDir() + "/01_Blueprints/DT_Items.DT_Items";
	DT_Object = Cast<UDataTable>(DT_Loader.TryLoad());
	if(!DT_Object)
	{
		Message = FText::FromString("No Object Found!");
		return;
	}
	Message = FText::FromString("Object Found!");

Tried with names:

DT_Items.DT_Items
DT_Items.uasset
DT_Items

Edit_2:
Now tried tih EngineUtils FindOrLoadAssetByPath…

UDataTable* DT_Object;
FString DT_AssetPath = FPaths::ProjectContentDir() + "/98_Datas";
[.....]

	TArray<UObject*> objcs;
	EngineUtils::FindOrLoadAssetsByPath(DT_AssetPath, objcs, EngineUtils::ATL_Regular);
	bool breakIt = false;
	for (auto in: objcs)
	{
		if(breakIt == false)
		{
			if(in->GetName().Contains("DT_Items"))
			{
				DT_Object = Cast<UDataTable>(in);
				breakIt = true;
			}
		}
	}
	if(!DT_Object)
	{
		Message = FText::FromString("No Object Found!");
		return;
	}
	Message = FText::FromString("Object Found!");

It still can´t be found…

1 Like

Found a Solution, thanks to the DerSky Discord…

The path was all wrong.
Instead of using

FPaths::ProjectContentDir() + "98_Datas/DT_Items";

As a Path to the Content, you need to use the cooked game Path…
Means:

"/Game/98_Datas/DT_Items"

in my case…

1 Like

Glad you found a solution, I only use constructor helpers, but from the reply you got , I realize now why the Path includes /Game/

I also noticed that when converting my project to 5.1, getting the path reference is different than UE4.x

1 Like