How can I bind to an object other than this: EnhancedInputComponent->BindAction(...)?

Hi!

Why can’t I bind to an object other than this? I know I could bind to wrapper functions that call the actual function. But there must be a direct way or am I wrong?

void AThePlayerController::SetPawn(APawn* InPawn)
{
	Super::SetPawn(InPawn);

	PlayerCharacter = Cast<ATheThirdPersonGameCharacter>(GetPawn());
}


void AThePlayerController::SetupInputComponent()
{
	Super::SetupInputComponent();
	if(UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(InputComponent))
	{
		// Is working
		EnhancedInputComponent->BindAction(TestAction, ETriggerEvent::Triggered, this, &AThePlayerController::Test);
		
		// Does nothing
		EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, GetCharacter(), &ACharacter::Jump);
		
		// Does nothing
		EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, PlayerCharacter.Get(), &ATheThirdPersonGameCharacter::Move);
	}
}

void AThePlayerController::Test()
{
	UE_LOG(LogTemp, Warning, TEXT("%s"), *FString(__FUNCTION__));
}

There’s alreay a thread, but since it’s old and not answered I aks again with a different example:

InputComponent BindAction delegate to other object than this

Thanks in advance!

Probably because SetupInputComponent() on PlayerController is called before the character is created, so GetCharacter() returns null at this point and you are binding to nothing.

The character has its own input component. You can override SetupInputComponent in character class to bind actions there.

If you really want to do everything in PlayerController, you’ll have to rebind actions to the character every time you change character. Override function OnPossess in playercontroller and do the binding there like you did with GetCharacter()… I wouldn’t recommend this approach though…

Alternatively, you can bind actions to PlayerController functions that simply forward to the current character in real time. Something like this :

// Setup
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &AThePlayerController::Jump);

void AThePlayerController::Jump()
{
    if (auto Char = GetCharacter())
        Char->Jump();
    else
        //do something else?
}
1 Like

Thanks for the answer!

This totally makes sense.

I know there is ACharacter::SetupPlayerInputComponent and it’s also used in the project templates. However, don’t you thinks it’s kind of violating the single responsibility principle? Isn’t this exactly the PlayerController 's responsibility?

"The PlayerController essentially represents the human player’s will. " - https://docs.unrealengine.com/5.1/en-US/player-controllers-in-unreal-engine/

I think even better would be if the PlayerController holds a reference to an Interface that is implemented by a Character or a CharacterInputComponent and BindAction on that, but this needs even more wrappers.

What are your thoughts on that?