I have a blank UE5.4 project where i created a basic scene and a ACharacter actor class (C++) and a Blueprint class derived from it. Initially, I tried to create the setup from scratch myself but the character didnt move in PIE. So I ended up literally just replicating what the ThirdPerson Template does, and I have the exact same problem still. The charact appears in game, and I seem to be in possession of it because I get it’s third person camera view, but it doesnt move despite the showdebug EnhancedInput
command showing that the inputs are being fired according to my Input Actions. Here is the deal:
- I have a ACharacter actor class which defines a capsule component as the RootComponent, a CameraBoom and a FollowCamera, sets up CharacterMovement and implements the necessary methods for binding and handling input (exactly as the C++ source code in the ThirdPerson template).
#include "Characters/PlayerCharacter.h"
#include "Engine/LocalPlayer.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "GameFramework/Controller.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "InputActionValue.h"
#include "InputMappingContext.h"
DEFINE_LOG_CATEGORY(LogPlayerCharacter);
APlayerCharacter::APlayerCharacter()
{
// Set size for collision capsule
GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);
// Don't rotate when the controller rotates. Let that just affect the camera.
bUseControllerRotationPitch = false;
bUseControllerRotationYaw = false;
bUseControllerRotationRoll = false;
// Configure character movement
GetCharacterMovement()->bOrientRotationToMovement = true; // Character moves in the direction of input...
GetCharacterMovement()->RotationRate = FRotator(0.0f, 500.0f, 0.0f); // ...at this rotation rate
GetCharacterMovement()->JumpZVelocity = 700.f;
GetCharacterMovement()->AirControl = 0.35f;
GetCharacterMovement()->MaxWalkSpeed = 500.f;
GetCharacterMovement()->MinAnalogWalkSpeed = 20.f;
GetCharacterMovement()->BrakingDecelerationWalking = 2000.f;
GetCharacterMovement()->BrakingDecelerationFalling = 1500.0f;
// Create a camera boom (pulls in towards the player if there is a collision)
CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
CameraBoom->SetupAttachment(RootComponent);
CameraBoom->TargetArmLength = 400.0f; // The camera follows at this distance behind the character
CameraBoom->bUsePawnControlRotation = true; // Rotate the arm based on the controller
// Create a follow camera
FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation
FollowCamera->bUsePawnControlRotation = false; // Camera does not rotate relative to arm
// Note: The skeletal mesh and anim blueprint references on the Mesh component (inherited from Character)
// are set in the derived blueprint asset named ThirdPersonCharacter (to avoid direct content references in C++)
AutoPossessPlayer = EAutoReceiveInput::Player0;
}
void APlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
UE_LOG(LogTemp, Warning, TEXT("SetupPlayerInputComponent called for %s"), *GetName());
// Add Input Mapping Context
if (APlayerController* PlayerController = Cast<APlayerController>(GetController()))
{
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
{
Subsystem->AddMappingContext(DefaultMappingContext, 0);
UE_LOG(LogTemp, Warning, TEXT("Mapping Context added: %s"), *DefaultMappingContext->GetName());
}
else
{
UE_LOG(LogTemp, Error, TEXT("Failed to add Mapping Context for %s"), *GetName());
}
}
// Set up action bindings
if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent)) {
// Jumping
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Started, this, &ACharacter::Jump);
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);
// Moving
EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &APlayerCharacter::Move);
// Looking
EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &APlayerCharacter::Look);
}
else
{
UE_LOG(LogPlayerCharacter, Error, TEXT("'%s' Failed to find an Enhanced Input component! This template is built to use the Enhanced Input system. If you intend to use the legacy system, then you will need to update this C++ file."), *GetNameSafe(this));
}
}
void APlayerCharacter::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogTemp, Warning, TEXT("C++ BeginPlay called for %s"), *GetName());
}
void APlayerCharacter::Move(const FInputActionValue& Value)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("MOVE FIRING"));
UE_LOG(LogTemp, Warning, TEXT("MOVE FIRING"));
// input is a Vector2D
FVector2D MovementVector = Value.Get<FVector2D>();
if (Controller != nullptr)
{
// find out which way is forward
const FRotator Rotation = Controller->GetControlRotation();
const FRotator YawRotation(0, Rotation.Yaw, 0);
// get forward vector
const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
// get right vector
const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
// add movement
AddMovementInput(ForwardDirection, MovementVector.Y);
AddMovementInput(RightDirection, MovementVector.X);
}
}
void APlayerCharacter::Look(const FInputActionValue& Value)
{
// input is a Vector2D
FVector2D LookAxisVector = Value.Get<FVector2D>();
if (Controller != nullptr)
{
// add yaw and pitch input to controller
AddControllerYawInput(LookAxisVector.X);
AddControllerPitchInput(LookAxisVector.Y);
}
}
- Next, I created Input Actions and an Input Mapping Context (both exactly as in the ThirdPerson template)
- Next, I mapped that InputMappingContext in my character Blueprint as the “Default Mapping Context”
- I even tried setting Auto Possession to Player0, but that didn’t make a difference. There is no other Pawns or Characters in the scene.
- I am not overwriting the behaviour or input mapping in the character blueprint. Its all set up in C++. The Character BP Event Graph is empty. In the Details Panel for the corresponding components, the mappings and default values all appear as set in the C++ code.
When I drag my Character BP in the scene for an instance of it in the game, it appears, and when i hit PIE i have its camera third person view, but cant move despite my input actions being registered as shown by the EnhancedInput debug command. The debug log shows that my constructor, SetupPlayerInputComponent
and BeginPlay
method is called and that the InputMappingContext was successfully added, BUT the logs in the Move
methods etc. do not appear when I press the corresponding keys (e.g. WASD).
LogTemp: Warning: SetupPlayerInputComponent called for BP_PlayerCharacter_C_0
LogTemp: Warning: Mapping Context added: IMC_Default
LogTemp: Warning: SetupPlayerInputComponent called for BP_PlayerCharacter_C_0
LogTemp: Warning: Mapping Context added: IMC_Default
LogTemp: Warning: C++ BeginPlay called for BP_PlayerCharacter_C_0
So my C++ methods are not being executed when the Input Actions register. Why? Also, I don’t know why the setup method seems to be called twice.