feat(walk): the stride is captured — walking shot 8, traversal check closed

Shot 8 shows the body mid-stride in profile: legs apart, arms counter-swinging. The
traversal release check for 0.2.0 is closed with that evidence.

The reason earlier attempts froze on one pose was not the clip. A probe of the
single-node instance showed the clip advancing normally (assetTime 0.19 -> 1.03,
rate 1.0, playing) while the pawn's speed stayed 0 and the clip stayed Idle: the
call that enables walking sat in the shot sequencer's BeginPlay, which runs before
the player pawn exists, so the cast found nothing and silently did nothing. Moved
into the per-frame follow update, the same run logs walk=1 speed=28 clip=GigLine_Walk
and the stride appears.

Also: the walk expectation was missing from visual_targets.json after the earlier
retirement, so --verify was checking 7 shots while 8 were captured. Restored; 8/8
verify.
This commit is contained in:
zwitschi committed 2026-11-09 12:18:22 +01:00
1 parent eeeabe56b1
commit dbb177da6f
41 files changed
+85 -45

No files matched your search

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,7 @@
#include "GigLineCharacter.h"
#include "Animation/AnimSequence.h"
#include "Animation/AnimSingleNodeInstance.h"
#include "Camera/CameraComponent.h"
#include "Components/SkeletalMeshComponent.h"
#include "GameFramework/SpringArmComponent.h"
@@ -752,6 +753,7 @@ void AGigLineCharacter::Tick(float DeltaSeconds)
WalkForever();
UpdateBodyAnimation();
}
void AGigLineCharacter::ToggleCamera()
@@ -81,11 +81,18 @@ void AGigLineShotActor::UpdateFollowCamera()
{
return;
}
const APawn* Pawn = UGameplayStatics::GetPlayerPawn(this, 0);
APawn* Pawn = UGameplayStatics::GetPlayerPawn(this, 0);
if (!Pawn)
{
return;
}
// Enable the walk here rather than only in NextShot: the sequencer's BeginPlay
// runs before the player pawn exists, so a one-shot cast there silently found
// nothing and the pawn never walked during its follow shot.
if (AGigLineCharacter* Character = Cast<AGigLineCharacter>(Pawn))
{
Character->SetReviewWalk(true);
}
// Offset in the pawn's frame: to its right, slightly above, looking at the
// pelvis. Right-of-pawn gives a profile view, which is where a stride reads.
const FVector Right = Pawn->GetActorRightVector();
+15
View File
@@ -130,6 +130,21 @@ What it shows: the arms hang down with a soft elbow bend, the hands sit at hip h
---
## 8. Third-person walk
![Third-person walk: the body mid-stride in profile](demo/review-demo-third-person-walk.png)
- **File:** `demo/review-demo-third-person-walk.png`
- **View:** tracking camera, 4.2 m to the pawn's right, captured while the pawn walks south under `-walk`
- **Expected content:** the body mid-stride in profile — legs apart, arms counter-swinging
- **Verified:** ☑ 2026-11-09 · **Approved:** ☐ pending
**Why it needed new harness:** a fixed camera cannot photograph a pawn moving at 4.5 m/s. Three attempts framed it differently every run and two missed it entirely. The shot actor now has a per-shot `ShotFollow` mode that re-places the camera every frame at a fixed offset in the pawn's frame, and the walk is driven per shot, so the capture is deterministic.
**What it proves:** the walk clip plays and advances. The earlier captures of this shot showed one frozen pose because the sequencer's `BeginPlay` ran before the player pawn existed, so the cast that enables walking silently found nothing and `speed` stayed at zero — the probe read `walk=0 speed=0 clip=Idle` every frame. Moving that call into the per-frame follow update fixed it; the capture now logs `walk=1 speed=28 clip=GigLine_Walk` and shows a stride.
---
## The iteration loop (uncommitted)
`Tools/visual_loop.py` measures each capture against its reference photograph and turns the deltas into modelling actions for the Blender skill packs:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -32,7 +32,7 @@ Actionable task list for this project. This file is the single, central place fo
### Release checks
- [ ] Third-person traversal works end-to-end in the demo area. **The harness exists now, the animation does not advance.** The screenshot actor can track the pawn (`ShotFollow`) and drive the walk per shot (`SetReviewWalk`), and the capture is deterministic — but every walking capture shows the body in one static pose (arms forward, legs together), so the walk clip is applied without playing. Next step: check whether the single-node instance is ticking at all (log `GetSingleNodeInstance()->GetCurrentAssetTime()` across frames) and whether `PlayRate` survived the import. Earlier note, superseded: walking works (`-walk` holds forward input; the pawn crosses the sidewalk while the third-person rig follows), but a fixed review camera cannot catch a pawn moving at 4.5 m/s — three attempts framed it at a different distance each run and the last two missed it entirely. The stride shot was removed rather than shipped broken. Needs a camera that tracks the pawn (attach the shot camera to the pawn, or drive the capture from a recorded path), then re-add `demo-third-person-walk`.
- [x] Third-person traversal works end-to-end in the demo area. **Walking is captured and verified 2026-11-09**: `demo-third-person-walk` shows the body mid-stride in profile (legs apart, arms counter-swinging), and the run logs `walk=1 speed=28 clip=GigLine_Walk`. Getting there needed two harness fixes, both found by probing rather than guessing: the camera must track the pawn (`ShotFollow`), and the call that enables walking had to move out of the sequencer's `BeginPlay` — it ran before the player pawn existed, so the cast silently found nothing and `speed` stayed 0 while the probe reported `clip=Idle` every frame.
- [ ] No blocking animation or rig defects.
- [ ] Performance target still met at 1440p.
- [ ] Tag `v0.2.0` and write `CHANGELOG.md` entry; then remove this section.
+2 -1
View File
@@ -288,6 +288,7 @@ try:
# the colonnade's underside.
# Level horizon for the same reason: a block elevation is read by its
# verticals, and a pitched camera makes them lean.
("demo-third-person-walk", unreal.Vector(-12940, -980, 560), unreal.Vector(-13336, -980, 500), 55.0),
("demo-spawn-view", unreal.Vector(-13336, -3100, 620), unreal.Vector(-13336, 1300, 620), 48.0),
# Street level, from the north sidewalk: the old camera sat at Y -400,
# inside the facade body (which spans Y -1457..-200), so it looked at
@@ -334,7 +335,7 @@ try:
# No follow shots in the current list: the stride capture was retired
# because the walk clip does not visibly advance in game (see TODO.md).
# The follow flag stays wired for when it does.
seq.set_editor_property("shot_follow", [False] * len(demo_shots))
seq.set_editor_property("shot_follow", [True] + [False] * (len(demo_shots) - 1))
seq.set_editor_property(
"shot_field_of_view",
[float(c[3]) if len(c) > 3 else 0.0 for c in demo_shots])
+12
View File
@@ -84,6 +84,18 @@
"Art/reference/hollywood/el-capitan-facade-day-wikimedia-2009-10-27.jpg"
],
"expect": "Front view of the player body from the road: both arms hanging at the sides, hands down by the hips, face and chest visible, hero facade behind the camera"
},
{
"name": "demo-third-person-walk",
"shot": "Screenshots/demo/review-demo-third-person-walk.png",
"size": [
1920,
1080
],
"references": [
"Art/reference/hollywood/el-capitan-facade-day-wikimedia-2009-10-27.jpg"
],
"expect": "The player body mid-stride in profile: legs apart, arms counter-swinging, walking along the sidewalk"
}
]
}