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.