NS-23: Tighten bump step-off bypass (dual floor ray, drop band, horiz cap)

- Sample floor Y from center and lower probe; use max for bump rim.
- Only bypass nav for step-sized vertical drop with wider near-goal horiz.
- Loosen next-waypoint stickiness so rim waypoints fall back to goal sooner.
pull/23/head
VinPropane 2026-04-05 01:36:32 -04:00
parent 8b2b64a326
commit dbae80627f
1 changed files with 19 additions and 9 deletions

View File

@ -14,8 +14,13 @@ const VERT_ARRIVE_EPS: float = 0.055
const DIRECT_APPROACH_RADIUS: float = 0.85 const DIRECT_APPROACH_RADIUS: float = 0.85
const FLOOR_PROBE_DOWN: float = 4.0 const FLOOR_PROBE_DOWN: float = 4.0
const STEP_OFF_FLOOR_MARGIN: float = 0.04 const STEP_OFF_FLOOR_MARGIN: float = 0.04
const STEP_OFF_MAX_DROP: float = 0.55 ## Only NS-19-sized step downs (not cliffs); allows a wider horiz cap without bee-lining big drops.
const STEP_OFF_MAX_HORIZ: float = 1.05 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 FLOOR_PROBE_BODY_Y_OFFSET: float = -0.55
## If next waypoint is within this xz of us, steer to goal (rim / underfoot waypoints).
const NEXT_WAYPOINT_MIN_HORIZ_SQ: float = 0.01
var _has_walk_goal: bool = false var _has_walk_goal: bool = false
var _auth_walk_goal: Vector3 = Vector3.ZERO var _auth_walk_goal: Vector3 = Vector3.ZERO
@ -46,20 +51,26 @@ func snap_to_server(world_pos: Vector3) -> void:
_nav_agent.set_target_position(world_pos) _nav_agent.set_target_position(world_pos)
func _floor_y_under_body() -> float: func _ray_floor_y_at(from: Vector3) -> float:
var space: PhysicsDirectSpaceState3D = get_world_3d().direct_space_state var space: PhysicsDirectSpaceState3D = get_world_3d().direct_space_state
var from: Vector3 = global_position
var to: Vector3 = from + Vector3(0.0, -FLOOR_PROBE_DOWN, 0.0) var to: Vector3 = from + Vector3(0.0, -FLOOR_PROBE_DOWN, 0.0)
var q: PhysicsRayQueryParameters3D = PhysicsRayQueryParameters3D.create(from, to) var q: PhysicsRayQueryParameters3D = PhysicsRayQueryParameters3D.create(from, to)
q.collision_mask = 1 q.collision_mask = 1
q.exclude = [get_rid()] q.exclude = [get_rid()]
var hit: Dictionary = space.intersect_ray(q) var hit: Dictionary = space.intersect_ray(q)
if hit.is_empty(): if hit.is_empty():
return global_position.y return from.y
var pv: Variant = hit.get("position") var pv: Variant = hit.get("position")
if pv is Vector3: if pv is Vector3:
return (pv as Vector3).y return (pv as Vector3).y
return global_position.y return from.y
func _floor_y_under_body() -> float:
var y_center: float = _ray_floor_y_at(global_position)
var lower: Vector3 = global_position + Vector3(0.0, FLOOR_PROBE_BODY_Y_OFFSET, 0.0)
var y_lower: float = _ray_floor_y_at(lower)
return maxf(y_center, y_lower)
func _nav_short_step_down_use_goal_direct() -> bool: func _nav_short_step_down_use_goal_direct() -> bool:
@ -67,7 +78,7 @@ func _nav_short_step_down_use_goal_direct() -> bool:
if _auth_walk_goal.y >= floor_y - STEP_OFF_FLOOR_MARGIN: if _auth_walk_goal.y >= floor_y - STEP_OFF_FLOOR_MARGIN:
return false return false
var drop: float = floor_y - _auth_walk_goal.y var drop: float = floor_y - _auth_walk_goal.y
if drop > STEP_OFF_MAX_DROP: if drop < STEP_OFF_MIN_DROP or drop > STEP_OFF_MAX_DROP:
return false return false
var hd: float = Vector2( var hd: float = Vector2(
_auth_walk_goal.x - global_position.x, _auth_walk_goal.z - global_position.z _auth_walk_goal.x - global_position.x, _auth_walk_goal.z - global_position.z
@ -120,8 +131,7 @@ func _physics_process(_delta: float) -> void:
var to_next_h: Vector3 = Vector3( var to_next_h: Vector3 = Vector3(
next_path_position.x - global_position.x, 0.0, next_path_position.z - global_position.z next_path_position.x - global_position.x, 0.0, next_path_position.z - global_position.z
) )
# “goal Y < body Y” skips nav wrongly: pick is floor height, body origin is higher. if to_next_h.length_squared() > NEXT_WAYPOINT_MIN_HORIZ_SQ:
if to_next_h.length_squared() > 0.0025:
_set_horizontal_velocity_toward(next_path_position) _set_horizontal_velocity_toward(next_path_position)
else: else:
_set_horizontal_velocity_toward(_auth_walk_goal) _set_horizontal_velocity_toward(_auth_walk_goal)