Declare component with default subcomponent

I am trying to combine two components to add them to the actors as one.

UCLASS(Blueprintable)
class UMySphere : USphereComponent
{
    GENERATED_BODY()

public:
    UPROPERTY(VisibleDefaultsOnly, Category = MyCategory)
    UStaticMeshComponent* SubComponent;

    UMySphere()
    {
        SubComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
        SubComponent->SetupAttachement(this);// throws template mismatch during attachment
        // Without SetupAttachment child component do not visible in Blueprint Viewport
    }
}

Please tell me, is it possible to make such a design? How to do it right?

1 Like

I don’t think it’s possible to spawn and attach a component inside another component’s constructor since neither of them has an owning actor at that point. See here for an explanation. Instead, I would suggest creating the two components in the constructor of the owning actor, setting one of them as root, and attaching the other to it, like this:

 UCLASS(Blueprintable)
 class AMyActor : AActor
 {
     GENERATED_BODY()
 
 public:
     UPROPERTY(VisibleDefaultsOnly, Category = MyCategory)
     UStaticMeshComponent* Mesh;

     UPROPERTY(VisibleDefaultsOnly, Category = MyCategory)
     USphereComponent* Collision;
 
     AMyActor()
     {
         Collision = CreateDefaultSubobject<USphereComponent>(TEXT("Collision"));
         RootComponent = Collision;
         Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
         Mesh->SetupAttachement(Collision);
     }
 }
1 Like

You can also create the subcomponents in the parent component constructor with CreateDefaultSubobject.

Then you can override OnComponentCreated and do the attachment there.

void UParentComponent::OnComponentCreated()
{
Super::OnComponentCreated();
ChildWidgetComponent->AttachToComponent(this, FAttachmentTransformRules::KeepRelativeTransform);
}

But make sure that your parent component is inheriting from USceneComponent, not UActorComponent (so that you can use this ptr as the target for attach.

You might also have to explicitly call RegisterAllComponents on the actor to see the attachment in-editor.

4 Likes

This was the solution that ended up working for me. It didn’t like the child component being attached at the same time the parent component was being constructed.

Moving the attachment to OnComponentCreated solved my issue.

1 Like