NS-23: Step-off footing uses capsule footprint max + wider horiz

At bump lips, center/lower rays often hit the floor first while the body is
still on the rim, so drop read ~0 and nav rim-follow resumed. Max floor Y
over center, lower probe, and 8 xz offsets (cardinal + diagonal) keeps
step-down bypass active until the whole footprint clears. Raise
STEP_OFF_MAX_HORIZ to 8 m (still capped by small drop band).
pull/23/head
VinPropane 2026-04-05 01:48:55 -04:00
parent b1ce87c5cc
commit f67705f4a3
1 changed files with 26 additions and 2 deletions

View File

@ -17,8 +17,10 @@ const STEP_OFF_FLOOR_MARGIN: float = 0.04
## Only NS-19-sized step downs (not cliffs); allows a wider horiz cap without bee-lining big drops.
const STEP_OFF_MIN_DROP: float = 0.055
const STEP_OFF_MAX_DROP: float = 0.24
const STEP_OFF_MAX_HORIZ: float = 3.0
const STEP_OFF_MAX_HORIZ: float = 8.0
const FLOOR_PROBE_BODY_Y_OFFSET: float = -0.55
## Extra xz rays for step-off; max Y keeps bump support when center ray sees floor first.
const STEP_FOOTPRINT_HALF: float = 0.2
## Downward vy only while step-off bypass is active (not global gravity).
const STEP_OFF_DESCEND_SPEED: float = 1.6
## If next waypoint is within this xz of us, steer to goal (rim / underfoot waypoints).
@ -75,6 +77,28 @@ func _floor_y_under_body() -> float:
return maxf(y_center, y_lower)
## Max floor Y under capsule + xz offsets (step-off). Fights lip rays that hit ground too early.
func _floor_y_max_under_capsule_footprint() -> float:
var best: float = _floor_y_under_body()
var p: Vector3 = global_position
var h: float = STEP_FOOTPRINT_HALF
var oxz: Array[Vector3] = [
Vector3(h, 0.0, 0.0),
Vector3(-h, 0.0, 0.0),
Vector3(0.0, 0.0, h),
Vector3(0.0, 0.0, -h),
Vector3(h, 0.0, h),
Vector3(h, 0.0, -h),
Vector3(-h, 0.0, h),
Vector3(-h, 0.0, -h),
]
for d: Vector3 in oxz:
best = maxf(best, _ray_floor_y_at(p + d))
var lower_from: Vector3 = p + d + Vector3(0.0, FLOOR_PROBE_BODY_Y_OFFSET, 0.0)
best = maxf(best, _ray_floor_y_at(lower_from))
return best
## Footing under goal xz (surface Y). Server goal.y may be capsule center (e.g. 0.9) or pick surface
## (e.g. 0) — do not compare that directly to `_floor_y_under_body()` (always surface).
func _destination_footing_y() -> float:
@ -88,7 +112,7 @@ func _destination_footing_y() -> float:
func _nav_short_step_down_use_goal_direct() -> bool:
var floor_y: float = _floor_y_under_body()
var floor_y: float = _floor_y_max_under_capsule_footprint()
var dest_floor_y: float = _destination_footing_y()
if dest_floor_y >= floor_y - STEP_OFF_FLOOR_MARGIN:
return false