How to use GetComponents with TSubclassOf?

I have a base class for a component called UBrushDynamicComponent, and various component classes that derive from it.

On my actor class, I want to be able to have an array I can iterate over which contains all of the components on the actor that derive from that class.

In my header file I have the following array set up:

  1. TArray<TSubclassOf<UBrushDynamicComponent>> BrushDynamicsArray;

I want to populate this array with all the attached components that are a subclass of UBrushDynamicComponent. What I’m trying is something like this:

  1. GetComponents<TSubclassOf<UBrushDynamicComponent>>(BrushDynamicsArray);

But it doesn’t work. I’ve been trying loads of things based on the error it throws when trying to build, but I can’t figure it out.

How can I end up with an array of all the components on my actor that derive from a particular class?

I usually use GetComponentsByClass for this:


TArray<UBrushDynamicComponent*> Comps = GetComponentsByClass(UBrushDynamicComponent::StaticClass());

Maybe that helps? Also you could post the error you are getting!

That gives me this error:


Error C2440 'initializing': cannot convert from 'TArray<UActorComponent *,FDefaultAllocator>' to 'TArray<UBrushDynamicComponent *,FDefaultAllocator>'

Oops!
It returns them as UActorComponents thus a simple cast should suffice:
I guess you could use



 TArray<UActorComponent*> Comps = GetComponentsByClass(UBrushDynamicComponent::StaticClass()); 

and then cast it to your UBrushDynamicComponent each time you use it.

For the simple GetComponents function did you try omitting the TSubclasOf part? A subclass is also the original class and should be returned eitherway

If I do the simple one as you suggest, like this:


GetComponents<UBrushDynamicComponent>(BrushDynamicsArray);

This is the error it throws:

**Error C2664 'void AActor::GetComponents(TArray<UActorComponent ,UBrushDynamicComponent> &,bool) const’: cannot convert argument 1 from ‘TArray<TSubclassOf,FDefaultAllocator>’ to 'TArray<UActorComponent ,UBrushDynamicComponent> &’

Which I do not understand at all!

If I try the other code you posted, and debug that to the screen:


TArray<UActorComponent*> Components = GetComponentsByClass(UBrushDynamicComponent::StaticClass());

    int32 ComponentsNumber = Components.Num();
    if (GEngine)
    GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::FromInt(ComponentsNumber));

It builds fine, but always debugs ‘0’, no matter how many UBrushDynamicComponents I add to my actor… any thoughts?

The error you are seeing is that you are giving a wrong type: UActorComponent instead of a UBrushDynamicComponent


 
   TArray<UBrushDynamicComponent*> Comp;
    GetComponents<UBrushDynamicComponent>(Comp);


This should compile just fine, doesn’t it?
You probably had something like:


TArray<UActorComponent*> Comp;

Now, I am not quite sure why you are getting zero components: I am not actually testing the code now, but I have used it before. Would you try adding UBrushDynamicComponent (and not a subclass) to check if that’s the issue?
Also make sure you are calling the function in the correct actor, AFTER the initialization of the components (say, add the component in the Constructor and call the function in begin play: just for testing purposes, if this is not what you want )

2 Likes

Ah! OK, I’m very new to C++ so I think I’ve just stumbled upon a fundamental mistake in my understanding. I didn’t really understand that a subclass still is the parent class as well as being the subclass.

So in order to have an array that holds all the subclass components, I can simply do TArray<UBrushDynamicComponent*>. I don’t even need to use TSubclassOf. So I can simply do:


TArray<UDynamicBrushComponent*> DynamicsArray;

GetComponents<UBrushDynamicComponent>(BrushDynamicsArray);

And it works perfectly. You were right about it needing to be in BeginPlay as well though. I was trying to do the GetComponents() in the constructor.

It works perfectly now. Thank you SO MUCH for helping me out!

Yep! Glad I could help :slight_smile: