Quick answer: The most common cause is setting variables in the Event Graph instead of the BlueprintUpdateAnimation event. The Event Graph runs on the game thread and may not sync correctly with the animation evaluation.

Here is how to fix Unreal animation Blueprint not updating. Your character is stuck in the T-pose or locked into the idle animation no matter what input you press. The Animation Blueprint is assigned, the state machine has transitions, and the variables exist — but nothing updates at runtime. This is one of the most common animation issues in Unreal, and it almost always comes down to where you set your animation variables, whether the ABP is actually assigned to the mesh, or a disconnect between your game logic and the animation evaluation thread.

The Symptom

Your character plays the idle animation but never transitions to walk, run, jump, or any other state. Or the character is locked in a T-pose, meaning the Animation Blueprint is not evaluating at all. You set Speed, IsJumping, and other variables from your character Blueprint or C++ class, but the state machine does not respond.

In other cases, animations play once and then stop. A montage triggers but the underlying locomotion blend does not resume after it finishes. Or the character’s animation looks correct in single-player but is stuck on remote clients in a multiplayer game.

Event Graph vs BlueprintUpdateAnimation

The Animation Blueprint has two main graphs: the Event Graph and the Anim Graph. The Event Graph fires standard Blueprint events like BeginPlay and Tick. The Anim Graph contains state machines and blend nodes that produce the final pose.

The critical event for updating animation variables is BlueprintUpdateAnimation (called NativeUpdateAnimation in C++). This event fires every frame during animation evaluation and is the correct place to read game state and set animation variables.

The mistake: Setting animation variables from the character Blueprint via a direct reference, or from the ABP’s Event Graph BeginPlay, or from a custom event that does not fire every frame. These approaches cause variables to be set once or intermittently instead of continuously.

// C++ Animation Instance - the correct way to update variables
void UMyAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
    Super::NativeUpdateAnimation(DeltaSeconds);

    APawn* Owner = TryGetPawnOwner();
    if (!Owner) return;

    // Get velocity from the movement component
    UCharacterMovementComponent* Movement =
        Cast<UCharacterMovementComponent>(
            Owner->GetMovementComponent());

    if (Movement)
    {
        Speed = Movement->Velocity.Size2D();
        bIsFalling = Movement->IsFalling();
        bIsCrouching = Movement->IsCrouching();
    }

    // Get aim rotation for upper body blending
    if (ACharacter* Character = Cast<ACharacter>(Owner))
    {
        FRotator AimRotation = Character->GetBaseAimRotation();
        FRotator ActorRotation = Character->GetActorRotation();
        FRotator Delta = (AimRotation - ActorRotation).GetNormalized();
        AimPitch = Delta.Pitch;
        AimYaw = Delta.Yaw;
    }
}

In the Blueprint version, open your Animation Blueprint, go to the Event Graph, and find the Event Blueprint Update Animation node. Connect your variable-setting logic there. Use Try Get Pawn Owner to get the character reference, then read its movement component values.

Skeletal Mesh Component Assignment

If your character shows a T-pose, the Animation Blueprint may not be assigned to the skeletal mesh at all. Select the Skeletal Mesh Component on your character and check the Anim Class property in the Details panel. It should point to your Animation Blueprint.

// Set the animation class in the character constructor
AMyCharacter::AMyCharacter()
{
    GetMesh()->SetAnimationMode(EAnimationMode::AnimationBlueprint);

    static ConstructorHelpers::FClassFinder<UAnimInstance> AnimBP(
        TEXT("/Game/Characters/Player/ABP_Player"));

    if (AnimBP.Succeeded())
    {
        GetMesh()->SetAnimInstanceClass(AnimBP.Class);
    }
}

Another subtle issue: the Animation Mode on the skeletal mesh might be set to Use Animation Asset instead of Use Animation Blueprint. In this mode, the mesh plays a single animation directly and ignores any assigned ABP entirely.

If you changed the skeleton or the skeletal mesh at some point, the Animation Blueprint might be incompatible. The ABP is compiled against a specific skeleton. If the mesh uses a different skeleton, the ABP will not apply and the character shows a T-pose.

State Machine Transitions

Even when variables update correctly, the state machine might not transition. Open the Anim Graph, double-click the state machine node, and inspect each transition rule.

Threshold mismatches. If your transition from Idle to Walk requires Speed > 100 but your character’s maximum walk speed produces a velocity of 50 units, the transition never fires. Print the Speed value in the ABP to verify what values you actually get.

Missing transitions. Each state needs an explicit transition arrow to every state it can move to. If you have Idle, Walk, Run, and Jump states but no transition from Walk back to Idle, the character gets stuck in Walk once it enters.

Always add bidirectional transitions. For every Idle-to-Walk transition, you need a Walk-to-Idle transition. State machines do not auto-reverse; each direction requires its own rule.

Blend time consuming the transition. If the transition blend time is very long (say 2 seconds) and the variable changes rapidly, the animation appears stuck because it is perpetually blending between states. Reduce the blend time to 0.1–0.3 seconds for responsive gameplay.

// Debug animation variables in C++
void UMyAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
    Super::NativeUpdateAnimation(DeltaSeconds);

    // ... normal update logic ...

    // Debug: draw speed on screen
    if (GEngine)
    {
        GEngine->AddOnScreenDebugMessage(
            -1, 0.f, FColor::Green,
            FString::Printf(TEXT("Speed: %.1f Falling: %d"),
                Speed, bIsFalling));
    }
}

Root Motion Conflicts

Root motion is a common source of animation issues. When an animation has root motion data baked in, the animation drives the character’s movement instead of the Character Movement Component. If both systems try to control movement simultaneously, the result is jittering, sliding, or the character not moving at all.

To use root motion correctly:

Enable root motion on the ABP. In the Animation Blueprint’s Class Defaults, set Root Motion Mode to Root Motion from Montages Only if you only want root motion during montages, or Root Motion from Everything if all animations should use root motion.

Enable root motion on the animation asset. Open the animation sequence or montage. In the Asset Details, check Enable Root Motion. If the animation was not authored with root motion data, enabling this flag has no effect.

// Configure root motion in the character
void AMyCharacter::SetupRootMotion()
{
    UCharacterMovementComponent* MoveComp = GetCharacterMovement();

    // Allow root motion to drive rotation
    MoveComp->bAllowPhysicsRotationDuringAnimRootMotion = true;

    // Use root motion for movement during montages
    GetMesh()->GetAnimInstance()->RootMotionMode =
        ERootMotionMode::RootMotionFromMontagesOnly;
}

Conflict with Character Movement. If you are using root motion for locomotion but the Character Movement Component also applies velocity from input, the character will move at double speed or stutter. When root motion is active, set the Character Movement’s ground speed to zero or disable input-driven velocity.

Multiplayer Variable Replication

In multiplayer, the Animation Blueprint runs independently on each machine. If you set animation variables only on the server, clients will not see the correct animations. The ABP’s NativeUpdateAnimation reads from the local pawn, so you need the pawn’s properties to replicate correctly.

// Replicate the properties that the ABP reads
void AMyCharacter::GetLifetimeReplicatedProps(
    TArray<FLifetimeProperty>& OutLifetimeProps) const
{
    Super::GetLifetimeReplicatedProps(OutLifetimeProps);

    // Movement automatically replicates velocity
    // But custom states need explicit replication
    DOREPLIFETIME(AMyCharacter, bIsAiming);
    DOREPLIFETIME(AMyCharacter, bIsSprinting);
    DOREPLIFETIME_CONDITION(AMyCharacter, AimPitch,
        COND_SkipOwner);
}

The ABP should read these replicated properties from the owning character. Since NativeUpdateAnimation runs on every client, and the character’s replicated properties are synced automatically, the ABP will produce the correct animations on all machines as long as the source properties replicate.

Related Issues

If the Animation Blueprint updates but specific montages do not play, see our guide on Animation Montage not playing. If the character does not move at all despite correct animations, check CharacterMovementComponent not working for input and movement setup issues.

Add on-screen debug messages for Speed and IsFalling in NativeUpdateAnimation. If the values do not change, the problem is in your character code, not the ABP.