Custom Creature: the animation clips
Authoring locomotion and attack clips for a creature, exporting them so the Modding Kit reads them correctly, and the one tag whose absence crashes the game everywhere at once.
Part of the Custom Creatures guide. Read the skeleton page first: if you author against the wrong rig, nothing on this page will save you.
Version
Measured against Bannerlord v1.4.8.
Locomotion clips are authored in place
A walk cycle has zero net root travel. The feet cycle, the body stays at the origin.
The engine supplies the translation itself, from the movement system. If you bake root motion into a walk, the engine adds its translation to yours and the creature moves at double speed while its feet skate.
The corresponding flag is anf_displace_position, which turns root motion on. Never set it on a
cyclic walk or run. See the reference tables.
quad_movement, or: the six-hour crash
This is the single most expensive lesson on these pages, so it goes near the top.
Every gait clip compiled for a movement_system="quadrupedal" action set must carry the
quad_movement clip usage, plus step points. Walks, runs, strafes, turns in motion, jumps.
Without it:
- The clip compiles fine. No error.
- It even plays correctly on a detached, non-mount agent. So it tests clean.
- Then a quadrupedal action set measures it, builds a null native gait structure, and the first
Skeleton.TickAnimationsorGetWalkSpeedLimitOfMountabledereferences it. - Access violation at offset
+0x10, in every mount context at once: the inventory thumbnail, the character tableau, and mission deployment.
The secondary fingerprint, if you are staring at a log: resolving an unbound action through the
poisoned set returns a runtime-synthesised garbage name, something shaped like
1002467048434979358_0.
In the Modding Kit, quad_movement is a CLIP USAGE, not a Flag
It is in the collapsed Clip usages section, below the Flags list. People look for a checkbox in Flags, do not find one, and conclude the tag does not exist.
make_walk_sound is a Flag. Step points are a third, separate field: they are the footstep
timing fractions, and unset they read as -1, -1, -1, -1.
Attack, hit and death clips correctly do not carry quad_movement. Only movement clips.
Per-category recipe
A working quadruped's clips, by category:
| Clip category | Flags | Clip usages |
|---|---|---|
| gait (walk, run, turn, strafe) | make_walk_sound |
quad_movement + step points |
| gallop-pace run | make_walk_sound |
quad_movement + step points + cyclic |
| attack | client_prediction, lock_movement, enforce_all |
none |
| death | make_bodyfall_sound, client_prediction, do_not_keep_track_of_sound, enforce_all, update_bounding_volume |
none |
| rear | lock_movement, enforce_lowerbody |
none |
Gait theory, or: why it looked wrong when everything was technically correct
Three things that made TAOM's creatures stop looking uncanny.
Elephants use a four-beat lateral sequence (left hind, left fore, right hind, right fore). Never a trot, never a pace. Their mass means there is no aerial phase at all, so the "fast" gait is a faster amble, not a different gait. Animating an elephant like a large horse reads as wrong immediately and it is hard to say why.
Spiders use an alternating tetrapod. Four legs down, four legs moving, alternating sets.
A spider idle is a braced, splayed stance, not a walk-in-place. An idle built by damping a walk looks like an animal treading water.
Amplitude edits have to be anchored to the planted-frame pose, or the stance foot floats. Phase shifts are a cyclic time offset and are safe to apply freely.
Exporting the clip
Armature only, and the armature object and its data are both renamed <skeleton>_notused.
object_types={'ARMATURE'}
add_leaf_bones=False
primary_bone_axis='Y', secondary_bone_axis='X'
axis_forward='-Y', axis_up='Z'
bake_anim=True
bake_anim_use_all_bones=True
bake_anim_use_nla_strips=False
bake_anim_use_all_actions=False
bake_anim_force_startend_keying=True
bake_anim_step=1.0
bake_anim_simplify_factor=0.0
What shipped clips from three separate creatures agree on, and what they do not:
| Property | Verdict |
|---|---|
UpAxis / FrontAxis / CoordAxisSign = 2 / 1 / -1 |
match this |
Model node types: Null 1 + LimbNode |
match this |
| Bones the Kit drops on import | must be 0 |
| TimeMode | not load-bearing. Shipped clips use both 24 and 30 fps |
| Clip flags count | not load-bearing. One shipped attack clip has zero flags and works |
Two traps in the export settings themselves:
bake_anim_use_all_bones=Falsedoes not reduce the exported bone set. Blender bakes the whole armature wheneverbake_animis on. The flag name is misleading.- Any
*_nub_notusedbone in the animation FBX is a difference from every shipped clip. Strip them before authoring.
Byte size is a reliable empty-bake detector
A healthy clip export is megabytes and takes seconds. An export that produced no keyframes comes out at roughly 0.06 MB in under 0.01 s. If your file is tiny, the bake found nothing.
On recent Blender this is usually because renaming edit bones does not rewrite slotted-action fcurve data paths. Lowercase your bones and the fcurves still point at the old names, so the bake is empty.
Compiling in the Kit
Import as a Skeleton Animation, set its Owner Skeleton, then create an Animation Clip from it: Source 1 = 0, Source 2 = the last frame, and check that Duration comes out greater than zero. Blend in around 0.1.
Do not rename a clip inside the Modding Kit
Renaming corrupts it. The Kit keeps resolving the old name, the inspector reports
Size in KB = 0, it refuses to save, the model viewer draws a scrambled pose, and the renamed
file can vanish outright. The only in-Kit remedy is restarting the tools after every single
rename.
Instead: create the clip, leave it on the default new_animation_clip name, set its source
range, sample rate and flags, save, close the Kit, rename the file on disk, and reopen.
The clip name itself does not need a particular prefix form. Bare names, single-prefixed and
double-prefixed all work; the <skeleton>| prefix you see on compiled clips comes from the Kit's
Owner Skeleton field, not from your take name.
Riders are not the creature skeleton
A mounted rider is the standard 28-bone human_skeleton. It is not your creature's rig.
Mounted rider poses are authored as human clips and bound in the as_human_warrior action set under
act_<mount>_* names mapping to rider_<mount>_* clips. At runtime the engine parents the rider to
the mount's rider_sit_bone.
Sit bones from shipped creatures, as a sanity check on your own:
| Mount | rider_sit_bone |
|---|---|
| horse | horsespine2 |
| warg | Spine1_M |
| spider | chest_m |
| elephant | Spine1_05 |
That leading space in the elephant's bone name is real
Bone names exported from some tools carry leading spaces, and the XML must reproduce them
exactly. A bone name that does not match resolves to index -1, silently, and a -1
rider_sit_bone seats the rider at the world origin. The symptom is "my rider is floating at
his own feet".
You do not have to author rider clips at all if an existing creature's fit close enough. TAOM's
spider reuses the warg's rider_warg_* clips.
Diagnosing a clip that looks right in Blender and wrong in game
Do these in order. Each is cheap and eliminates a whole class.
- Render a FRONT view. A yaw is almost invisible from the side, and it is very easy to spend hours looking only at side views. Assert on bone direction vectors, not head positions.
- Count the bones the Kit will drop. Any
*_nub_notusedis a difference from every shipped clip. - Diff the FBX globals against a shipped clip: UpAxis, FrontAxis, CoordAxisSign, node types.
- Compare the rig against the engine skeleton. Parenting and bone axis are the two things a mesh FBX gets wrong with no visible symptom.
A verification that cannot fail is not a verification
Three hypotheses were "refuted" during one TAOM session by tests structurally incapable of detecting the fault, and two turned out to be real problems.
Deleting the _nub_notused bones in Blender and seeing no pose change proves nothing: the nubs
sit coincident with their child carrying identity rotation, so removing them is a no-op by
construction. Re-parenting a bone in Blender and seeing no change fails the same way. And a
bone's head position cannot detect a rotation about its own origin, so head checks are blind to
exactly the error being hunted.
Before trusting a negative result, ask what the test would show if the hypothesis were true. If the answer is "the same thing", the test is worthless.
Pick the right reference creature
Compare your creature mount against a single-creature mount: a warg, a spider, an elephant.
Do not use a multi-creature rig such as a chariot as your reference. A two-horse-plus-cart rig is its own skeleton asset whose horse-named bones are not the horse skeleton, and they sit 90 degrees off every mesh rig. That looks exactly like a smoking gun and sent two rounds of TAOM's work in the wrong direction.
Measured against same-shaped creatures, a creature's animation FBX uses the same bone convention as its own mesh FBX: median differences of 6.79 and 16.83 degrees, which are rest-pose differences, not a 90 degree flip.
An honest status note
TAOM's own internal write-up of the export mapping closes with UNRESOLVED, as of its last
revision. The engine-data facts on the skeleton page are read
straight out of the engine's own assets and are solid. The step from those facts to an export
setting that reproduces a perfect clip on a reskinned rig is still open: the best result so far
comes from primary_bone_axis='Y' off the mesh rig with the neck bone re-parented to match the
engine, and the residual over-rotation is not fully explained.
Clips authored on bespoke rigs (spider, elephant, warg) work correctly. This caveat is specific to authoring new clips onto a vanilla rig you did not build.