Select component type in editor

I am trying to let my designers assign a specific type of camera component in the editor rather than hard-coding which camera is being used.

(e.g. I don’t have their soon-to-exist custom camera component, and it might be a BP only one).

I have tried two methods based on threads in the answerhub

Method 1

This is based on the following thread:

1) Set up a new C++ Pawn with a Camera Component

	UPROPERTY(Category = "Camera", BlueprintReadWrite)
		TSubclassOf<UCameraComponent> Camera;

2) Add a Camera Component Type selection variable

	UPROPERTY(Category = "Camera", BlueprintReadWrite)
		UClass* CameraType;

3) Construct the given component type and assign it to the camera variable (in pawn constructor)

Camera = CreateDefaultSubobject<CameraType>(TEXT("Camera"));

Is something like this possible? I currently get the following error:

error C2974: 'UObject::CreateDefaultSubobject': invalid template argument for 'TReturnType', type expected

##Method 2

Based on this thread:

1) Set up a new C++ Pawn with a Camera Component

	UPROPERTY(Category = "Camera", BlueprintReadWrite)
		UCameraComponent* Camera;		

2) Construct the given component type and assign it to the camera variable (in pawn constructor)

Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));

3) Create a blueprint derived from the C++ class (which is BlueprintType)

**4) Show Inherited Variables **

**5) Edit the Camera Component Type from the dropdown **

This doesn’t work, see the attached image:

70501-variable+editing.png

Hello vikhik,

Can I assume that your custom camera component inherits from UCameraComponent? If this is the case, your first method is almost correct. You can remove the line about creating a UClass variable and replace the line in the 3rd step with:

Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));

After doing this, if you create a blueprint based off the pawn, you should see a “Camera” variable in the details panel. Due to the TSubclassOf, the dropdown should include CameraComponent and any class / blueprint that inherits from it.

You also may need to add the “EditAnywhere” specifier to the UPROPERTY declaration.

The problem with that is now I get an error when compiling:

error C2679: binary '=': no operator found which takes a right-hand operand of type 'UCameraComponent *' (or there is no acceptable conversion)

The code I am using is:

.h:

	UPROPERTY(Category = "camera", BlueprintReadWrite, EditAnywhere)
		TSubclassOf<UCameraComponent> Camera;

.cpp constructor:

	Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));

Also, dereferencing or casting the created component doesn’t help, not sure how to solve this?

UPROPERTY(Category = “Camera”, BlueprintReadWrite, EditAnywhere)
TSubclassOf CameraComponentType;

UPROPERTY(Category = "Camera", BlueprintReadOnly)
    UCameraComponent * CameraComponent;

ACustomPawn::ACustomPawn(const FObjectInitializer& ObjectInitializer): Super(ObjectInitializer)
{
    ObjectInitializer.CreateDefaultSubobject(CameraComponent, TEXT("Camera"), UCameraComponent::StaticClass(), CameraComponentType, false, false, false);
    
}

So this works for selecting the type. Now, what do you need to do if you want to edit some UPROPERTY variables for the selected type?

Does’nt work for me. CameraComponentType still contains its default value while in constructor.

It seems to me that we cannot access a property value edited in editor while still in constructor. And the problem is that CreateDefaultSubObject can only be executed in constructor. That’s the catch.

If any one knows a way to directly get the modified value of a property while still in constructor or a way to cleanly replace a component that was first created as a DefaultSubObject, I think it would work :p.

By the way, there was a missing “*” before CameraComponentType which in CreateDefaultSubObject which caused a crash to desktop. Took me a while to find out :

ObjectInitializer.CreateDefaultSubobject(CameraComponent, TEXT("Camera"), UCameraComponent::StaticClass(), *CameraComponentType, false, false, false);

For this, you need “EditInlineNew” as specifier of your base C++ class and “EditAnyWhere” as specifier of the UProperty:

UCLASS(EditInlineNew) class XXXX UCameraComponent : public UGameplayComponent

And

UPROPERTY(Category = "Camera", BlueprintReadOnly, EditAnyWhere) UCameraComponent * CameraComponent;

Well I found a solution (the upvoted answer is 5 years old and does not work anymore).

UPROPERTY(Category = "Camera", BlueprintReadWrite, EditAnywhere)
TSubclassOf<UCameraComponent> CameraComponentType;
     
UPROPERTY(Category = "Camera", BlueprintReadOnly)
UCameraComponent * CameraComponent;

ACustomPawn::ACustomPawn(): Super()
	{
	// Get the object as modified in editor
	ACustomPawn* DefaultObject = Cast<ACustomPawn>(this->GetClass()->GetDefaultObject());

	// Get value of sub class to use
	TSubclassOf<UCameraComponent> DefaultClass = DefaultObject->CameraComponentType;
	if (DefaultClass)
	{
		CameraComponent = Cast<UCameraComponent>(this->CreateDefaultSubobject(TEXT("Camera"), UCameraComponent::StaticClass(), *DefaultClass, true, false, false));
	}         
}

I’m not sure it’s the simplest, but at least it works (been looking for it for 15 hours).

you mean DefaultClass instead of CameraComponentType in line 16 :stuck_out_tongue:

tried, but doesn’t work…

  • pointer type is still UCameraComponent;
  • execution of subclassed component crashes the engine…

You’re right. Thanks for your attention, I’ve just corrected it.