V4 is one game that has to animate like six. A tactical-FPS operator leaning out of cover, a social-stealth assassin dragging a body, a real-time-tactics specialist holding a squad pose, a Wukong-class action-RPG hero chaining a combo into a transformation morph, an RTS unit cycling work-and-march loops, and a 2D run-and-gun pilot flipping through Paper2D frames — all of them are meant to ride the same modern UE5 animation stack: AnimBlueprints with per-cell sub-states, Motion Matching for traversal-heavy areas, IK retargeting through one IKRig per body archetype, Motion Warping for contact alignment, and the MetaHuman pipeline for principal faces. The organizing idea mirrors V4's GAS layer (./gas-layout.md): share one skeleton and one master AnimBlueprint per body family, then specialize with cell-specific slots and state machines so a costume or a verb is an addition, not a fork.
What actually lives in the repo today is the contract and validation layer
for that stack, plus two genuinely runtime helpers. The V4Animation module is
small and honest: a set of USTRUCT specs, two data-asset manifests that build
and self-validate the required AnimBlueprints / motion-matching datasets /
IKRigs / retargeters, a real hit-reaction-and-wake-up chooser table that
runs its lookups in C++, and a motion-warping handler that calls straight
into Unreal's MotionWarping plugin. Unlike V2's fighting-game animation chapter
— which was pure config behind unlinked plugins — V4's module links the real
animation plugins and makes a real plugin call, but the heavy authored
content (compiled AnimBlueprints, pose-search databases, IKRig assets, montages,
MetaHuman heads) is not yet present as binary .uasset. This page is part
of the Combat, Character & Input Systems group; the section hub is
../V4_ARCHITECTURE.md.
What ships, honestly#
The V4Animation module is real C++ that builds and is tested, but it is a
specification-and-runtime-helpers layer, not the authored animation graph. Five
honest qualifications, so the rest of the page reads at face value:
-
The module links the real animation plugins.
V4Animation.Build.cs:9-22addsAnimGraphRuntime,PoseSearch,Mover,Chooser, andMotionWarpingto its public dependencies — alongsideCore,CoreUObject,Engine, andV4Core. This is a step beyond V2, whose animation module linked none of them. But linking is not calling: only one of those plugins (MotionWarping) is actually invoked from C++ today. -
Two of the four classes are validated config; two are runtime.
UV4AnimBlueprintManifestandUV4AnimationPipelineManifestareUDataAssets that describe the required AnimBlueprints and the motion-matching / IKRig / retarget / MetaHuman pipeline and then validate that description.UV4AnimationChooserTableandUV4MotionWarpingHandlerdo real work at runtime — a data-driven decision and a real plugin call, respectively. -
There are zero binary
.uassetanimation assets.V4/ue/Contentholds no.uassetfiles at all; the animation content directory (V4/ue/Content/V4Animation) instead ships 47*.uasset.v4asset.jsondescriptors across eight subdirectories (AnimationBlueprints,Choosers,IKRig,MetaHuman,Mocap,MotionMatching,Retargeters,Takedowns). These JSON files mirror — and slightly extend — the C++ specs (theABP_Operator_Masterdescriptor lists aTakedownslot the C++ default does not), but no skeleton, AnimBlueprint, pose-search database, IKRig, or montage binary exists for the soft names to resolve to. -
The animation classes are not yet wired into gameplay. Outside the module itself, the only consumer of
UV4AnimationChooserTable,UV4MotionWarpingHandler,UV4AnimationPipelineManifest, andUV4AnimBlueprintManifestis the automation spec (V4Tests/Private/V4AnimationTests/AnimBPCompileSpec.cpp). No ability, pawn, or combat component instantiates them in the live path yet. They are shippable units awaiting an integration call site. -
There is no AnimNotifyState bridge, and no montages. V2 turned montage timelines into combat data through real
UAnimNotifyStatesubclasses (hitbox / armor / cancel-window). V4 has none of those inV4Animation, and no montage.uassetanywhere. The frame-accurate combat windows the GAS verbs depend on — dodge i-frames, the parry window — are computed in combat C++ components inV4ActionRPG, not driven by animation notifies (see How the pipeline connects).
Everything below is real where it cites a function and a line; where it names an authored asset or a plugin runtime, that is the specified-but-pending part.
The module surface#
V4Animation is four public classes over V4AnimationTypes.h, which defines
the shared enums and structs. The enums are the vocabulary the rest of the
module keys on: EV4MotionWarpContext (Breach / Throw / Finisher,
V4AnimationTypes.h:8), EV4HitReactionType
(Light / Heavy / Knockdown / Death, :16), and EV4WakeupType
(BackRise / RollLeft / RollRight / KipUp, :25). The cell identity itself is
shared from core — EV4RulesetCell (V4Core/Public/V4CellState.h:7:
None, Tactical, Stealth, Tactics, ActionRPG, RTS, Arcade) — so the
motion-matching datasets can be keyed by the same join key the GAS layer uses.
The dashed edges are the two runtime helpers; the solid path (AnimBP → source → retarget → mesh) is the authored graph that today exists as JSON descriptors and validated specs rather than compiled assets.
AnimBlueprint layout — masters, slots, and state machines#
The AnimBlueprint design is captured by FV4AnimBlueprintSpec
(V4AnimationTypes.h:94): an AssetName, a list of RequiredSlots (montage
slot names), a list of RequiredStateMachines, and a bUsesFlipbooks flag for
the 2D exception. UV4AnimBlueprintManifest::LoadDefaultSpecs
(V4AnimBlueprintManifest.cpp:32) builds ten master AnimBlueprints — more
than the architecture monolith's six, because it also covers hostiles and
vehicles:
| AnimBlueprint | Required slots | State machines |
|---|---|---|
ABP_Operator_Master |
Cover, ADS, Crouch, Prone, BodyDrag | Locomotion, Weapon, Injured |
ABP_RTSUnit_Master |
FactionOverride | UnitLocomotion, Work |
ABP_RTST_Specialist_Master |
SquadPose, CommandPose | SpecialistLocomotion, TacticalAction |
ABP_ARPGHero_Master |
Combo, Parry, Dodge, Transformation | CombatCombo, TransformationMorph |
ABP_NPC_Civilian |
Panic, DropAndCover | Idle, PanicRun |
ABP_2DOperator |
Flipbook, Weapon | ContraCellFlipbook (flipbooks) |
ABP_NPC_Hostile_FPS |
Combat, Suppression, Vault | HostileFPSLocomotion, WeaponResponse |
ABP_NPC_Hostile_RTST |
Patrol, Alert, ConeAim | RTSTPatrol, HostileTacticalAction |
ABP_Vehicle_Driver |
VehicleSeat, Steering, ExitVehicle | DriverPose, VehicleTransition |
ABP_Vehicle_Gunner |
DoorGunner, AimOffset, Reload | GunnerPose, MountedWeapon |
The pattern is the cell-sharing thesis made concrete: each entry is a master
graph for one body/role family, and the cell verbs hang off it as named
montage slots (cover-lean, ADS, body-drag, the ARPG combo/parry/dodge/morph)
layered over a small set of state machines (always a locomotion machine plus
one or two role machines). ABP_2DOperator is the deliberate outlier — its sole
state machine is ContraCellFlipbook and it is the only spec with
bUsesFlipbooks = true, encoding that the Contra cell is Paper2D rather than
skeletal.
ValidateRequiredSpecs (:78) is a genuine self-check, not a tautology: it
constructs a fresh required manifest, then for every required spec confirms the
actual manifest contains it, contains all of its required slots and state
machines (ContainsAllNames, :5), and matches the flipbook flag exactly. A
manifest that dropped the BodyDrag slot or flipped a flipbook flag fails. The
automation spec asserts the count is 10 and spot-checks that
ABP_Operator_Master carries BodyDrag and ABP_Vehicle_Gunner carries
DoorGunner (AnimBPCompileSpec.cpp:27-51).
Blending — motion matching, root motion, and shared skeletons#
UV4AnimationPipelineManifest (V4AnimationPipelineManifest.h:9) is the larger
data asset, aggregating the motion-matching datasets, IKRigs, retargeters, and
MetaHuman pipeline that produce a blended pose. LoadDefaultPipeline
(V4AnimationPipelineManifest.cpp:86) populates them with domain-tuned
defaults.
Motion matching. Six FV4MotionMatchingDatasetSpec
(V4AnimationTypes.h:112) datasets, one per playable cell, each carrying the
architecture's promised parameters: PoseHistoryFrames = 8,
TrajectoryMilliseconds = 600, and four distance-field cost weights —
StanceCost, VelocityCost, AccelerationCost, FacingCost — plus the
BakedArchetypes the dataset is trained for. The defaults are not uniform: the
Stealth Hitman-sandbox dataset raises StanceCost to 1.25 and FacingCost to
1.0 (stealth cares about stance and which way you face), while the Wukong
open-area ARPG dataset raises VelocityCost to 1.15 (:93-120). The intent
matches the monolith: motion matching is reserved for traversal-heavy cells
(Hitman sandbox, Wukong open areas); FPS and RTS use the standard root-motion
AnimBP path, which is why the diagram branches on locomotion source.
IK retargeting and shared skeletons. Five FV4IKRigSpec
(V4AnimationTypes.h:145) entries cover the body archetypes — Adult Male, Adult
Female, Adolescent, Animal Quadruped, Animal Biped — each declaring its IK
chains. Bipeds share a six-chain set
(Root, Spine, LeftArm, RightArm, LeftLeg, RightLeg, V4BipedChains() at
:8); the quadruped swaps in four legs (V4QuadrupedChains() at :20). Two
FV4RetargeterSpec (:160) entries retarget MetaHuman → Operator and
Mixamo → Operator, both onto the shared six biped chains. This is the
one-skeleton-per-archetype rule: there is no per-operator skeleton, costume
and cosmetic differences ride on the shared rig, and animation authored against
MetaHuman or Mixamo is retargeted in.
MetaHuman pipeline. FV4MetaHumanPipelineSpec (V4AnimationTypes.h:178) is
the most config-shaped piece — five fields, four booleans plus a
LipSyncProvider name. LoadDefaultPipeline sets all four configured and names
the provider OVRMetaSounds (:133-137). These are capability flags (Creator
workflow, Animator facial mocap, Live Link Face, lip-sync runtime) declaring
intent, not a wired runtime — there is no Live Link or MetaHuman runtime call
in this module.
ValidatePipeline (:140) is the substantive part. For each of the six
required cells it finds the dataset, then asserts PoseHistoryFrames == 8, the
trajectory is within tolerance of 600 ms, every distance-field cost is
strictly positive, and at least one baked archetype is present. For each
archetype it confirms an IKRig exists and contains every required chain; for
each retarget source it confirms a → Operator retargeter with the full biped
chain set; and it fails if any MetaHuman flag is unset or the provider is
None. The automation spec drives this end-to-end and pins the headline numbers
— 6 datasets, 5 IKRigs, 2 retargeters, the Wukong dataset baked for Hero
at depth 8 and 600 ms, and the OVRMetaSounds provider
(AnimBPCompileSpec.cpp:60-88).
The runtime decision: hit-reaction and wake-up choosers#
UV4AnimationChooserTable (V4AnimationChooserTable.h:9) is where the module
stops describing and starts deciding. It models UE5's Chooser-table concept as a
small data-driven matcher with two real lookup functions.
LoadDefaultRows (V4AnimationChooserTable.cpp:3) seeds two row tables.
Hit-reaction rows are {MinDamage, MaxDamage, bRequiresHeadshot, Reaction}: a
headshot row (0–999, headshot-only → Death) first, then 0–20 → Light,
20–60 → Heavy, 60–99 → Knockdown. Wake-up rows are
{MinDownTime, MaxDownTime, bRequiresThreatNearby, Wakeup}: 0–2 s → BackRise,
a threat-only 2–5 s → RollLeft, 2–5 s → RollRight, 5 s+ → KipUp.
ChooseHitReaction(Damage, bHeadshot) (:18) walks rows in order, skipping
any row whose bRequiresHeadshot is unmet, and returns the first whose
half-open damage band contains the hit; it falls back to Light if nothing
matches. Because the headshot row is first and spans the whole range, a 5-damage
headshot returns Death, while a 35-damage body shot skips that row and lands
in Heavy. ChooseWakeup(DownTime, bThreatNearby) (:36) is the same shape
gated on threat: 3 seconds down with a nearby threat returns RollLeft; the
same 3 seconds without a threat skips that row and returns RollRight. The
automation spec asserts exactly those four outcomes
(AnimBPCompileSpec.cpp:98-101) — and they would fail against a hardcoded
return, because two of them differ only by the boolean flag. This is the genuine
selection logic an AnimBlueprint's hit-reaction and get-up state machines would
call into; today the call site is the test.
Motion warping — the one real plugin call#
UV4MotionWarpingHandler (V4MotionWarpingHandler.h:11) is a
BlueprintSpawnableComponent and the only place V4 reaches into an animation
plugin runtime. FV4MotionWarpAlignment (V4AnimationTypes.h:34) describes a
warp request: a context (Breach / Throw / Finisher), a TargetName, a target
FTransform, translation and rotation offsets, and a bMatchRotation flag.
ApplyWarpAlignment (V4MotionWarpingHandler.cpp:11) stores the request,
lazily finds-or-creates a real UMotionWarpingComponent on the owning actor
(GetOrCreateMotionWarpingComponent, :49 — FindComponentByClass, else
NewObject + AddInstanceComponent + RegisterComponent), and then calls the
engine plugin API
UMotionWarpingComponent::AddOrUpdateWarpTargetFromTransform
(MotionWarpingComponent.h:155 in the UE5.5 MotionWarping plugin) with the
computed transform. That is a genuine integration: a breach, a throw, or a
finisher can register a warp target the engine's motion-warping anim node
consumes, so root motion bends to align the operator's hands to a door or the
hero's strike to a boss.
The transform math is in CalculateAlignedTransform (:27) and is
independently testable without an owner: it starts from the alignment's target
transform, adds the translation offset, and either concatenates the rotation
offset (when bMatchRotation) or preserves the source rotation. The automation
spec exercises exactly this — a breach target at (100,0,0) yaw 90° plus a
(10,0,0) offset and a 90° rotation offset yields location X 110.0 and yaw
180.0 (AnimBPCompileSpec.cpp:110-118) — concrete arithmetic that pins the
offset and rotation-compose behavior.
How cells share and specialize#
The animation pipeline is the same shared-spine / narrow-specialization split as the GAS layer:
- Shared: one master AnimBlueprint per body/role family (not per character),
one IKRig per body archetype with a fixed chain set, the
MetaHuman → OperatorandMixamo → Operatorretargeters onto a singleOperatortarget skeleton, the8-frame /600 msmotion-matching contract, and the two runtime helpers (chooser table, warp handler) that are cell-agnostic. - Specialized per cell: which montage slots and state machines the master
graph exposes (cover/ADS for Tactical, body-drag for Stealth, combo/parry/
dodge/morph for ARPG, faction-override for RTS, flipbooks for Arcade), and
which motion-matching dataset (with its own cost weights and baked archetypes)
a traversal-heavy cell loads. Adding a seventh cell means a new master spec,
its slots/state-machines, optionally a motion-matching dataset, and a
ValidatePipelinearm — with no change to the shared skeletons or helpers.
Because there is exactly one skeleton per archetype and costumes ride on top, a new outfit or a new operator is an asset addition, never a rig fork — the same "mutually exclusive at run-time, shared by construction" property the GAS layer enforces for attribute sets.
How the pipeline connects (and where it does not yet)#
Animation sits downstream of GAS and input. A GAS verb
(./gas-layout.md) decides what a character is doing; the
AnimBlueprint expresses it as a pose. Input feeds the same chain: EnhancedInput
IMCs and the reused V4Input::FMotionParser (a 16-frame directional recognizer,
V4Input/Public/V4MotionParser.h:10) drive the ARPG combo verbs that the
ABP_ARPGHero_Master Combo/Parry/Dodge slots animate — detailed in
./input-pipeline.md.
The honest seam is the frame windows. The gas-layout page notes abilities "drive
the dodge/parry/posture frame windows"; those windows are computed today in
combat components — UV4DodgeComponent (InvincibilityFrames = 9,
IsInvincibleAtFrame) and UV4ParryComponent (ParryWindowFrames = 6,
IsFrameInsideParryWindow) in V4ActionRPG — not by animation notify
states, of which V4Animation ships none. So the integer-frame combat truth and
the visual animation are presently parallel tracks: the C++ windows are real and
tested, and the montages that would visualize them are not authored. Wiring the
chooser table and warp handler into those verbs, and authoring the AnimBlueprint
and montage .uasset the specs describe, is the remaining integration work.
The cloth, hair, facial-performance, and lip-sync presentation of these poses
— the MetaHuman runtime side the FV4MetaHumanPipelineSpec flags stand in for —
belongs to the presentation layer, not this module; see
./presentation-pipelines.md.
Related#
- GAS Layout — the verbs that pick montages and the combat-side dodge/parry/posture frame windows animation visualizes
- Input Pipeline — EnhancedInput IMCs and the
FMotionParserthat feed the ARPG combo/parry/dodge animation slots - Presentation Pipelines — cloth, hair, facial performance, and lip-sync that dress the poses this module produces
- The section hub: ../V4_ARCHITECTURE.md