Replace Root Component on an Inherited Class

Looked a little bit into it,
if you are in C++ there is an easier way to change a component the important part is to set the component defined in the parent of a common root type of the new component.

e.g. if you want your class to support box and sphere collider I would recommend to use the next common parent which is a primitive component.

Then you would assign the component with a fixed name and can override it in the constructor in the C++ class.

TestActor.h

#pragma once

#include "GameFramework/Actor.h"

#include "TestActor.generated.h"

UCLASS(Blueprintable)
class PROPERTYGRAPHII_API ATestActor : public AActor
{
	GENERATED_BODY()

public:
	static const FName RootPrimitiveComponentName;
	
	explicit ATestActor(const FObjectInitializer& ObjectInitializer);
	
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
	TObjectPtr<UPrimitiveComponent> RootPrimitiveComponent { nullptr };
};

UCLASS(Blueprintable)
class PROPERTYGRAPHII_API AChildTestActor : public ATestActor
{
	GENERATED_BODY()

public:
	explicit AChildTestActor(const FObjectInitializer& ObjectInitializer);
};

TestActor.cpp


#include "PropertyGraphII/TestActor.h"

#include "Components/BoxComponent.h"
#include "Components/SphereComponent.h"

const FName ATestActor::RootPrimitiveComponentName = TEXT("Root");

ATestActor::ATestActor(const FObjectInitializer& ObjectInitializer)
{
	RootPrimitiveComponent = Cast<UPrimitiveComponent>(CreateDefaultSubobject(RootPrimitiveComponentName, UPrimitiveComponent::StaticClass(),
		USphereComponent::StaticClass(), true, false));
	SetRootComponent(RootPrimitiveComponent);
}

AChildTestActor::AChildTestActor(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer.SetDefaultSubobjectClass<UBoxComponent>(ATestActor::RootPrimitiveComponentName))
{
}

The important part is

Super(ObjectInitializer.SetDefaultSubobjectClass<UBoxComponent>(ATestActor::RootPrimitiveComponentName))

which defines the new type for the component identified with ATestActor::RootPrimitiveComponentName by name.


Now to blueprint.
I couldn’t find an easy way how to do this in blueprint only the best thing I could find was to create a base C++ class with a defined component then you are able to change the class of the component in blueprints.

ABlueprintTestActor.h

#pragma once

#include "GameFramework/Actor.h"

#include "BlueprintTestActor.generated.h"

UCLASS(Blueprintable)
class PROPERTYGRAPHII_API ABlueprintTestActor : public AActor
{
	GENERATED_BODY()

public:
	static const FName OverridableRootComponentName;
	
	explicit ABlueprintTestActor(const FObjectInitializer& ObjectInitializer);
	
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
	TObjectPtr<USceneComponent> OverridableRootComponent { nullptr };
};

ABlueprintTestActor.cpp

#include "PropertyGraphII/BlueprintTestActor.h"

const FName ABlueprintTestActor::OverridableRootComponentName = TEXT("Root");

ABlueprintTestActor::ABlueprintTestActor(const FObjectInitializer& ObjectInitializer)
{
	OverridableRootComponent = CreateDefaultSubobject<USceneComponent>(OverridableRootComponentName);
	SetRootComponent(OverridableRootComponent);
}

This allows you to change the component in blueprints by selecting a different component class.

The only issue that I found with this is that child blueprints can only go into more specialization.
Meaning that if you change the component to a sphere component you can only change the component to something even more specific in the child.


sphere component can get more specialized to a DrawSphereComponent but not to a box component.

So guess the lesson here is keep the root on a common type until you specialize.