Agent skill

Unreal Engine Animation System

by quodsoler in quodsoler/unreal-engine-skills

Reference for writing and debugging Unreal Engine 5.8 animation C++: AnimInstance and proxy, montages, notifies, curves, blend spaces, state machines, linked layers and root motion.

MITAuto-check passedGame Development

Install Unreal Engine Animation System

skills CLI
$ npx skills add quodsoler/unreal-engine-skills --skill ue-animation-system -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install quodsoler/unreal-engine-skills ue-animation-system --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/ue-animation-system .claude/skills/ue-animation-system && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
ue-animation-system
GitHub stars
362
Token cost
~7k tokens
SKILL.md length
1,335 words
Files
3 (incl. references)
Skills in repo
31
Repo updated
First seen
Licence
MIT

At a glance

Reference for writing and debugging Unreal Engine 5.8 animation C++: AnimInstance and proxy, montages, notifies, curves, blend spaces, state machines, linked layers and root motion.

  • Writing a UAnimInstance subclass with a thread-safe update
  • SKILL.md covers Context, AnimInstance and Proxy, Montages and Anim Notifies, plus 8 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md
  • Playing montages and handling their end callbacks

What it does

This skill targets Unreal Engine 5.8, with APIs verified against its headers and older forms listed as deprecated. It covers the runtime animation path in the Engine module: UAnimInstance and FAnimInstanceProxy, montages, anim notifies and notify states, curves, blend spaces, state machines, linked anim layers and root motion, plus the animation plugins that ship with 5.8, among them PoseSearch, MotionWarping, Chooser, IKRig, ControlRig, BlendStack, OptimusCore and UAF. It names the Build.cs modules to depend on, such as Engine and AnimGraphRuntime.

The agent first reads .agents/ue-project-context.md if present for module names, conventions and enabled plugins, then routes the request through a table to the matching section. A key rule for AnimInstance is its two phases: NativeUpdateAnimation on the game thread is safe for reading gameplay state, while NativeThreadSafeUpdateAnimation and blend-tree evaluation run on a worker thread, so gameplay values should be cached on the game thread and only the cached values read on the worker. Reference files cover anim notifies and locomotion setup, and movement or ability topics go to the ue-character-movement and ue-gameplay-abilities skills.

When your agent uses it

  • Writing a UAnimInstance subclass with a thread-safe update
  • Playing montages and handling their end callbacks
  • Setting up anim notifies, curves, blend spaces or linked anim layers
  • Debugging root motion or motion matching in Unreal Engine C++

Example prompts

  • “Create a UAnimInstance subclass that caches speed and direction on the game thread.”
  • “Play a montage from C++ and run code when it ends.”
  • “Switch locomotion sets at runtime using linked anim layers.”

Requirements

  • An Unreal Engine 5.8 C++ project

What it can do on your machine

Read from SKILL.md and the folder at commit f3742d7. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are cpp).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Unreal Engine Animation System loads about 7k tokens when it runs, and up to ~15k if it reads all its reference files. Until then it costs about 178 tokens; SKILL.md has 1,335 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~178
When it runs · the whole SKILL.md, loaded when a task matches
~7k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~15k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from quodsoler/unreal-engine-skills at commit f3742d7, republished under its MIT licence (© quodsoler). 1,335 words, ~6,982 tokens.

Download SKILL.mdSave it as .claude/skills/ue-animation-system/SKILL.md (or your agent's skills folder). This skill also uses 2 other files; get the full folder from GitHub.
name
ue-animation-system
description
Use when writing or debugging Unreal Engine animation C++: AnimInstance subclasses, thread-safe update, FAnimInstanceProxy, montage playback and delegates, anim notifies, animation curves, blend spaces, anim state machines, linked anim layers, root motion. Also use when the user mentions 'UAnimInstance', 'NativeUpdateAnimation', 'NativeThreadSafeUpdateAnimation', 'Montage_Play', 'OnMontageEnded', 'UAnimNotify', 'UAnimNotifyState', 'branching point', 'GetCurveValue', 'blend space', 'AnimGraph', 'LinkAnimClassLayers', 'motion matching', 'motion warping', 'root motion'. For movement and RootMotionSource, see ue-character-movement; for montage-driven abilities, see ue-gameplay-abilities.
metadata.version
2.0.0
metadata.engine
5.8

UE Animation System

Target engine: UE 5.8. APIs below are verified against the 5.8 headers; older forms are listed under "Deprecated — do not use".

Covers the runtime animation path in the Engine module — UAnimInstance, FAnimInstanceProxy, UAnimMontage, UAnimNotify/UAnimNotifyState, curves, blend spaces, anim state machines, linked anim layers and root motion — plus the animation plugins shipped in 5.8 (PoseSearch, MotionWarping, Chooser, IKRig, ControlRig, BlendStack, OptimusCore, UAF). Build.cs: Engine for everything under Runtime/Engine/Classes/Animation, AnimGraphRuntime for the helper anim nodes such as FAnimNode_LayeredBoneBlend; plugin module names are listed per row below.

Context

Read .agents/ue-project-context.md if it exists (module names, conventions, enabled plugins, GAS/networking setup). Do not stop if it is missing.

Identify the area from the request and the codebase. Ask only when two plausible readings would produce different code.

Request is about…Go to
AnimInstance subclass, thread-safe update, proxyAnimInstance and Proxy
Playing/stopping montages, section jumps, end callbacksMontages
Notifies, notify states, branching points, notify timingAnim Notifies
Curve values, morph targets, curve metadataAnimation Curves
Blend spaces, state machines, aim offsets, layered blendsBlend Spaces and State Machines
Linked anim layers, per-mode locomotion swappingLinked Anim Graphs and Layers
Root motion extraction and modesRoot Motion
Motion matching, warping, IK Rig, Control Rig, deformers5.8 Animation Plugins

AnimInstance and Proxy

UAnimInstance (Animation/AnimInstance.h) runs in two phases. Game thread: NativeUpdateAnimation — safe to read gameplay state. Worker thread: NativeThreadSafeUpdateAnimation and blend-tree evaluation. Cache gameplay reads on the game thread; read only those cached values on the worker thread.

Verbatim virtuals (AnimInstance.h:1436-1457 public, :1716-1719 protected):

cpp
virtual void NativeInitializeAnimation();
virtual void NativeUpdateAnimation(float DeltaSeconds);
virtual void NativeThreadSafeUpdateAnimation(float DeltaSeconds);
virtual void NativePostEvaluateAnimation();
virtual void NativeUninitializeAnimation();
virtual void NativeBeginPlay();
virtual FAnimInstanceProxy* CreateAnimInstanceProxy();               // protected
virtual void DestroyAnimInstanceProxy(FAnimInstanceProxy* InProxy);  // protected

FAnimInstanceProxy (Public/Animation/AnimInstanceProxy.h) is the worker-thread data container. Its override points are protected (:603-669):

cpp
virtual void Initialize(UAnimInstance* InAnimInstance);
virtual void PreUpdate(UAnimInstance* InAnimInstance, float DeltaSeconds);
virtual void Update(float DeltaSeconds) {}
virtual bool Evaluate(FPoseContext& Output) { return false; }
virtual void PostUpdate(UAnimInstance* InAnimInstance) const;
virtual void Uninitialize(UAnimInstance* InAnimInstance);

Reach the proxy with the protected templates GetProxyOnGameThread<T>() (:1746) and GetProxyOnAnyThread<T>() (:1769).

cpp
// MyAnimInstance.h
#pragma once

#include "CoreMinimal.h"
#include "Animation/AnimInstance.h"
#include "Animation/AnimInstanceProxy.h"
#include "MyAnimInstance.generated.h"

class ACharacter;
class UCharacterMovementComponent;

USTRUCT()
struct FMyAnimInstanceProxy : public FAnimInstanceProxy
{
    GENERATED_BODY()

    FMyAnimInstanceProxy() = default;
    explicit FMyAnimInstanceProxy(UAnimInstance* InAnimInstance)
        : FAnimInstanceProxy(InAnimInstance) {}

    // Written on the game thread in PreUpdate, read on the worker thread in Update.
    FVector Velocity = FVector::ZeroVector;
    float Speed = 0.f;
    bool bIsFalling = false;

protected:
    virtual void PreUpdate(UAnimInstance* InAnimInstance, float DeltaSeconds) override;
    virtual void Update(float DeltaSeconds) override;
};

UCLASS()
class MYGAME_API UMyAnimInstance : public UAnimInstance
{
    GENERATED_BODY()

public:
    virtual void NativeInitializeAnimation() override;
    virtual void NativeUpdateAnimation(float DeltaSeconds) override;
    virtual void NativeThreadSafeUpdateAnimation(float DeltaSeconds) override;
    virtual void NativeUninitializeAnimation() override;

protected:
    virtual FAnimInstanceProxy* CreateAnimInstanceProxy() override;
    virtual void DestroyAnimInstanceProxy(FAnimInstanceProxy* InProxy) override;

    UPROPERTY(Transient)
    TObjectPtr<ACharacter> OwningCharacter;

    UPROPERTY(Transient)
    TObjectPtr<UCharacterMovementComponent> MovementComp;

    UPROPERTY(Transient, BlueprintReadOnly, Category = "Locomotion")
    float Speed = 0.f;

    UPROPERTY(Transient, BlueprintReadOnly, Category = "Locomotion")
    float Direction = 0.f;

    UPROPERTY(Transient, BlueprintReadOnly, Category = "Locomotion")
    bool bIsInAir = false;
};
cpp
// MyAnimInstance.cpp
#include "MyAnimInstance.h"
#include "GameFramework/Character.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Kismet/KismetMathLibrary.h"

void FMyAnimInstanceProxy::PreUpdate(UAnimInstance* InAnimInstance, float DeltaSeconds)
{
    FAnimInstanceProxy::PreUpdate(InAnimInstance, DeltaSeconds);

    // Game thread: safe to touch the owning actor here.
    if (const ACharacter* Character = Cast<ACharacter>(InAnimInstance->TryGetPawnOwner()))
    {
        const UCharacterMovementComponent* Movement = Character->GetCharacterMovement();
        Velocity = Movement->Velocity;
        bIsFalling = Movement->IsFalling();
    }
}

void FMyAnimInstanceProxy::Update(float DeltaSeconds)
{
    FAnimInstanceProxy::Update(DeltaSeconds);
    Speed = Velocity.Size2D(); // Worker thread: proxy members only.
}

FAnimInstanceProxy* UMyAnimInstance::CreateAnimInstanceProxy()
{
    return new FMyAnimInstanceProxy(this);
}

void UMyAnimInstance::DestroyAnimInstanceProxy(FAnimInstanceProxy* InProxy)
{
    delete InProxy;
}

void UMyAnimInstance::NativeInitializeAnimation()
{
    Super::NativeInitializeAnimation();

    OwningCharacter = Cast<ACharacter>(TryGetPawnOwner());
    if (OwningCharacter)
    {
        MovementComp = OwningCharacter->GetCharacterMovement();
    }
}

void UMyAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
    Super::NativeUpdateAnimation(DeltaSeconds);

    if (!OwningCharacter || !MovementComp)
    {
        return;
    }

    const FVector CurrentVelocity = MovementComp->Velocity;
    Speed = CurrentVelocity.Size2D();
    bIsInAir = MovementComp->IsFalling();

    if (Speed > 3.f)
    {
        Direction = UKismetMathLibrary::NormalizedDeltaRotator(
            CurrentVelocity.ToOrientationRotator(),
            OwningCharacter->GetActorRotation()).Yaw;
    }
}

void UMyAnimInstance::NativeThreadSafeUpdateAnimation(float DeltaSeconds)
{
    Super::NativeThreadSafeUpdateAnimation(DeltaSeconds);

    // Worker thread: read the proxy, never the owning actor. This runs before the
    // proxy's Update(), so read what PreUpdate wrote, not what Update derives.
    const FMyAnimInstanceProxy& Proxy = GetProxyOnAnyThread<FMyAnimInstanceProxy>();
    Speed = Proxy.Velocity.Size2D();
    bIsInAir = Proxy.bIsFalling;
}

void UMyAnimInstance::NativeUninitializeAnimation()
{
    Super::NativeUninitializeAnimation();
    OwningCharacter = nullptr;
    MovementComp = nullptr;
}

Query pending-update state with NeedsUpdate() (AnimInstance.h:512); the bNeedsUpdate member is deprecated.

Montages

Source: Animation/AnimInstance.h, Animation/AnimMontage.h. Verbatim signatures (AnimInstance.h:626-796):

cpp
float Montage_Play(UAnimMontage* MontageToPlay, float InPlayRate = 1.f,
    EMontagePlayReturnType ReturnValueType = EMontagePlayReturnType::MontageLength,
    float InTimeToStartMontageAt = 0.f, bool bStopAllMontages = true);
// Same trailing params; override the asset's blend-in (FMontageBlendSettings adds BlendProfile and
// BlendMode, e.g. EMontageBlendMode::Inertialization)
float Montage_PlayWithBlendIn(UAnimMontage* MontageToPlay, const FAlphaBlendArgs& BlendIn, ...);
float Montage_PlayWithBlendSettings(UAnimMontage* MontageToPlay, const FMontageBlendSettings& BlendInSettings, ...);
void  Montage_Stop(float InBlendOutTime, const UAnimMontage* Montage = NULL);
void  Montage_Pause(const UAnimMontage* Montage = NULL);
void  Montage_Resume(const UAnimMontage* Montage);
void  Montage_JumpToSection(FName SectionName, const UAnimMontage* Montage = NULL);
void  Montage_SetNextSection(FName SectionNameToChange, FName NextSection,
          const UAnimMontage* Montage = NULL);
void  Montage_SetPlayRate(const UAnimMontage* Montage, float NewPlayRate = 1.f);
bool  Montage_IsPlaying(const UAnimMontage* Montage) const;
bool  Montage_IsActive(const UAnimMontage* Montage) const;
bool  Montage_GetIsStopped(const UAnimMontage* Montage) const;
float Montage_GetPosition(const UAnimMontage* Montage) const;
void  Montage_SetPosition(const UAnimMontage* Montage, float NewPosition);
float Montage_GetBlendTime(const UAnimMontage* Montage) const;
float Montage_GetPlayRate(const UAnimMontage* Montage) const;
FName Montage_GetCurrentSection(const UAnimMontage* Montage = NULL) const;
void  Montage_SetEndDelegate(FOnMontageEnded& InOnMontageEnded, UAnimMontage* Montage = NULL);
void  Montage_SetBlendingOutDelegate(FOnMontageBlendingOutStarted& InOnMontageBlendingOut,
          UAnimMontage* Montage = NULL);

EMontagePlayReturnType (AnimInstance.h:70) is MontageLength or Duration. Once blend-out starts, Montage_IsPlaying and Montage_IsActive return false and Montage_GetIsStopped returns true, even though the pose is still blending (Stop() removes the instance from ActiveMontagesMap, AnimInstance.cpp:3709). Use OnMontageBlendingOut / Montage_SetBlendingOutDelegate for blend-out start and OnMontageEnded for the end. Delegate types (AnimInstance.h:79-80) are single-cast:

cpp
DECLARE_DELEGATE_TwoParams(FOnMontageEnded, UAnimMontage*, bool /*bInterrupted*/)
DECLARE_DELEGATE_TwoParams(FOnMontageBlendingOutStarted, UAnimMontage*, bool /*bInterrupted*/)

For broadcast, use the dynamic multicast members OnMontageStarted, OnMontageEnded and OnMontageBlendingOut (:758-770).

cpp
void UMyWeaponComponent::PlayAttackMontage(USkeletalMeshComponent* Mesh, UAnimMontage* Montage)
{
    UAnimInstance* AnimInst = Mesh ? Mesh->GetAnimInstance() : nullptr;
    if (!AnimInst || !Montage)
    {
        return;
    }

    // Play FIRST: the delegate setters resolve the active montage instance,
    // which does not exist until Montage_Play has created it.
    if (AnimInst->Montage_Play(Montage) <= 0.f)
    {
        return;
    }

    FOnMontageEnded EndDelegate;
    EndDelegate.BindUObject(this, &UMyWeaponComponent::OnAttackEnded);
    AnimInst->Montage_SetEndDelegate(EndDelegate, Montage);

    FOnMontageBlendingOutStarted BlendOutDelegate;
    BlendOutDelegate.BindUObject(this, &UMyWeaponComponent::OnAttackBlendingOut);
    AnimInst->Montage_SetBlendingOutDelegate(BlendOutDelegate, Montage);
}

void UMyWeaponComponent::OnAttackEnded(UAnimMontage* Montage, bool bInterrupted) {}
void UMyWeaponComponent::OnAttackBlendingOut(UAnimMontage* Montage, bool bInterrupted) {}

USkeletalMeshComponent (Components/SkeletalMeshComponent.h):

cpp
UAnimInstance* GetAnimInstance() const;                                  // :1111
void PlayAnimation(class UAnimationAsset* NewAnimToPlay, bool bLooping); // :1258
virtual void SetAnimInstanceClass(class UClass* NewClass);               // :1096
void LinkAnimClassLayers(TSubclassOf<UAnimInstance> InClass);            // :1194
void UnlinkAnimClassLayers(TSubclassOf<UAnimInstance> InClass);          // :1205
UAnimInstance* GetLinkedAnimGraphInstanceByTag(FName InTag) const;       // :1160
void SetAnimationMode(EAnimationMode::Type InAnimationMode,
    bool bForceInitAnimScriptInstance = true);                           // :1246

PlayAnimation puts the component in single-node mode; SetAnimInstanceClass puts it in Animation Blueprint mode. Mixing both on one component silently drops one of them.

Multiplayer: with GAS, drive montages through UAbilityTask_PlayMontageAndWait::CreatePlayMontageAndWaitProxy (GameplayAbilities/Public/Abilities/Tasks/AbilityTask_PlayMontageAndWait.h:66) — see ue-gameplay-abilities. Without GAS, replicate the montage choice yourself and call Montage_Play from the replication callback; never call it independently per net role.

Anim Notifies

Source: Animation/AnimNotifies/AnimNotify.h, AnimNotifyState.h. Override these exact signatures:

cpp
// UAnimNotify (AnimNotify.h:85-86, :59)
virtual void Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation,
    const FAnimNotifyEventReference& EventReference);
virtual void BranchingPointNotify(FBranchingPointNotifyPayload& BranchingPointPayload);
FString GetNotifyName() const;  // BlueprintNativeEvent: override GetNotifyName_Implementation

// UAnimNotifyState (AnimNotifyState.h:74-80)
virtual void NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation,
    float TotalDuration, const FAnimNotifyEventReference& EventReference);
virtual void NotifyTick(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation,
    float FrameDeltaTime, const FAnimNotifyEventReference& EventReference);
virtual void NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation,
    const FAnimNotifyEventReference& EventReference);

Received_Notify (AnimNotify.h:62) and Received_NotifyBegin/Received_NotifyTick/Received_NotifyEnd (AnimNotifyState.h:45-51) are BlueprintImplementableEvent entry points — implement them in Blueprint, never override them in C++.

Montage notify timing is per event: FAnimNotifyEvent::MontageTickType (Public/Animation/AnimTypes.h:318) is EMontageNotifyTickType::Queued (fired at the end of the evaluation phase — the header states it is not suitable for changing sections or montage position) or BranchingPoint (fired as encountered, suitable for section changes). A native notify forces the branching-point path by setting bIsNativeBranchingPoint = true in its constructor (AnimNotify.h:123, AnimNotifyState.h:108).

Bind named montage notifies from outside the AnimInstance with OnPlayMontageNotifyBegin / OnPlayMontageNotifyEnd (AnimInstance.h:1820-1823, type FPlayMontageAnimNotifyDelegate).

See references/anim-notify-reference.md for the built-in notify catalog, complete custom notify and notify-state examples, FAnimNotifyEvent fields and linked-instance propagation.

Animation Curves

Curves are addressed by FName in 5.8 — no smart names, no curve UIDs, no mapping lookups.

cpp
// UAnimInstance (AnimInstance.h:1241-1273)
float GetCurveValue(FName CurveName) const;
bool  GetCurveValue(FName CurveName, float& OutValue) const;
bool  GetCurveValueWithDefault(FName CurveName, float DefaultValue, float& OutValue) const;
void  SetMorphTarget(FName MorphTargetName, float Value);

// USkeletalMeshComponent (SkeletalMeshComponent.h:664-667)
bool GetCurveValue(FName CurveName, float DefaultValue, float& Value) const;
const FBlendedHeapCurve& GetAnimCurves() const;

Per-curve flags (does the curve drive a material or a morph target) live in CurveMetaData on the skeleton (Animation/Skeleton.h:387-467): GetCurveMetaData(FName), AddCurveMetaData(FName CurveName, bool bTransact = true), GetCurveMetaDataNames(TArray<FName>& OutNames), SetCurveMetaDataMorphTarget(FName CurveName, bool bOverrideMorphTarget).

Blend Spaces and State Machines

Blend spaces are assets sampled by AnimGraph nodes; drive them from UPROPERTY members the AnimGraph reads.

Asset classHeaderUse
UBlendSpaceAnimation/BlendSpace.h:470Two-axis blend, typically Direction x Speed
UBlendSpace1DAnimation/BlendSpace1D.h:19Single axis, typically Speed
UAimOffsetBlendSpaceAnimation/AimOffsetBlendSpace.h:20Additive aim poses over a base pose

Axis smoothing is FInterpolationParameter (BlendSpace.h:80-110): InterpolationTime, DampingRatio, MaxSpeed, and InterpolationType of type TEnumAsByte<EFilterInterpolationType> — values BSIT_Average, BSIT_Linear, BSIT_Cubic, BSIT_EaseInOut, BSIT_ExponentialDecay, BSIT_SpringDamper (Engine/EngineTypes.h:1356).

Bind native C++ to a compiled state machine from NativeInitializeAnimation (AnimInstance.h:1461-1473):

cpp
// CanStartMoving() and OnLandEntered() are members of UMyAnimInstance.
// DECLARE_DELEGATE_RetVal(bool, FCanTakeTransition)                     AnimInstance.h:118
// DECLARE_DELEGATE_ThreeParams(FOnGraphStateChanged,
//     const struct FAnimNode_StateMachine&, int32, int32)              AnimInstance.h:121
AddNativeTransitionBinding(FName("LocomotionSM"), FName("Idle"), FName("Walk"),
    FCanTakeTransition::CreateUObject(this, &UMyAnimInstance::CanStartMoving),
    FName("IdleToMoving"));

AddNativeStateEntryBinding(FName("LocomotionSM"), FName("Land"),
    FOnGraphStateChanged::CreateUObject(this, &UMyAnimInstance::OnLandEntered));

Query at runtime with GetStateMachineIndex(FName MachineName) (:1202), GetStateMachineInstanceFromName(FName MachineName) (:1191) and GetInstanceStateWeight(int32 MachineIndex, int32 StateIndex) (:1116).

See references/locomotion-setup.md for a full blend space, state machine, layered-blend-per-bone and aim-offset setup.

Linked Anim Graphs and Layers

Source: Animation/AnimNode_LinkedAnimGraph.h, Animation/AnimNode_LinkedAnimLayer.h.

cpp
// UAnimInstance (AnimInstance.h:850-910)
virtual void LinkAnimClassLayers(TSubclassOf<UAnimInstance> InClass);
virtual void UnlinkAnimClassLayers(TSubclassOf<UAnimInstance> InClass);
UAnimInstance* GetLinkedAnimLayerInstanceByClass(TSubclassOf<UAnimInstance> InClass,
    bool bCheckForChildClass = false) const;
void LinkAnimGraphByTag(FName InTag, TSubclassOf<UAnimInstance> InClass);
UAnimInstance* GetLinkedAnimGraphInstanceByTag(FName InTag) const;

LinkAnimClassLayers(nullptr) restores the default layer implementations. Notify flow across linked instances is set by SetReceiveNotifiesFromLinkedInstances(bool bSet) and SetPropagateNotifiesToLinkedInstances(bool bSet) (:523-531), or per node by bReceiveNotifiesFromLinkedInstances / bPropagateNotifiesToLinkedInstances (AnimNode_LinkedAnimGraph.h:76-80). SetUseMainInstanceMontageEvaluationData(bool bSet) (:537) makes linked layers share the main instance's montage evaluation.

Blend the swap with PendingBlendInDuration / PendingBlendOutDuration on the linked node (AnimNode_LinkedAnimGraph.h:60-67), or request one from code:

cpp
// AnimInstance.h:1006
AnimInst->RequestSlotGroupInertialization(FName("DefaultGroup"), 0.2f);

Root Motion

ERootMotionMode::Type (Animation/AnimEnums.h:27-42): NoRootMotionExtraction, IgnoreRootMotion, RootMotionFromEverything, RootMotionFromMontagesOnly. The header marks RootMotionFromEverything as unsuitable for networked multiplayer and RootMotionFromMontagesOnly as the networked choice.

cpp
// AnimInstance.h:372, :1066, :1662
TEnumAsByte<ERootMotionMode::Type> RootMotionMode;   // UPROPERTY(EditDefaultsOnly)
void SetRootMotionMode(TEnumAsByte<ERootMotionMode::Type> Value);
FRootMotionMovementParams ConsumeExtractedRootMotion(float Alpha);

// Suppress root motion for part of a montage (AnimMontage.h:562-564)
if (FAnimMontageInstance* Inst = AnimInst->GetActiveInstanceForMontage(Montage))
{
    Inst->PushDisableRootMotion();
    // ... later ...
    Inst->PopDisableRootMotion();
}

Montage root motion and RootMotionSource are separate systems: the montage path feeds the pose-derived delta into the movement component, while RootMotionSource applies scripted movement with no animation attached. Networked prediction, correction and bAllowPhysicsRotationDuringAnimRootMotion (GameFramework/CharacterMovementComponent.h:1083) belong to ue-character-movement.

Show full SKILL.md (529 more words)Show less

5.8 Animation Plugins

Each is disabled by default in the .uproject unless noted; add the module to Build.cs when you use its types.

Plugin / module5.8 maturityKey types and headers
PoseSearchproductionFAnimNode_MotionMatching (PoseSearch/AnimNode_MotionMatching.h:18), UPoseSearchDatabase (PoseSearch/PoseSearchDatabase.h:502); trajectories are FTransformTrajectorySample (Runtime/Engine/Public/Animation/TrajectoryTypes.h:18)
ChooserproductionUChooserTable (Chooser.h:22), UChooserFunctionLibrary (ChooserFunctionLibrary.h:18) — data-driven asset selection, commonly feeding motion matching
MotionWarpingBeta in 5.8UMotionWarpingComponent (MotionWarpingComponent.h:100), URootMotionModifier (RootMotionModifier.h:71); rotation offsets use AdditionalRotationOffset (RootMotionModifier.h:407)
IKRigproduction, enabled by defaultUIKRigDefinition (Rig/IKRigDefinition.h:206), UIKRetargeter (Retargeter/IKRetargeter.h:70) — runtime IK solving and animation retargeting
ControlRigproduction, enabled by defaultUControlRig (ControlRig.h:63), FAnimNode_ControlRig (AnimNode_ControlRig.h:21) — procedural rigs evaluated inside the AnimGraph
BlendStackproductionFAnimNode_BlendStack and FAnimNode_BlendStack_Standalone (BlendStack/AnimNode_BlendStack.h:272,150) — the blend stack motion matching is built on
OptimusCore (Deformer Graph)Beta in 5.8UOptimusDeformer (OptimusDeformer.h:132) — GPU mesh deformation graphs
UAFExperimental in 5.8Plugins/Experimental/UAF/UAF, module UAF: UUAFRigVMAsset (AnimNextRigVMAsset.h:61), UUAFComponent (Component/AnimNextComponent.h:77) — the successor animation framework

Deprecated — do not use

Do not emitUse in 5.8Source
FSmartName, FSmartNameMapping, FSmartNameContainerplain FName curve namesUE_DEPRECATED(5.8) in Animation/SmartName.h:20,80,121
Skeleton smart-name curve tablesCurveMetaData accessors on USkeletonUE_DEPRECATED(5.7) in Animation/Skeleton.h:505
AnimCurveUIDFName curve namesUE_DEPRECATED(5.7) in Animation/Skeleton.h:384
UAnimInstance::bNeedsUpdateNeedsUpdate()UE_DEPRECATED(5.7) in Animation/AnimInstance.h:389
USkeletalMeshComponent::SetAnimClassSetAnimInstanceClassUE_DEPRECATED(5.5) in Components/SkeletalMeshComponent.h:1084
USkeletalMeshComponent::AnimCurves memberGetAnimCurves() / GetCurveValue()UE_DEPRECATED(5.6) in Components/SkeletalMeshComponent.h:470
UAnimSequence::RetargetSourceAsset memberGetRetargetSourceAsset / SetRetargetSourceAssetUE_DEPRECATED(5.5) in Animation/AnimSequence.h:305
FTrajectorySampleFTransformTrajectorySampleUE_DEPRECATED(5.6) in Public/Animation/MotionTrajectoryTypes.h:10
FPoseSearchQueryTrajectorySampleFTransformTrajectorySampleUE_DEPRECATED(5.6) in PoseSearch/PoseSearchTrajectoryTypes.h:16
FPoseSearchDatabaseSequence, FPoseSearchDatabaseBlendSpaceFPoseSearchDatabaseAnimationAssetUE_DEPRECATED(5.7) in PoseSearch/PoseSearchDatabase.h:228
EMotionWarpRotationType::OppositeDefault / OppositeFacingAdditionalRotationOffsetUE_DEPRECATED(5.8) in MotionWarping/RootMotionModifier.h:309,312
FAnimInstanceProxy::GetSlotInertializationRequestGetSlotInertializationRequestDataUE_DEPRECATED(5.5) in Public/Animation/AnimInstanceProxy.h:444
SetSubInstanceClassByTag, GetSubInstanceByTagLinkAnimGraphByTag, GetLinkedAnimGraphInstanceByTagUE_DEPRECATED(4.24) in Animation/AnimInstance.h:860,845
SetLayerOverlay, ClearLayerOverlayLinkAnimClassLayers, UnlinkAnimClassLayersUE_DEPRECATED(4.24) in Animation/AnimInstance.h:868,880
GetLayerSubInstanceByClassGetLinkedAnimLayerInstanceByClassUE_DEPRECATED(4.24) in Animation/AnimInstance.h:906

Common Mistakes

Touching the owning actor in NativeThreadSafeUpdateAnimation: that function runs on a worker thread, so TryGetPawnOwner(), component queries and traces are unsafe there. Cache what you need in NativeUpdateAnimation or in FAnimInstanceProxy::PreUpdate, and read only those members on the worker thread.

Binding montage delegates before Montage_Play: Montage_SetEndDelegate and Montage_SetBlendingOutDelegate resolve the active montage instance, which does not exist yet. Call Montage_Play first, check the return value is greater than zero, then bind.

Overriding Received_Notify in C++: it is a BlueprintImplementableEvent. Override Notify(USkeletalMeshComponent*, UAnimSequenceBase*, const FAnimNotifyEventReference&) instead.

Jumping sections from a queued notify: queued notifies fire after the evaluation phase, so Montage_JumpToSection from one lands a frame late. Set bIsNativeBranchingPoint = true and override BranchingPointNotify for section control.

Looking curves up by smart name or UID: FSmartName, FSmartNameMapping and AnimCurveUID are deprecated. Pass FName to GetCurveValue and keep per-curve flags in CurveMetaData.

Declaring a proxy override public: Initialize, PreUpdate, Update, Evaluate and PostUpdate are protected on FAnimInstanceProxy, and so are CreateAnimInstanceProxy / DestroyAnimInstanceProxy on UAnimInstance. Keep the access level or the override will not compile.

Skipping the base call: every Native* override calls its Super:: form, and every proxy override calls FAnimInstanceProxy::<Name>; the base implementations drive montage ticking, notify queues and proxy bookkeeping.

  • ue-character-movement — UCharacterMovementComponent, RootMotionSource, networked root motion prediction and correction.
  • ue-gameplay-abilities — UAbilityTask_PlayMontageAndWait, GAS montage replication, ability-driven animation.
  • ue-actor-component-architecture — USkeletalMeshComponent setup, attachment, component tick ordering.
  • ue-sequencer-cinematics — Level Sequence animation tracks and cinematic playback on skeletal meshes.
  • ue-mass-entity — crowd-scale animation through Mass representation instead of per-actor AnimInstances.
  • ue-cpp-foundations — delegate binding, UPROPERTY/UFUNCTION specifiers, TObjectPtr.
  • ue-niagara-effects — Niagara systems spawned from notifies and skeletal mesh data interfaces.
  • ue-audio-system — UAudioComponent, MetaSounds, submixes, attenuation and concurrency
  • ue-mover — the Mover plugin: movement modes, layered moves and rollback networking

© quodsoler, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 2 other files (references) in skills/ue-animation-system of quodsoler/unreal-engine-skills.

  • SKILL.md
  • references/anim-notify-reference.md
  • references/locomotion-setup.md

Open the folder on GitHubat commit f3742d7

Compare with similar skills

Unreal Engine Animation System next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Unreal Engine Animation System compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Unreal Engine Animation System this skillquodsoler/unreal-engine-skills362—~7kAutomated safety check: PassMIT
Debugging CodeJetBrains/skills3661 repos~3.8kAutomated safety check: PassNone
Unreal Engine MCPEpicGames/unreal-engine-skills-for-claude-code-plugin338—~1.8kAutomated safety check: PassMIT
Unreal Live CodingItalink/UnrealClientProtocol127—~1kAutomated safety check: PassMIT
Unreal Cpp Gameplayukanwat/overtime3871 repos~1.5kAutomated safety check: PassApache-2.0
Unreal Enhanced Inputukanwat/overtime3871 repos~1.5kAutomated safety check: PassApache-2.0

Similar skills

  • Debugging Code

    JetBrains/skills

    Official

    A skill your agent uses for debugger-driven runtime root-cause analysis in Rider-supported solutions and projects, including .NET/C, F, VB, C++, Unity, Unreal Engine, and other GameDev or…

    366 GitHub starsUsed in 1 repo~3.8k tokens
    Game DevelopmentAuto-check passed
  • Unreal Engine MCP

    EpicGames/unreal-engine-skills-for-claude-code-plugin

    Drives a live Unreal Editor through the unreal-mcp server: spawn actors, edit Blueprints, materials and sequences, change properties and trigger Live Coding.

    338 GitHub stars~1.8k tokensUpdated 23 days ago
    Game DevelopmentAuto-check passed
  • Unreal Live Coding

    Italink/UnrealClientProtocol

    Trigger Live Coding compilation via UCP. An agent skill from Italink/UnrealClientProtocol.

    127 GitHub stars~1k tokensUpdated 1 mo ago
    Game DevelopmentAuto-check passed
  • Unreal Cpp Gameplay

    ukanwat/overtime

    Write Unreal Engine 5 C++ gameplay code: the UCLASS/UPROPERTY/UFUNCTION reflection macros, the Gameplay Framework (GameMode, Pawn, Character, PlayerController, Actor components), and the module…

    387 GitHub starsUsed in 1 repo~1.5k tokens
    Game DevelopmentAuto-check passed
  • Unreal Enhanced Input

    ukanwat/overtime

    Set up player input in Unreal Engine 5 with Enhanced Input: Input Actions, Input Mapping Contexts, modifiers and triggers, adding the mapping context, and binding actions by ETriggerEvent.

    387 GitHub starsUsed in 1 repo~1.5k tokens
    Game DevelopmentAuto-check passed
  • Unreal Niagara

    ukanwat/overtime

    Create and control VFX in Unreal Engine 5 with Niagara: systems and emitters, modules and the spawn/update stages, exposed User parameters, and spawning or driving effects from Blueprints or C++.

    387 GitHub starsUsed in 1 repo~1.5k tokens
    Game DevelopmentAuto-check passed

More from quodsoler/unreal-engine-skills

All 31 skills in this repo
  • Unreal Actor-Component Architecture

    quodsoler/unreal-engine-skills

    Unreal Engine C++ guidance for AActor and UActorComponent: lifecycle hooks, spawning, component creation and attachment, ticking, interfaces and composition.

    362 GitHub stars~7.5k tokensUpdated 11 days ago
    Auto-check passed
  • Unreal Engine AI and Navigation

    quodsoler/unreal-engine-skills

    Guides Unreal Engine C++ AI work across AI controllers, behavior trees, blackboards, perception, navmesh pathfinding, EQS and Smart Objects.

    362 GitHub stars~8.9k tokensUpdated 11 days ago
    Auto-check passed
  • Unreal Engine Async and Threading

    quodsoler/unreal-engine-skills

    Picks and applies the right Unreal Engine C++ concurrency API, from UE::Tasks and FPipe to ParallelFor, FRunnable, locks and timers, with game-thread safety rules.

    362 GitHub stars~8k tokensUpdated 11 days ago
    Auto-check passed
  • Ue Audio System

    quodsoler/unreal-engine-skills

    A skill your agent uses when playing, mixing or debugging sound in Unreal Engine — one-shot SFX, looping ambience, music, dialogue or procedural audio.

    362 GitHub stars~7.9k tokensUpdated 11 days ago
    Auto-check passed
  • Unreal Blueprint and C++ Interop

    quodsoler/unreal-engine-skills

    Reference for exposing Unreal Engine C++ to Blueprint and calling Blueprint from C++, covering UFUNCTION and UPROPERTY specifiers, latent and async nodes, and interfaces.

    362 GitHub stars~7.8k tokensUpdated 11 days ago
    Auto-check passed
  • Unreal Character Movement Component

    quodsoler/unreal-engine-skills

    Reference for writing and debugging UCharacterMovementComponent code in Unreal Engine C++: custom movement modes, floor detection, root motion, prediction and gravity.

    362 GitHub stars~8.5k tokensUpdated 11 days ago
    Auto-check passed

Questions about Unreal Engine Animation System

What does Unreal Engine Animation System do?

Reference for writing and debugging Unreal Engine 5.8 animation C++: AnimInstance and proxy, montages, notifies, curves, blend spaces, state machines, linked layers and root motion. 8, with APIs verified against its headers and older forms listed as deprecated.8, among them PoseSearch, MotionWarping, Chooser, IKRig, ControlRig, BlendStack, OptimusCore and UAF.

When should I use Unreal Engine Animation System?

Unreal Engine Animation System fits situations like: writing a UAnimInstance subclass with a thread-safe update; playing montages and handling their end callbacks; setting up anim notifies, curves, blend spaces or linked anim layers; debugging root motion or motion matching in Unreal Engine C++.

How do I install Unreal Engine Animation System in Claude Code?

Run `npx skills add quodsoler/unreal-engine-skills --skill ue-animation-system -a claude-code`. Or copy the skill folder (skills/ue-animation-system in quodsoler/unreal-engine-skills) into .claude/skills/ue-animation-system in your project. Claude Code loads it when a task matches its description.

How do I install Unreal Engine Animation System in Codex?

Run `npx skills add quodsoler/unreal-engine-skills --skill ue-animation-system -a codex`. Or copy the skill folder (skills/ue-animation-system in quodsoler/unreal-engine-skills) into .agents/skills/ue-animation-system in your project. Codex loads it when a task matches its description.

Can I use Unreal Engine Animation System in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add quodsoler/unreal-engine-skills --skill ue-animation-system -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ue-animation-system, .gemini/skills/ue-animation-system, .github/skills/ue-animation-system and .opencode/skills/ue-animation-system in your project.

What does Unreal Engine Animation System need to run?

SKILL.md names no scripts, command-line tools or credentials: Unreal Engine Animation System is instructions for the agent only. Our summary lists: An Unreal Engine 5.8 C++ project.

Does Unreal Engine Animation System access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Unreal Engine Animation System safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Unreal Engine Animation System use?

Unreal Engine Animation System is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Unreal Engine Animation System use?

About 7k tokens (SKILL.md is roughly 28k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 8.4k tokens, read only when the agent opens those files.

What are the alternatives to Unreal Engine Animation System?

Skills that share tags, products or a category with Unreal Engine Animation System: Debugging Code (JetBrains/skills, 366 stars), Unreal Engine MCP (EpicGames/unreal-engine-skills-for-claude-code-plugin, 338 stars), Unreal Live Coding (Italink/UnrealClientProtocol, 127 stars) and Unreal Cpp Gameplay (ukanwat/overtime, 387 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Unreal Engine Animation System?

quodsoler (a GitHub user) maintains it in quodsoler/unreal-engine-skills, which has 362 GitHub stars. The repository holds 31 skills in this directory. The repository was last updated on September 28, 2026.

Source: quodsoler/unreal-engine-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.