Animation¶
All · 15 min read
What the player sees: characters walk and run with smooth blending, turn their upper body toward a locked enemy while their legs keep running, switch to a sword stance when a battle starts, fidget when left standing, flinch without dropping their swing, and (on VRoid characters) blink, pull faces and turn their heads toward whoever they are looking at.
Every party character shares one host Animation Blueprint, Characters/Player/ABP_XenoCore_Base,
which holds the state machine (Idle, Move, the jump states). Which clips each state plays
come from a linked animation layer: a small Animation Blueprint chosen by what the character
holds and by its masculine or feminine style. The host is shared and never edited per character;
a new weapon or stance is a new layer child that only swaps clips, set in its Asset Override
editor with no graph editing.
What you can change¶
- Masculine or feminine movement for a character: Choose an animation style.
- A new weapon stance: Add a weapon (see Extending it).
- One character's own flinch, topple, dodge, death or victory pose: Give a character its own combat animations.
- One character's idle fidgets and resting faces: Give a character its own idle breaks and faces.
- Stride, turn and head-look limits: settings on the host Animation Blueprint (Settings).
How it fits together¶
| Piece | Class / sample asset | Job |
|---|---|---|
| Anim instance (C++ parent of every XenoCore Animation Blueprint) | XenoCoreAnimInstance |
Works out ground speed, direction, stride scale, battle stance, target twist, head turn and idle breaks, so no Blueprint graph has to |
| Host ABP | Characters/Player/ABP_XenoCore_Base |
Locomotion state machine, montage slots, inertialization, stride warping, spine twist, head and neck turn |
| Layer interface | Characters/Player/AnimLayers/ALI_XenoCore_AnimLayers |
The layer functions: FullBody_Idle, FullBody_Move, FullBody_Jump, FullBody_Apex, FullBody_Falling, FullBody_Land, FullBody_SkeletalControls |
| Layer base | AnimLayers/ABP_XenoCore_ItemLayersBase |
The layer graphs, written once |
| Layer children | ABP_XenoCore_UnarmedAnimLayers, ABP_XenoCore_UnarmedAnimLayers_Feminine, ABP_XenoCore_GreatSwordAnimLayers |
Override clips and blend spaces only |
| Blend spaces | Characters/Player/BlendSpaces/BS_XenoCore_Unarmed_Locomotion, _Feminine, BS_XenoCore_GreatSword_Combat_Locomotion |
Direction × speed |
| Style parts | Characters/Core/Cosmetics/B_XenoCore_Cosmetic_Masculine, _Feminine |
Carry Cosmetic.AnimationStyle.Masculine / .Feminine |
| Weapon instance | Weapons/B_WeaponInstance_Base, GreatSword/B_WeaponInstance_GreatSword |
Picks and links the layer when the weapon is drawn or stowed |
| Face (VRoid only) | Characters/VRoid/<Name>/Animation/ABP_XenoCore_VRoidRetarget_* |
Blinks, expressions and mouth on a VRoid body |
| Expression table | Characters/Core/Face/DT_XenoCore_FaceExpressions |
Named faces (Happy, Laugh, Smug…) as mixes of face curves |
| Anim profile | Characters/VRoid/<Name>/DA_XenoCore_AnimProfile_VRoid_* |
One character's own reaction, death and victory clips, idle breaks and resting faces |
| Enemy ABP | Characters/Enemies/Minion/ABP_XenoCore_Minion_Melee |
Built on the same C++ parent, not on the host ABP. Moves on a 2D blend space, Minion/Animations/BS_XenoCore_Minion_Locomotion2D (direction × speed), so a minion circling sideways in a fight plays side and back jogs |
Lifecycle¶
Every frame. The C++ parent works out these values, which the graphs read (you can see them in the Animation Blueprint's Variables list):
- Ground Speed (horizontal only) and a smoothed copy; Is Moving above Moving Speed
Threshold (
20). - Direction, −180 to 180 against the actor's facing. Out of battle the character faces where it runs, so this stays near 0.
- Stride Scale = Ground Speed ÷ Authored Clip Speed (
400), floored at Min Stride Scale (1.0), so warping only ever lengthens the stride above the fastest clip. - In Battle, from
Status.XenoCore.InBattleon the character's ability system. - Target Yaw Delta, the damped, clamped angle to the locked target. It turns the upper body
toward the target while the legs keep running (look traversal), up to Max Target Twist (
70°). - Look Bone Rotation 0–2, the head and neck turn toward what a companion is looking at (see The head turn).
- Wants Idle Break (see below).
The state machine. The host moves between Idle and Move on ground speed with a short
blend, and through jump states (Jump, Apex, Falling, Land) when airborne. Each state calls its layer
function, such as FullBody_Move, which plays a 2D blend space: direction on one axis, speed on
the other, with walk clips at 200 and jog at 400, so both walking and running blend continuously.
Choosing the layer. The weapon instance Blueprint holds two sets, Equipped Anim Set and Uneuipped Anim Set (Lyra's spelling), each a list of layer classes with the tags that select them. When the weapon is drawn or stowed, the set for that state is searched for the layer whose tags best match the character's style tags (so a feminine character gets the feminine unarmed layer), that layer is linked, and the change of stance blends over Anim Layer Blend Time instead of popping.
If nothing is linked, each layer node falls back to ABP_XenoCore_UnarmedAnimLayers.
Masculine and feminine. A party pawn's Cosmetic Part (on B_XenoCore_PartyMember_Base)
adds a style part carrying Cosmetic.AnimationStyle.Masculine or .Feminine. The same tag picks
the body mesh through the pawn's Body Meshes rules (SKM_Manny or SKM_Quinn) and the unarmed
layer. The feminine layer uses Lyra's MF_ clips (MM_ is Lyra's masculine set).
Idle breaks. After Idle Break Delay (8 s) plus a random Idle Break Jitter (up to 6 s)
of standing still, Wants Idle Break turns true for exactly the length of the chosen clip, and the
idle layer blends to that clip and back. Each character rolls its own timing, so a party does not
fidget in unison.
Which clip plays comes from two places:
- The character's Anim Profile, if it has one: Idle Breaks out of battle, Armed Idle Breaks with the weapon drawn. One is picked at random each time, never the same one twice running.
- Otherwise, the stance's own Idle Break Anim on its layer child. The shipped ones:
MM_Unarmed_IdleBreak_Fidget(unarmed),MF_Unarmed_Idle_Break(feminine),AS_Kwang_IdleBreak_Laugh(greatsword). An empty Idle Break Anim means that stance never fidgets, unless the profile gives it a list.
Each shipped VRoid member has four breaks in its profile, drawn from Lyra's three and nine
bare-handed clips in Characters/Core/Animations/IdleBreaks (Stretch, Waiting, Sneeze, Greeting and
others). Their Armed Idle Breaks are empty, so with the sword out they use the stance's own break.
See Give a character its own idle breaks and faces.
Montages. Attacks, Arts, hit reactions and the draw and sheathe play as montages on top of the
state machine. Attacks and Arts use the slots of the default slot group (DefaultGroup): the
party's play on FullBody, the minion's on DefaultSlot; Topple, Daze, guards, recoils and victory
emotes also use FullBody; the draw and sheathe use UpperBody. A flinch plays additively on the AdditiveHitReact slot, which
sits in its own group, AdditiveGroup: it is layered on top of whatever the body is doing, so a hit
reads while the character walks or swings, and it never stops the swing. A character does not flinch
while drawing or sheathing.
A miss plays a duck or a dodge, picked at random from the evade ability's Random Montages
(GA_XenoCore_Evade), on the Defence slot. In battle the arms are taken back from the stance under
that slot, so the body ducks while the hands stay on the sword; unarmed, the clip's own arms play.
While a hit's knockback is pushing the body, the anim instance reads its velocity as zero, so a character sliding backwards from a blow does not break into a forward jog.
Fails silently: a flinch that never shows, or that cancels the swing
A flinch montage must be on the AdditiveHitReact slot, its clips must be Additive Anim Type
Local Space (base pose: the clip's own first frame), the anim Blueprint must apply that slot
additively, and the slot must be in its own slot group on the skeleton. Montages in one group
stop each other, and compiling an anim Blueprint puts a new slot in DefaultGroup, so a flinch
there cuts the attack short and the next swing cuts the flinch off. Check it in the skeleton's
Anim Slot Manager: AdditiveHitReact belongs under AdditiveGroup, as on SK_Mannequin.
Per-character combat clips. Reaction and death montages come from the reaction ability and the
pawn by default, shared by everyone who has them. A character's Anim Profile (a data asset, set
on the pawn under XenoCore › Animation) overrides them for that
character only, slot by slot: an empty slot keeps the shared clip. Each reaction ability names the
profile row it reads with its Profile Key (Anim.XenoCore.Reaction.Flinch, .Topple, .Daze,
.Guard, .Evade, .Recoil). Walking, running and idles are not in the profile; they come from
the style and the weapon, as above. See
Give a character its own combat animations.
Stride warping happens once, in the host ABP, driven by Stride Scale.
VRoid faces. A VRoid party member runs the Mannequin animation on an invisible body; its VRoid
mesh copies the pose, and its retarget Animation Blueprint (ABP_XenoCore_VRoidRetarget_*) drives
the face:
- a random blink, timed per character;
- an expression chosen from the character's gameplay tags by Expression Rules, first matching rule wins. The shipped order: downed looks pained, dead closes the eyes, Topple and Break look surprised, Daze sad, a victory celebration laughs, casting an art and being in battle look angry, a conversation looks relaxed;
- a mouth flap while Talking Tag is held, or lip sync for a voice line;
- Play Expression for scripted moments, which wins over the rules for its duration.
An expression is named by a row of the face's Expression Table, which defaults to
Characters/Core/Face/DT_XenoCore_FaceExpressions. It ships 19 rows: Happy, Smile, Laugh, Giggle, Wink,
Smug, Annoyed, Angry, Determined, Sad, Worried, Surprised, Shocked, Relaxed, Bored, Sleepy, Yawn,
Thinking and Pained. Each row is a Curves map of face curve to
weight, built from the VRM presets (happy, angry, sad, relaxed, surprised, aa, ih, ou,
ee, oh, blink, blinkLeft, blinkRight). Suppress Blink stops the blink while it shows,
and Pulse Curve, Pulse Weight and Pulse Rate add an oscillating curve on top, such as a
laugh's opening and closing mouth. A name that is not a row is played as one curve at full weight, so
a rule that says angry still works.
To play a face from any Blueprint, call Play Expression On Actor with the pawn (or its cosmetic part), a row name, a weight and a duration. It returns false, and does nothing, on a character without a face, such as a Mannequin-bodied member or an enemy.
The head turn¶
Companions turn their head and neck toward whatever their gaze is on: the leader, another member, the view, the battle target. What they look at is chosen by the party StateTree (see Companion AI); this is the part that moves the bones.
ABP_XenoCore_Base adds Look Bone Rotation 0, 1 and 2 to neck_01, neck_02 and head,
after the chest twist. The head carries about half the turn and moves fastest, and the neck trails
it, so the turn reads as a head leading rather than one stiff hinge. When the chest is already
twisted toward a battle target, that twist is taken off first, so the head does not turn twice.
The head returns forward while the character holds any of Look Blocked By Tags (downed, celebrating, toppled, dazed by default), because a clip is driving the head then. A player-controlled body has no gaze and always looks straight ahead.
Settings¶
| Setting | Where it lives | What it does |
|---|---|---|
| Idle Break Anim, Idle Break Delay, Idle Break Jitter | Layer child › Class Defaults › XenoCore › IdleBreak | The fidget for this stance and how often |
| Clip and blend space overrides | Layer child › Asset Override editor | Which clips each state plays |
| Authored Clip Speed, Min Stride Scale, Moving Speed Threshold, Speed Smoothing Rate | Host ABP › Class Defaults › XenoCore › Locomotion | Stride warping and idle/move threshold |
| Max Target Twist, Target Twist Interp Rate | Host ABP › Class Defaults › XenoCore › Battle | Upper-body turn toward the target |
| Equipped Anim Set, Uneuipped Anim Set | Weapon instance Blueprint › Class Defaults | Layers for drawn and stowed |
| Anim Layer Blend Time | Weapon instance Blueprint | Blend time on a layer swap |
| Cosmetic Part | Party pawn Blueprint › Class Defaults | Masculine or feminine style part |
| Anim Profile | Party or enemy pawn Blueprint › Class Defaults › XenoCore › Animation | This character's own reaction, death and victory clips, idle breaks and resting faces; empty slots use the shared ones |
| Body Meshes | Party pawn's character parts component | Tag → body mesh rules |
| Expression Rules, Expression Table, blink and mouth settings | VRoid retarget ABP › Class Defaults › XenoCore › Face | Face behaviour, and the table expression names are looked up in |
| Look Bone Shares, Look Bone Interp Speeds, Look Max Yaw, Look Give Up Yaw, Look Max Pitch Up/Down, Look Origin Bone, Look Blocked By Tags | Host ABP › Class Defaults › XenoCore › Look | How far and how fast the head turns (70° yaw, given up past 125°; 30° up, 25° down) |
| Idle Breaks, Armed Idle Breaks | Anim profile › Idle | This character's own fidgets; empty uses the stance's |
| Social Expressions, Solo Expressions | Anim profile › Face | This character's faces at rest: its temperament |
A style tag with no rule gives the default body
The character-parts component always applies a body mesh from Body Meshes. A style part whose tags match no rule, or whose class is empty, resolves to Default Mesh. Every shipped pawn has one, and XenoCore's party and player characters fall back to their spawn mesh (with a warning) if a Default Mesh is missing, so the result is the wrong body rather than none. A pawn outside XenoCore's character classes still disappears. A party pawn that sets no Cosmetic Part must not add a part at all. See Characters.
For programmers. Fails silently: an anim property without Blueprint Read Only
If you add a C++ property to an anim instance and drive an anim graph pin from it, it must be Blueprint Read Only (or Read Write). Otherwise the Animation Blueprint fails to compile with no message anywhere, and Play in Editor just says a Blueprint failed to compile.
Fails silently: a face curve the mesh does not have
An expression row that names a curve the VRoid model's face does not have shows nothing, and
nothing is logged. A typo in a row name looks the same, because a name that is not a row is
tried as a single curve. Rows built from the VRM presets listed above are known to work; check
any row that uses a raw Fcl_* morph curve in Play before relying on it.
Fails silently: the idle break branches wired backwards
In Blend Poses by bool, the first pose pin is the True pose. Wired the other way round, the fidget becomes the idle and the real idle plays as an occasional interruption.
Fails silently: a second Stride Warping node
Stride warping already runs in the host. Adding it in a layer too applies it twice and the feet slide. A Stride Warping node with no thigh bones set does nothing at all, which hides the mistake until someone fills them in.
Fails silently: a montage on the wrong slot group
The layer-swap blend is requested on DefaultGroup. A montage on another group blends wrongly
when the stance changes, with no error.
Extending it¶
- A new weapon stance: duplicate
ABP_XenoCore_GreatSwordAnimLayersinto your own folder, set its clip and blend-space overrides and its Idle Break Anim, then point your weapon instance's Equipped Anim Set at it. No graph editing is needed. See Add a weapon. - Changing a character's animation style: see Animation style.
- One character's own topple, flinch, block, dodge or death: fill in its Anim Profile; see Give a character its own combat animations. No ability needs duplicating.
- Never recreate
ABP_XenoCore_UnarmedAnimLayers. The host's layer nodes use it as their fallback class; a new asset under the same name orphans them. Duplicate it instead. - Do not reparent an Animation Blueprint to another Animation Blueprint to share logic: a child Animation Blueprint loses its own graph. Use override-only layer children as above; logic shared by every Animation Blueprint belongs in the C++ parent, which is a programmer's job.
- Keep gameplay-tag-driven variables on the host Animation Blueprint; on a linked layer they stop updating after the layer is linked.
For programmers: classes and calls
The C++ parent is UXenoCoreAnimInstance: it captures velocity and rotation on the game thread
and computes the values above in the thread-safe update. The face is UXenoCoreFaceAnimInstance,
the profile UXenoCoreCharacterAnimProfile, an expression row FXenoCoreFaceExpressionRow. On a
draw or stow, the weapon instance's SetDrawn collects the cosmetic tags, calls Lyra's
PickBestAnimLayer, then LinkAnimClassLayers, then
RequestSlotGroupInertialization("DefaultGroup", AnimLayerBlendTime). The flinch ability refuses
while Status.XenoCore.Arming is held.
Why it's built this way¶
For programmers
- Own host, not Lyra's. Lyra's locomotion enters Start/Stop states on input and commits to them
for up to a second, which feels unresponsive for this style of game; its state machine lives in
Lyra's own asset and cannot be owned. XenoCore's
Idle ↔ Movemachine with a 2D blend space is snappier and blends walk and run continuously. - Lyra's layer mechanism, kept. Per-state linked layers,
PickBestAnimLayerfrom the weapon on draw, and an inertialization request (Lyra delivers the same request through a transition). Links are made once on an event, never per frame, and never unlink-then-link, which would drop every node to its fallback for an instant. - Not derived from
ULyraAnimInstance, because it has no export macro and cannot be derived from outside Lyra's module;UXenoCoreAnimInstancereproduces the part it needs and pulls the ability system itself. - Idle breaks in the anim stack, where Lyra keeps its own, because the graph already knows whether the Idle state is active; an ability polling for it was heavier and less exact.