Getting Data from DataAsset

How can I get data from the DataAsset without using FOR.
If DataAsset contain, for example 1000 items it’ll be too slow…

Now I do it like this

TSubclassOf UDreampaxItemsDataAsset::GetItemOutfitClass(FName ItemNameId)
{
	for (int i = 0; i <= ItemsDataBase.Num(); i++) // loop trough the whole DB
	{

		if (ItemNameId == ItemsDataBase[i].ItemNameId) // if the item exists in our DB, return it
		{
			return ItemsDataBase[i].ItemOutfitClass;
			break;
		}
	}

	return nullptr; // else return nothing
}

Yeah, TArray is linear search. You need to use another container, like TMap. Something like this:

TMap<FName, TSubclassOf> MyMap;

Fill it up at the beginning and use anywhere.

Thanks! I’ll check and answer how it will be.

Well… I have done one small test…
I’ve compared three methods

  1. TArray and search by “for”.
  2. TArray and direct call the element.
  3. TMap and call using FGameplayTag.

Test showed next time delay in fps for 10 million calls:

Two Items in Array:

  1. 0.082s
  2. 0.045s
  3. 0.095s

Fifty (50) Items in Array. Item for search is the last one:

  1. 0.4s
  2. 0.045s
  3. 0.095s

Results:

  1. In view of 10 millions calls it’s possible to use any method.
  2. Fastest method is 2. However, it’s required to save (int) variable as adress in DataBase to Actors and inventory. It can lead to mistakes.
  3. TMap is two times slower than direct call to TArray element, nevertheless it’s more preferred method. It’s allow to use all data more safly.

I choosed last one.

Test function with cycle:

void ADreampaxCharacter::TestFunction()
{
	UE_LOG(LogTemp, Warning, TEXT("Test function started"));
	
	// Cast to class with Data Blueprint
	ADreampaxGameMode* DreampaxGameMode = Cast<ADreampaxGameMode>(GetWorld()->GetAuthGameMode());
	
	// Set Name of the Item for all variants
	FGameplayTag ItemNameTag;
	ItemNameTag.FromExportString("ItemName.CartonBox");
	FName TestName = TEXT("CartonBox");
	
	// Class to spawn
	TSubclassOf<class ADreampaxItem> ItemToEquipClass;

	UE_LOG(LogTemp, Warning, TEXT("Test name is %s"), *TestName.ToString());

	// ten million cycles
	for (int i = 0; i < 10000000; i++)
	{
		// 2 items - 0.082s
		// 50 items - 0.4s
		//ItemToEquipClass = DreampaxGameMode->DreampaxItemsDataAsset->GetItemOutfitClass(TestName);

		// 2 items - 0.045s
		// 50 items - 0.045s
		//ItemToEquipClass = DreampaxGameMode->DreampaxItemsDataAsset->GetSpeedTestFunctionArray(1);
		//ItemToEquipClass = DreampaxGameMode->DreampaxItemsDataAsset->GetSpeedTestFunctionArray(49);

		// 2 items - 0.095s
		// 50 items - 0.095s
		ItemToEquipClass = DreampaxGameMode->DreampaxItemsDataAsset->GetItemOutfitClassTest(ItemNameTag);
	}
	UE_LOG(LogTemp, Warning, TEXT("Cycle is finished"));
	if (ItemToEquipClass)
	{
		UE_LOG(LogTemp, Warning, TEXT("Item is found"));
	}

	FActorSpawnParameters SpawnInfo;
	SpawnInfo.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
	ADreampaxItem* SpawnedItem = GetWorld()->SpawnActor<ADreampaxItem>(ItemToEquipClass, SpawnInfo);

	if (SpawnedItem)
	{
		UE_LOG(LogTemp, Warning, TEXT("Item is spawned"));
		AddItem(SpawnedItem);
	}
}

Search functions:

TSubclassOf<class ADreampaxItem> UDreampaxItemsDataAsset::GetItemOutfitClass(FName ItemNameId)
{
	for (int i = 0; i <= ItemsDataBase.Num(); i++) // loop trough the whole DB
	{

		if (ItemNameId == ItemsDataBase[i].ItemNameId) // if the item exists in our DB, return it
		{
			return ItemsDataBase[i].ItemOutfitClass;
			break;
		}
	}

	return nullptr; // else return nothing
}

TSubclassOf<class ADreampaxItem> UDreampaxItemsDataAsset::GetItemOutfitClassTest(FGameplayTag ItemNameTag)
{
	return ItemsDataBaseTest.Find(ItemNameTag)->ItemOutfitClass;
}


TSubclassOf<class ADreampaxItem> UDreampaxItemsDataAsset::GetSpeedTestFunctionArray(uint32 ItemId)
{
	return ItemsDataBase[ItemId].ItemOutfitClass;
}