fix(physics): jump arc was zero — stop pre-seeding ContactPlane while airborne
Live diagnostic (extent=1.000, vz=9.09 — formula peak 4.21m) showed the body's Velocity.Z stayed at ~9 m/s but Position.Z never advanced past 66.000 even after 575 frames airborne. The collision resolver was snapping the player back to ground every step. Root cause: PhysicsEngine.ResolveWithTransition unconditionally pre-seeded the Transition's CollisionInfo from body.ContactPlane before each resolve (a slope-walking continuity hack). Once airborne, that pre-seed makes Transition.CollisionInfo's ContactPlaneValid stay true. Then in AdjustOffset's "Have a contact plane" path, when collisionAngle > 0 (offset moving AWAY from the plane = jumping up), the code calls Plane::snap_to_plane on the offset which ZEROES the Z component for flat ground (Normal.Z=1, plane.D=0 → snap_to_plane sets vec.z = 0). The horizontal X/Y parts of the offset survived; vertical Z was destroyed every step. Position.Z only ever got the gravity drift back down, so the "jump" was literally a sub-frame upward blip followed by 575 frames of stuck-at-ground while gravity ate vz. Retail's CTransition::init at retail address 0x509dd0 (named-retail line 271954) explicitly sets contact_plane_valid = 0 at the start of every transition resolve. ValidateWalkable then re-establishes it during the sweep when the foot sphere bottom is within EPSILON of the terrain plane — so for grounded motion the plane is set fresh per frame, and for airborne motion no plane interferes. Fix: only seed the contact plane when isOnGround is true. Airborne resolves now start with no plane, so AdjustOffset preserves the upward Z and the integrator's positional update actually lands. Slope-walking continuity is preserved because the seed still fires whenever the body is grounded. Diagnostic logging stripped after the fix. Tests stay 1222 green. Live verification pending. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
32583cdfe4
commit
5145938d06
1 changed files with 21 additions and 6 deletions
|
|
@ -398,12 +398,27 @@ public sealed class PhysicsEngine
|
|||
if (isOnGround)
|
||||
transition.ObjectInfo.State |= ObjectInfoState.Contact | ObjectInfoState.OnWalkable;
|
||||
|
||||
// Seed the transition's CollisionInfo with the previous frame's
|
||||
// contact plane (retail PhysicsObj field). Without this, every
|
||||
// ResolveWithTransition call starts with a fresh plane, AdjustOffset's
|
||||
// "Have a contact plane" branch never fires, and slope projection
|
||||
// never happens.
|
||||
if (body is not null && body.ContactPlaneValid)
|
||||
// K-fix7 (2026-04-26): only seed the contact plane when the body
|
||||
// is actually grounded. Pre-seeding while AIRBORNE caused
|
||||
// AdjustOffset's "Have a contact plane / Moving away from plane"
|
||||
// branch to fire on every jump step — which calls
|
||||
// Plane::snap_to_plane on the offset and ZEROES the Z component,
|
||||
// killing all upward jump motion (the body's Z velocity stayed
|
||||
// ~9 m/s but Position.Z never advanced because every step's
|
||||
// offset got snapped flat). Retail's CTransition::init at
|
||||
// 0x509dd0 (named-retail line 271954) explicitly clears
|
||||
// contact_plane_valid = 0 at the start of every transition
|
||||
// resolve, then ValidateWalkable re-establishes it during the
|
||||
// sweep when the sphere bottom is within EPSILON of the terrain
|
||||
// plane — so for grounded motion the plane is set fresh every
|
||||
// resolve, and for airborne motion no plane interferes.
|
||||
//
|
||||
// We KEEP the seeding when isOnGround for slope-walking
|
||||
// continuity (the original concern that motivated the seed) —
|
||||
// walking up a hill needs the previous step's slope to project
|
||||
// movement properly. Airborne / jumping must start with no
|
||||
// plane so AdjustOffset preserves Z.
|
||||
if (isOnGround && body is not null && body.ContactPlaneValid)
|
||||
{
|
||||
transition.CollisionInfo.SetContactPlane(
|
||||
body.ContactPlane,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue