UE4.21.0 - InputComponent found in code, but not in DefaultPawn Details tab while running

urc_s03_introducing_input_binding

#1

This may be a silly question, but the answer is preventing me from understanding the components that get created at run time.

At the moment, I am unable to find the input component on my default pawn on runtime (this is in the details tab). However, the code still finds one and tells me that it is found. Why would this be? Image attached below - thanks for any help!


#2

I’m seeing the same thing on 4.21.1. I guess something might have changed in newer versions due to which components added at runtime are not shown in the details tab.


#3

The details tab displays only a subset of all components of a class. To simplify a bit: native components are only displayed if they are stored in a property with one of the Visible* or Edit* property specifiers. The input component property is introduced in the AActor class without any of these specifiers, so you won’t see it in the details panel unless you assign the component to another variable that has one of these specifiers.

To test this you can create a C++ subclass of ADefaultPawn along the following lines:

Header (without guards, includes, etc.):

UCLASS() class BUILDINGESCAPE_API AExtendedDefaultPawn : public ADefaultPawn
{
	GENERATED_BODY()

public:
	AExtendedDefaultPawn(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());

	void BeginPlay() override;

private:
	UPROPERTY(VisibleDefaultsOnly)
	UGrabber* Grabber;

	UPROPERTY(VisibleDefaultsOnly)
	UPhysicsHandleComponent* PhysicsHandle;

	UPROPERTY(VisibleDefaultsOnly)
	UInputComponent* MyInputComponent;
};

Body (similarly):

AExtendedDefaultPawn::AExtendedDefaultPawn(
	const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	Grabber = CreateDefaultSubobject<UGrabber>("Grabber");
	PhysicsHandle = CreateDefaultSubobject<UPhysicsHandleComponent>("PhysicsHandle");
	BaseEyeHeight = 60.f;
}

void AExtendedDefaultPawn::BeginPlay()
{
	Super::BeginPlay();

	MyInputComponent = FindComponentByClass<UInputComponent>();

	USphereComponent* SphereComponent{GetCollisionComponent()};
	SphereComponent->SetSimulatePhysics(true);
	SphereComponent->SetMassOverrideInKg(NAME_None, 70.f);
	SphereComponent->SetGenerateOverlapEvents(true);
	SphereComponent->SetNotifyRigidBodyCollision(true);
}

When using this class instead of DefaultPawn_BP, you’ll see that MyInputComponent shows up in the details panel, but this changes as soon as you remove the VisibleDefaultsOnly property specifier for the variable.

In more technical detail (and probably only interesting for the most hard-core nerds among us): How the subset of displayed properties is determined depends on the so-called component-editor mode. The case you’re interested in is EComponentEditorMode::ActorInstance and the code that populates the panel for this mode starts around line 4582 in SSCSEditor.cpp. The important call is ShouldAddInstancedActorComponent() which in turn calls FComponentEditorUtils::CanEditNativeComponent(). If you look in ComponentEditorUtils.cpp you’ll see that this method only returns true if the CPF_EDIT property flag is set, which is typically done by the UPROPERTY() macro.