SvarogZ
(SvarogZ)
October 30, 2017, 1:50pm
1
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
}
Flash7
(Flash7)
October 30, 2017, 4:30pm
2
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.
SvarogZ
(SvarogZ)
October 31, 2017, 4:44am
3
Thanks! I’ll check and answer how it will be.
SvarogZ
(SvarogZ)
November 1, 2017, 6:59am
4
Well… I have done one small test…
I’ve compared three methods
TArray and search by “for”.
TArray and direct call the element.
TMap and call using FGameplayTag.
Test showed next time delay in fps for 10 million calls:
Two Items in Array:
0.082s
0.045s
0.095s
Fifty (50) Items in Array. Item for search is the last one:
0.4s
0.045s
0.095s
Results:
In view of 10 millions calls it’s possible to use any method.
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.
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.
SvarogZ
(SvarogZ)
November 1, 2017, 7:00am
5
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);
}
}
SvarogZ
(SvarogZ)
November 1, 2017, 7:00am
6
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;
}