Quick answer: The most common cause is not calling AddMovementInput in your Tick or input handler. CharacterMovementComponent requires you to feed it a direction and scale each frame. Without AddMovementInput calls, the component has no movement request to process, even if input bindings are set up correctly.

Here is how to fix Unreal character movement not working. You placed a Character in your level, gave it a CharacterMovementComponent, set up input actions, and pressed Play — but the character stands completely still. No movement, no falling, no response to WASD or gamepad input whatsoever. The frustrating part is that nothing in the Output Log suggests anything is wrong. Here is how to diagnose and fix it.

The Symptom

Your ACharacter subclass is in the world with a valid capsule component and a CharacterMovementComponent. You have input actions configured in the project settings or via Enhanced Input assets. You press movement keys at runtime and the character does not budge. The camera may rotate if you have look input wired up, but the character stays planted at its spawn location.

In some variations, the character might spawn and immediately fall through the floor, float in the air without gravity, or move at an impossibly slow speed that looks like it is stationary. All of these stem from movement component misconfiguration rather than input issues.

You might also see this with AI-controlled characters where MoveToLocation or MoveToActor returns success but the pawn does not physically move across the level.

What Causes This

1. AddMovementInput is never called. This is the most common cause. CharacterMovementComponent does not read raw input directly. It waits for your code to call AddMovementInput() with a world direction and scale value each frame. If your input binding calls a function that does not call AddMovementInput, or if the binding itself is broken, the component never receives a movement request.

2. Enhanced Input mapping context not added. With Unreal 5.x and the Enhanced Input system, input actions only work if you add the Input Mapping Context to the player's Enhanced Input Local Player Subsystem at runtime. Forgetting this step means your input actions exist but are never processed, so your bound handlers never fire.

3. Movement mode is wrong. The CharacterMovementComponent has several movement modes: Walking, Falling, Swimming, Flying, and Custom. If the mode is set to None or an unexpected mode, the component may refuse to process movement input. This happens when code or a Blueprint accidentally sets the mode, or when the character spawns in a volume that changes the mode.

4. No NavMesh for AI movement. If you are using the AI MoveTo functions, the character requires a valid NavMesh that covers the destination. Without one, the pathfinding query fails and the AI controller never issues movement commands. The character stays still even though MoveToLocation returns a seemingly valid result.

The Fix

Step 1: Set up Enhanced Input bindings and call AddMovementInput. This is the complete setup for a character that moves with WASD using the Enhanced Input system.

// MyCharacter.h
UPROPERTY(EditAnywhere, Category = "Input")
class UInputMappingContext* DefaultMappingContext;

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

void Move(const FInputActionValue& Value);

// MyCharacter.cpp - BeginPlay
void AMyCharacter::BeginPlay()
{
    Super::BeginPlay();

    // Add the mapping context so input actions are processed
    APlayerController* PC = Cast<APlayerController>(GetController());
    if (PC)
    {
        UEnhancedInputLocalPlayerSubsystem* Subsystem =
            ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(
                PC->GetLocalPlayer());
        if (Subsystem)
        {
            Subsystem->AddMappingContext(DefaultMappingContext, 0);
        }
    }
}

Step 2: Bind the action and convert input to world movement.

// SetupPlayerInputComponent
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
    UEnhancedInputComponent* EIC =
        Cast<UEnhancedInputComponent>(PlayerInputComponent);
    if (EIC)
    {
        EIC->BindAction(MoveAction, ETriggerEvent::Triggered,
            this, &AMyCharacter::Move);
    }
}

void AMyCharacter::Move(const FInputActionValue& Value)
{
    FVector2D Axis = Value.Get<FVector2D>();

    // Get forward/right vectors relative to controller rotation
    const FRotator YawRotation(0, Controller->GetControlRotation().Yaw, 0);
    const FVector ForwardDir = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
    const FVector RightDir = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);

    // This is the critical call that feeds the movement component
    AddMovementInput(ForwardDir, Axis.Y);
    AddMovementInput(RightDir, Axis.X);
}

Step 3: Verify movement component settings. Log the movement state to identify misconfigurations.

// Add to Tick or BeginPlay for diagnostics
UCharacterMovementComponent* CMC = GetCharacterMovement();
UE_LOG(LogTemp, Warning, TEXT("Mode: %d, Speed: %.1f, Gravity: %.1f"),
    (int)CMC->MovementMode, CMC->MaxWalkSpeed, CMC->GravityScale);

// Fix common defaults
CMC->MaxWalkSpeed = 600.f;   // Default is 600
CMC->GravityScale = 1.f;     // 0 means no gravity
CMC->SetMovementMode(MOVE_Walking);

Related Issues

If your character moves but animations do not play, check our guide on animation montages not playing. If movement works but event dispatchers that should fire on movement events are silent, see Blueprint events not firing for binding and replication troubleshooting.

No AddMovementInput call, no movement. The component does not read input on its own.