Hi,
I wrote a basic function that ensures all component names of a given actor are unique, and renames as necessary to enforce it.
Here is the code:
TSet<FString> ExistingNames; // Notice FString
TArray<USceneComponent*> Components;
Actor->GetComponents(Components);
for (USceneComponent* Component : Components) {
FString Name = Component->GetName();
FString NewName = Name;
int32 Counter = 1;
if (ExistingNames.Contains(NewName.ToLower())) {
do {
NewName = FString::Printf(TEXT("%s_%d"), *Name, Counter++);
} while (ExistingNames.Contains(NewName.ToLower()));
}
while (!Component->Rename(*NewName, Actor, REN_Test)) {
NewName = FString::Printf(TEXT("%s_%d"), *Name, Counter++);
}
Component->Rename(*NewName, Actor);
ExistingNames.Add(NewName.ToLower());
}
A couple points about this code:
- I want to maintain the original case of the name, but ensure case-insensitive uniqueness. This is why all the
ToLower()
are here. - I need this code to be as fast as possible.
I’ve heard that FName is better optimized for comparaisons, and is also case-insensitive. This would in theory make this code faster and eliminate the need for ToLower()
.
But here is my question: by using a TSet of FNames, instead of FStrings, I would need to change all occurences of ExistingNames.Contains(NewName.ToLower())
to ExistingNames.Contains(FName(*NewName))
.
I wonder if the performance gains from querying and comparing FName values in the TSet would outweigh the overhead costs of casting to FName constantly. (I am also a bit unsure how this handles the point I made about case above).
What do you think?