Quick answer: The most common cause is that the Input Mapping Context (IMC) was never added to the local player's Enhanced Input subsystem. Without adding the IMC at runtime, the input actions defined in it will not be processed. Call AddMappingContext on the EnhancedInputLocalPlayerSubsystem during BeginPlay.

Here is how to fix Unreal enhanced input not responding. You have created Input Actions and an Input Mapping Context in Unreal Engine 5's Enhanced Input system, wired everything up in your character class, and pressed the key — nothing. No callback, no movement, no response. The Enhanced Input system replaces the legacy input system with a more flexible architecture, but that flexibility introduces several new failure points. Here is how to track down the problem systematically.

The Symptom

Your UInputAction assets are created and assigned to keys in a UInputMappingContext. You have bound the action in C++ or Blueprint, but pressing the mapped key does nothing. The bound callback function is never called. There is no error in the Output Log, no warning about missing bindings, and no indication that input is being processed at all.

In some cases, one action works but another does not, even though they are in the same mapping context. In other cases, input works during the first pawn possession but stops after a respawn or pawn change. You might also see input working in PIE but failing in a packaged build, or working for Player 0 but not for additional local players in a split-screen setup.

A particularly confusing variant is when the action fires but with unexpected values. A movement action might fire with zero magnitude, or a look action might fire only on Started but never on Triggered. These point to trigger configuration issues rather than binding problems.

What Causes This

1. The Input Mapping Context was never added to the subsystem. This is by far the most common cause. Unlike the legacy input system where bindings in a project settings input table are always active, Enhanced Input requires you to explicitly add your UInputMappingContext to the UEnhancedInputLocalPlayerSubsystem at runtime. Creating the IMC asset and referencing it in your code is not enough. If you never call AddMappingContext, the subsystem does not know about your key bindings and will not process them.

2. Binding to the wrong trigger event type. Enhanced Input actions have multiple trigger event types: Started, Triggered, Ongoing, Completed, and Canceled. The default trigger for a simple key press is Triggered, which fires every frame the key is held. If you bind to Started expecting it to fire continuously for a movement action, you will only get one callback on key-down. If you bind to Completed expecting a press event, you will only get a callback on key-up. The trigger type must match your intended behavior.

3. Input priority conflicts between mapping contexts. When multiple IMCs are active simultaneously, they are processed in priority order. If two IMCs map the same key to different actions, the higher-priority context wins and can consume the input, preventing the lower-priority context from ever seeing it. This is common when you have a gameplay IMC and a menu IMC both active, or when a vehicle IMC conflicts with a character IMC.

4. Input consuming preventing action delivery. By default, when an input action is triggered, it consumes the underlying key event. If a higher-priority action consumes a key, other actions mapped to the same key in lower-priority contexts will not fire. This can be controlled per-action via the bConsumeInput flag, but the default is to consume.

5. Binding on the wrong object or at the wrong lifecycle stage. If you bind input on the Pawn but add the IMC on the PlayerController (or vice versa), the binding may not connect properly. Additionally, if you set up input in BeginPlay on a Pawn that gets possessed after BeginPlay runs, the owning controller may not be available yet. The safest place to set up input on a Pawn is SetupPlayerInputComponent, which is called when the Pawn is possessed.

The Fix

Step 1: Add the Input Mapping Context to the local player subsystem. This must happen at runtime before any input can be processed. The most reliable place is in your PlayerController or Pawn's initialization. Here is the complete setup:

// MyCharacter.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "InputActionValue.h"
#include "MyCharacter.generated.h"

class UInputMappingContext;
class UInputAction;

UCLASS()
class AMyCharacter : public ACharacter
{
    GENERATED_BODY()

public:
    AMyCharacter();

protected:
    virtual void BeginPlay() override;
    virtual void SetupPlayerInputComponent(
        UInputComponent* PlayerInputComponent) override;

    UPROPERTY(EditDefaultsOnly, Category = "Input")
    UInputMappingContext* DefaultMappingContext;

    UPROPERTY(EditDefaultsOnly, Category = "Input")
    UInputAction* MoveAction;

    UPROPERTY(EditDefaultsOnly, Category = "Input")
    UInputAction* JumpAction;

    void OnMove(const FInputActionValue& Value);
    void OnJump(const FInputActionValue& Value);
};
// MyCharacter.cpp
#include "MyCharacter.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "InputMappingContext.h"

AMyCharacter::AMyCharacter() {}

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

    // Add the mapping context to the local player subsystem
    APlayerController* PC = Cast<APlayerController>(
        GetController());
    if (!PC) return;

    UEnhancedInputLocalPlayerSubsystem* Subsystem =
        ULocalPlayer::GetSubsystem<
            UEnhancedInputLocalPlayerSubsystem>(
            PC->GetLocalPlayer());
    if (!Subsystem) return;

    // Priority 0 is default. Higher values take precedence.
    Subsystem->AddMappingContext(DefaultMappingContext, 0);

    UE_LOG(LogTemp, Log,
        TEXT("Added mapping context: %s"),
        *DefaultMappingContext->GetName());
}

void AMyCharacter::SetupPlayerInputComponent(
    UInputComponent* PlayerInputComponent)
{
    Super::SetupPlayerInputComponent(PlayerInputComponent);

    UEnhancedInputComponent* EIC =
        Cast<UEnhancedInputComponent>(PlayerInputComponent);
    if (!EIC) return;

    // Movement: use Triggered for continuous per-frame input
    EIC->BindAction(MoveAction, ETriggerEvent::Triggered,
        this, &AMyCharacter::OnMove);

    // Jump: use Started for a single press event
    EIC->BindAction(JumpAction, ETriggerEvent::Started,
        this, &AMyCharacter::OnJump);
}

void AMyCharacter::OnMove(const FInputActionValue& Value)
{
    FVector2D Axis = Value.Get<FVector2D>();
    AddMovementInput(GetActorForwardVector(), Axis.Y);
    AddMovementInput(GetActorRightVector(), Axis.X);
}

void AMyCharacter::OnJump(const FInputActionValue& Value)
{
    Jump();
}

The critical detail is the AddMappingContext call in BeginPlay. Without this single line, none of the bindings in SetupPlayerInputComponent will ever fire. The subsystem is per-local-player, so you must access it through a valid APlayerController and its ULocalPlayer. If the controller is null at BeginPlay time (which can happen with late possession), move the AddMappingContext call to PossessedBy or OnPossess instead.

Step 2: Verify trigger event types match intended behavior. A common mistake is using the wrong ETriggerEvent for a given action. Here is a diagnostic helper that logs all incoming trigger events for a specific action, so you can see exactly what the system is delivering:

// Debug: bind all trigger events to see what fires
void AMyCharacter::DebugBindAllEvents(
    UEnhancedInputComponent* EIC,
    UInputAction* Action)
{
    EIC->BindAction(Action, ETriggerEvent::Started,
        this, &AMyCharacter::OnDebugStarted);
    EIC->BindAction(Action, ETriggerEvent::Triggered,
        this, &AMyCharacter::OnDebugTriggered);
    EIC->BindAction(Action, ETriggerEvent::Ongoing,
        this, &AMyCharacter::OnDebugOngoing);
    EIC->BindAction(Action, ETriggerEvent::Completed,
        this, &AMyCharacter::OnDebugCompleted);
    EIC->BindAction(Action, ETriggerEvent::Canceled,
        this, &AMyCharacter::OnDebugCanceled);
}

void AMyCharacter::OnDebugStarted(
    const FInputActionValue& V)
{
    UE_LOG(LogTemp, Log, TEXT("INPUT: Started val=%s"),
        *V.ToString());
}

void AMyCharacter::OnDebugTriggered(
    const FInputActionValue& V)
{
    UE_LOG(LogTemp, Log, TEXT("INPUT: Triggered val=%s"),
        *V.ToString());
}

void AMyCharacter::OnDebugOngoing(
    const FInputActionValue& V)
{
    UE_LOG(LogTemp, Log, TEXT("INPUT: Ongoing val=%s"),
        *V.ToString());
}

void AMyCharacter::OnDebugCompleted(
    const FInputActionValue& V)
{
    UE_LOG(LogTemp, Log, TEXT("INPUT: Completed val=%s"),
        *V.ToString());
}

void AMyCharacter::OnDebugCanceled(
    const FInputActionValue& V)
{
    UE_LOG(LogTemp, Log, TEXT("INPUT: Canceled val=%s"),
        *V.ToString());
}

Run this and press your key. If you see no output at all, the IMC is not added or the key is not mapped. If you see Started but not Triggered, your action's trigger is configured as a press trigger (single fire). If you see Triggered every frame, the default hold trigger is active. This tells you exactly which ETriggerEvent to bind to for your use case.

Step 3: Resolve priority conflicts and input consumption. When multiple mapping contexts fight over the same key, you need to manage priorities explicitly. Here is a pattern for swapping contexts cleanly during gameplay mode transitions:

// Switch mapping contexts when entering a vehicle
void AMyCharacter::EnterVehicle(AActor* Vehicle)
{
    APlayerController* PC = Cast<APlayerController>(
        GetController());
    if (!PC) return;

    UEnhancedInputLocalPlayerSubsystem* Subsystem =
        ULocalPlayer::GetSubsystem<
            UEnhancedInputLocalPlayerSubsystem>(
            PC->GetLocalPlayer());
    if (!Subsystem) return;

    // Remove character context, add vehicle context
    Subsystem->RemoveMappingContext(CharacterMappingContext);
    Subsystem->AddMappingContext(VehicleMappingContext, 0);

    UE_LOG(LogTemp, Log,
        TEXT("Switched to vehicle input context"));
}

void AMyCharacter::ExitVehicle()
{
    APlayerController* PC = Cast<APlayerController>(
        GetController());
    if (!PC) return;

    UEnhancedInputLocalPlayerSubsystem* Subsystem =
        ULocalPlayer::GetSubsystem<
            UEnhancedInputLocalPlayerSubsystem>(
            PC->GetLocalPlayer());
    if (!Subsystem) return;

    // Restore character context
    Subsystem->RemoveMappingContext(VehicleMappingContext);
    Subsystem->AddMappingContext(CharacterMappingContext, 0);

    UE_LOG(LogTemp, Log,
        TEXT("Switched to character input context"));
}

If you need both contexts active simultaneously (for example, a shared pause key), use different priority values and set bConsumeInput to false on shared actions. The higher-priority context processes first, and non-consumed inputs pass through to lower-priority contexts.

Related Issues

If Enhanced Input works in PIE but not in packaged builds, check that you have the EnhancedInput plugin enabled in your .uproject file and that the EnhancedInput module is listed in your Build.cs dependencies. If input works initially but stops after a pawn switch (respawn, vehicle exit), the IMC was likely added in the old pawn's BeginPlay and not re-added for the new pawn. Move the AddMappingContext call to the PlayerController's OnPossess to persist across pawn changes.

If you are migrating from the legacy input system, make sure your project's default input class is set to EnhancedPlayerInput in Project Settings under Input. If it is still set to the legacy PlayerInput class, Enhanced Input subsystems will not be created and none of the Enhanced Input pipeline will function.

If nothing fires, the mapping context was never added. That one line of AddMappingContext is required every time.