Body step 2.2: fix the 2.1 headset instabilities
Spike now runs real input (90 Hz sample-and-hold tracking + jitter under 144 Hz physics), which reproduced the playtest. Root causes fixed: - PoseFilter/RagdollDriver: timestamped extrapolation of tracking, one tick pipeline shared by PlayerRig and the spike - low-pass all feed-forwards (ground control amplified jitter by body mass) - arm muscles back to local targets (physical-frame aim fed chest rotation back) - structural hand strength only when braced or holding - no free-path view chasing while grounded (8 m crouch slide); stick hold-back - explicit inertia for the Legs body (shape-less tuck tumbled the pelvis) - world grab: Box3D shape queries return a null collider, use collider_id - new crouch-hold phases; world-grab detection asserted Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2aff2b61da
commit
6006c5de98
8 files changed
+352
-81
No files matched your search
@@ -92,3 +92,42 @@ Changes and the measured reasons:
|
||||
Ground steeper than `MaxSlopeDegrees` 35° gives no support, so the 40° ramp can't be walked up; the 18° one can.
|
||||
Still open: the shoulder cone limit (needs a fork addition). `tools/playground_shots.tscn` renders overview PNGs for
|
||||
layout checks.
|
||||
|
||||
## Step 2.2 — the 2.1 playtest was unstable; root causes (2026-10-02)
|
||||
|
||||
The owner reported everything "all over the place":
|
||||
- Mantling swung the chest out of control and the hands "wobbled more and more".
|
||||
- Crouching made the body slide around and spin.
|
||||
- Nothing static was grabbable.
|
||||
- The steep ramp slipped the body out from under them.
|
||||
|
||||
RagdollSpike passed all of it, because its input was IDEAL: smooth poses every 144 Hz tick, no jitter. Fixes:
|
||||
|
||||
1. **The spike now runs on REAL input by default**: tracking sample-and-hold at 90 Hz under 144 Hz physics, plus
|
||||
0.5 mm / 0.1° jitter per sample (`-- ideal` / `nonoise` / `nohold` isolate the factors). Lesson: a body-physics
|
||||
test with perfect input proves nothing about the headset.
|
||||
2. **`PoseFilter` + `RagdollDriver`** (`scripts/RagdollDriver.cs`). Tracked poses are timestamped per new sample
|
||||
and extrapolated between samples in play-space-local coordinates. One driver runs the tick pipeline for
|
||||
both `PlayerRig` and the spike, so the test runs the game's code path.
|
||||
3. **Low-pass every feed-forward**: muscles/elbow τ 0.05 s, ground control τ 0.12 s. Ground control's velocity
|
||||
term multiplies by the whole body mass, so 1.5 mm of jitter became hundreds of newtons of buzz (pelvis
|
||||
0.27 → 0.04 m/s at rest).
|
||||
4. **Arm muscles stay LOCAL to the chest's target pose.** 2.1 aimed them in the physical chest frame, which closes a
|
||||
rotation feedback loop: the chest turns, the world-fixed arm targets push back on the chest, and the chest turns
|
||||
further. Jitter excited it into a slow twist (eye drifting 15 cm): the mantle "chest slipping". Only a
|
||||
horizontal translation of the reach is kept (body held back from the camera).
|
||||
5. **Structural hand strength only when the hand pushes on or holds something.** A hand reaching past its arm's
|
||||
length into free air pulled the whole body down by up to 400 N (crouch: eye 11 cm off).
|
||||
6. **No free-path view chasing while grounded.** Any eye/camera mismatch (crouch poses can't match exactly) moved
|
||||
the view, the pose target followed, the body followed, and so on: an 8 m slide while holding a crouch. The view
|
||||
is now only pushed back when geometry blocks the head. Instead, the stick stops pushing in the direction the
|
||||
body is held back (`PlayerRagdoll.HeldBack`, `PlayerRig.HoldBack`).
|
||||
7. **Explicit inertia on the `Legs` body.** Disabling its only collision shape (tuck) left it with no rotational
|
||||
inertia; its 400 N·m drive then tumbled the pelvis forward, which flipped the "yaw". This was the crouch spin.
|
||||
Rule: a body whose shapes can all be disabled needs explicit `Inertia`.
|
||||
8. **World grabs: the Box3D wrapper returns a null `collider` from `IntersectShape`**, only `collider_id`. Resolve it
|
||||
with `GodotObject.InstanceFromId`. The grab sphere is now 7 cm, checked at the palm and then the hand centre.
|
||||
The spike asserts the game's own `PropGrabber.WorldUnderPalm` finds the bar.
|
||||
|
||||
New spike phases: hold a crouch (eyes 1.0 m) and a deep crouch (0.7 m) without drift (< 5 cm) or spin (< 5°),
|
||||
eye on camera (< 5 cm). 29 phases total, all on real input.
|
||||
Reference in new issue
Block a user