GetComponentByClass()

I tried to implement the TotalMassOfActors function myself before looking at how you’d do it, and I came up with the following using Google:

float UOpenDoor::TotalMassOfActors() const
{
	TArray<AActor*> OverlappingActors;
	PressurePlate->GetOverlappingActors(OUT OverlappingActors);

	float Total = 0.f;
	
	for (int i = 0; i < OverlappingActors.Num(); i++)
	{
		UPrimitiveComponent* PrimComp = OverlappingActors[i]->GetComponentByClass(UPrimitiveComponent::StaticClass());
		Total += PrimComp->GetMass();
	}

	// for (AActor* Actor : OverlappingActors)
	// {
	// 	Total += Actor->FindComponentByClass<UPrimitiveComponent>()->GetMass();
	// }

	UE_LOG(LogTemp, Warning, TEXT("Total weight = %f"), Total);
	return Total;
}

However, this attempt gave me an error message:

"a value of type “UActorComponent *” cannot be used to initialize an entity of type “UPrimitiveComponent *”

I’m guessing that the problem is the following part of the line:

OverlappingActors[i]->GetComponentByClass(UPrimitiveComponent::StaticClass());

But I can’t understand why this returns a UActorComponent and not a UPrimitiveComponent.

Also a related question - the only difference in the documentation between GetComponentByClass() and FindComponentByClass() seems to be that FindComponentByClass() is a “native version of GetComponentByClass”. But what does “native version” mean here?

Because it’s not a function template. It always returns AActorComponent and you need to cast it yourself. i.e. this is the function declaration

AActorComponent* AActor::GetComponentByClass(TSubclassOf<UActorComponent> ComponentClass) const;

Whereas FindComponentByClass has a template version and will return whatever the template argument T* happens to be. Basically, it does the cast for you.

GetComponentByClass is exposed to blueprint. GetComponentByClass just calls FindComponentByClass, so native = native to the engine/C++.

1 Like

Where would I be able to find that function declaration?

The documentation “remarks” section for GetComponentByClass says:
“Searches components array and returns first encountered component of the specified class”. This feels misleading because it sounds like you should be able to specify what class you want to return.

I don’t understand what a template version is (can you point me towards more info?) but it would be helpful to have the difference between template version/non template version in the documentation, is it documented somewhere else?

Also, the function declaration that you posted above has a parameter of “TSubclassOf ComponentClass” and I thought that UPrimitiveComponent was a subclass of UActorComponent because it inherited from UActorComponent

It’s only misleading if you are unfamiliar with C++.

It is, but that doesn’t change the return type at all. The return type is UActorComnponent*,
You would need to cast to UPrimitiveComponent.

UPrimitiveComponent* Thing = Cast<UPrimitiveComponent>(GetComponentByClass(UPrimitiveComponent));

It’s this one

AActor::FindComponentByClass | Unreal Engine Documentation

That does

template<typename T>
T* FindComponentByClass() const
{
    return Cast<T>(FindComponentByClass(T::StaticClass());
}

And you provide the template argument for type T.

FindComponentByClass<UPrimitiveComponent>();

And that means the compiler would generate the function

UPrimitiveComponent* FindComponentByClass() const
{
    return Cast<UPrimitiveComponent>(FindComponentByClass(UPrimitiveComponent::StaticClass());
}
2 Likes

Thanks, the above is helpful. Where did you get this information though (or rather, how could I find the same info)? The specific info that I’d like to be able to look up is the content of the functions, so for example this bit:

template<typename T>
T* FindComponentByClass() const
{
    return Cast<T>(FindComponentByClass(T::StaticClass());
}

Similarly, where I said “Where would I be able to find that function declaration?” above, I meant where do i go to look up the declaration and definition of GetComponentByClass(), i.e. where did you pull the following line from?

AActorComponent* AActor::GetComponentByClass(TSubclassOf<UActorComponent> ComponentClass) const;

I hope that makes sense.

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.

Privacy & Terms