Self-contained next-session brief for the airborne XY drift follow-up. Captures: confirmed root cause (ResolveWithTransition, verified A/B), three ranked hypotheses for the in-sweep mechanism (initial-overlap depenetration on non-+Z terrain normal is leading), three fix paths in preference order, repro steps with terrain-slope direction-correlation test, and the acceptance criteria. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4.1 KiB
#42 follow-up — PhysicsEngine.ResolveWithTransition airborne XY drift
Context: L.3 motion port landed in this branch (commits de129bc
40d88b9 2365c8c d57ace0 c26bbbb b37b713) — player-remote
running/walking/strafing/NPCs all visually verified clean. M4 jump
landing was fixed (CellId update). But that fix re-enabled
ResolveWithTransition per-tick during airborne arcs and exposed a
pre-existing PhysicsEngine bug: stationary jumps render with ~1 m
horizontal offset from the actor's actual XY, then snap back on the
next UM/UP.
Confirmed root cause (A/B-tested 2026-05-05): drift originates
inside ResolveWithTransition, not from wire data, local Euler error,
or stale velocity. With the sweep skipped, jumps render geometrically
correct (but body falls through floor). With it enabled, jumps land
correctly but show the drift. So the bug lives in the sweep.
Most likely mechanism
Initial-overlap depenetration along non-+Z terrain normal. At jump start the collision sphere is touching the floor at body Z. Most outdoor terrain triangles have non-vertical normals (small horizontal component). The sweep's first-frame action is to resolve the penetration by separating the sphere along the contact normal — and on a tilted triangle that separation has horizontal magnitude. The body gets shoved sideways the first frame; the rest of the arc carries the offset.
Direction-correlation test: jump at multiple landblock positions; if drift direction varies with terrain slope orientation (not actor facing), this hypothesis is confirmed.
Other candidates ranked by probability:
2. Step-down probe firing despite isOnGround: false parameter.
3. EdgeSlide on near-vertical motion against near-vertical surface.
Files to investigate
src/AcDream.Core/Physics/PhysicsEngine.cs—ResolveWithTransition- any internal
CTransition/find_valid_positionhelpers. The initial-overlap depenetration path is the primary target.
- any internal
- Reference at
docs/research/named-retail/acclient_2013_pseudo_c.txt:CTransition::find_valid_position(called fromtransition())SpherePathinitialization- Verbatim retail depenetration logic for airborne bodies
If our port differs from retail in this region, that diff is the bug.
Fix paths (in order of preference)
(a) Skip initial-overlap depenetration when airborne. Gate the
"separate from initial contact plane" step inside
ResolveWithTransition on isOnGround: true. Trusts the previous
tick's resolve to have left the body in a non-overlapping position.
Most likely correct fix.
(b) Zero step-up/down for airborne sweeps. Pass
stepUpHeight: 0f, stepDownHeight: 0f from
GameWindow.cs:6478+ when rm.Airborne. No side effects since
airborne bodies don't step.
(c) Stripped airborne sweep. Replace the full sphere sweep with a simpler vertical sphere-vs-terrain intersection + wall-collision stop. Loses retail fidelity but eliminates all three mechanisms. Probably overkill if (a) or (b) suffices.
Repro
- Launch acdream + retail client side-by-side on local ACE (127.0.0.1:9000).
- Have a retail-controlled toon stand still on outdoor terrain.
- Jump in place.
- Observe acdream window: arc shows ~1 m XY offset, lands offset, snaps back on next inbound UM.
To verify hypothesis (1) specifically: repeat the jump on terrain patches with different visible slope orientations; if drift direction changes accordingly, depenetration is confirmed.
Acceptance
- Stationary jumps render at the actor's actual XY (no perceptible drift, no snap-back on next UM).
- Wall-collision airborne still works (jumping into doorways, jumping puzzles where you have to thread between platforms or through arches).
Operating notes
- This is a
PhysicsEnginebug, not a motion-port bug. The L.3 work is done; this is a separate investigation. - The
[VU.WIRE]instrumentation idea from #42's earlier draft can be skipped — we already proved wire data isn't the source via the A/B test. - cdb attach to retail (
docs/research/2026-05-04-l3-port/-adjacent toolchain documented in CLAUDE.md) is available if comparing retail's airborne sweep behavior against ours becomes useful.