Download

is "FindComponentByClass<>()" expensive?

Dear experts,

I have a Character (derived from ACharacter) and I attached a HealthComponent (derived from UActorComponent) to it to keep track
of the Character health.

Now I have a Pickup (derived from AActor) that adds health points and I call a Heal() method like this:
On line 22 I get a reference to the HealthComponent of the Character to then call Heal() on line 30:

Now I read that “FindComponentByClass<>()” is an expensive thing to do. But what would be an alternative? How else
can I get a reference from my Pickup AActor to a UActorComponent of a ACharacter?

If I leave out line 22 the engine crashes when I overlap the Pickup with my Character.

Thank you, Peter

Usually, I would use FindComponentByClass<>() on actors that may or may not have the component I’m looking for (meaning the component isn’t standard to my class). But if you know that your AMainCharacter will always have a UHealthComponent, then make it a UHealthComponent* property on your AMainCharacter class and access it directly (or if you want to keep it a private member, add public accessors to its data) – no need to search all components for the one you’re looking for if you know it’s always supposed to be there.

This is extremely unlikely to have any measurable performance impact in the usage you showed.

I would also like to know which container is used for storing the actor components/actors. Personally I avoid using functions like these in tick-events or timers, but for a one-time-call it should’nt be too expensive.

This is very cheap because Epic guys are very clever (in Unity doing that is very expensive).

Unreal will do a “->IsA(…)” check before even casting anything in there.
Within IsA() method there’s a bunch of UE_ASSUME macros that speeds up things even further.

If your concern is bound to RAM (slow), Epic also provide us a workaround you can use inline with TInlineComponentArray<>:



TInlineComponentArray<UStaticMeshComponent*> SMComponets;
Actor->GetComponents<UStaticMeshComponent>(SMComponets);

for (UStaticMeshComponent* Component : SMComponets)
{
    // .....
}


https://docs.unrealengine.com/en-US/…ray/index.html

For custom types other than components you can also use custom allocators and specify the min size you expect, like:



TArray< FmyCustomType , TInlineAllocator<24> > myArray;


2 Likes

Hi, “OnComponentBeginOverlap” is defined in “APickupHealer” and is of what I understand only called when the PickupHealer is overlapped. So no Tick() is checking on it.

Thank you for this explanation. I will stick with my code then, I feel pretty comfortable.