feat(anim): idle and walk clips on the MPFB rig

Two parametric cycles authored at 30 fps instead of hand-keyed poses, so the loop
closes by construction: GigLine_Idle (60 f, breathing sway, feet planted) and
GigLine_Walk (30 f, one stride, hip 0.45 rad / knee 0.55 / arm 0.32, arms
counter-phased, torso counter-rotation).

The limb axes were measured, not assumed: a probe rotated upperleg01.L by 0.5 rad
on each axis and read foot.L, which moved -0.022 -> +0.362 in Y on X, twisted on Y
and abducted on Z. Using the wrong axis here would have produced a character
scissoring sideways, which no import error would have caught.

The character export preset now bakes animation. Without bake_anim the exporter
writes a static bind pose and Unreal imports a mesh with no AnimSequence and no
error, so the importer asserts a clip exists and prints VERDICT: PASS/FAIL.

Verified in /Game/Test/Character: Idle 1.967 s and Walk 0.967 s, both AnimSequences,
skeleton intact. Playback on a possessed pawn is not yet verified: the demo pawn has
no visible body, so that check belongs with the third-person camera item.
This commit is contained in:
zwitschi committed 2026-11-09 10:14:05 +01:00
1 parent 817313aabd
commit 96238bdb6a
12 files changed
+343 -2

No files matched your search

+13
View File
@@ -49,12 +49,25 @@ _METRIC = {
}
# Character exports differ only in the object set and the armature/path flags.
#
# Animation export (added for the 0.2.0 animation set): without `bake_anim` the
# exporter silently writes a static bind pose even when the armature carries
# actions, and Unreal then imports a character with no AnimSequence and no error.
# `bake_anim_use_all_actions` exports every action as its own clip; NLA strips are
# off because the project does not author NLA. `bake_anim_simplify_factor=0.0`
# keeps the sampled keys exactly as authored - the clips are short, so the size
# cost is irrelevant and a simplified curve would drift from the source poses.
_CHARACTER = dict(
_METRIC,
object_types={"ARMATURE", "MESH"},
add_leaf_bones=False,
path_mode="COPY",
embed_textures=False,
bake_anim=True,
bake_anim_use_all_actions=True,
bake_anim_use_nla_strips=False,
bake_anim_force_startend_keying=True,
bake_anim_simplify_factor=0.0,
)
PRESETS = {"ue_metric_v1": _METRIC, "ue_character_v1": _CHARACTER}