NEON-29: Ignore walk probe hits far below feet (void saw lower floor)

Down-rays use 0.32 m depth; a gold step is ~0.3 m above the slab, so a
forward sample over empty space still intersected the gray floor and
passed the up-normal test. That looked like continued support, so ledge
gravity and snap-off never fired.

Only treat a hit as walk support if its Y is within 0.14 m below the
current feet (one tread scale); deeper hits are a lower deck / pit.
pull/41/head
VinPropane 2026-04-12 18:10:36 -04:00
parent 6bd1acd9e7
commit c3fd9892e3
1 changed files with 9 additions and 1 deletions

View File

@ -75,6 +75,11 @@ const WALK_STEP_ASSIST_MAX_SURFACE_DELTA: float = 0.35
## Down-ray length under the capsule foot disk while walking (~[member NavigationMesh.agent_max_climb]).
const WALK_SUPPORT_PROBE_DEPTH: float = 0.32
const WALK_SUPPORT_PROBE_MIN_UP_DOT: float = 0.42
## Ignore ray hits farther below the feet than this (m). Prototype tread rise is ~0.104 m; without
## this cap, a probe over a **void** still reaches the **main floor** (~0.3 m down from a gold step)
## and reads as “forward support”, so snap + lip [code]is_on_floor()[/code] keep the capsule skating
## at deck height until XZ arrival.
const WALK_CONTINUATION_MAX_BELOW_FEET: float = 0.14
## CapsuleShape3D in scene: height = 1.0 (cylinder portion), radius = 0.4.
## Total half-height from body origin to physical bottom = 0.5 + 0.4 = 0.9
## (`CAPSULE_HALF_HEIGHT + PLAYER_CAPSULE_RADIUS`).
@ -359,7 +364,10 @@ func _walk_ray_hit_up_floor(space: PhysicsDirectSpaceState3D, off_xz: Vector2) -
var res: Dictionary = space.intersect_ray(q)
if res.is_empty():
return false
if not res.has("normal"):
if not res.has("normal") or not res.has("position"):
return false
var hit_y: float = (res["position"] as Vector3).y
if hit_y < feet.y - WALK_CONTINUATION_MAX_BELOW_FEET:
return false
var n: Vector3 = res["normal"]
return n.dot(Vector3.UP) > WALK_SUPPORT_PROBE_MIN_UP_DOT