NS-23: Arrival footing uses footprint max_y (avoid false stop on bump lip)
Premature arrival used _floor_y_under_body() vs dest footing; at the rim that can read floor while xz is already within ARRIVE_EPS, clearing the walk goal. Match step-down logic: compare destination footing to footprint max_y and cache footprint scan once per physics frame.pull/23/head
parent
003750c7ae
commit
8053f08804
|
|
@ -31,6 +31,8 @@ const NEXT_WAYPOINT_MIN_HORIZ_SQ: float = 0.01
|
|||
|
||||
var _has_walk_goal: bool = false
|
||||
var _auth_walk_goal: Vector3 = Vector3.ZERO
|
||||
var _footprint_cache_frame: int = -1
|
||||
var _footprint_cache: Dictionary = {}
|
||||
|
||||
@onready var _nav_agent: NavigationAgent3D = $NavigationAgent3D
|
||||
|
||||
|
|
@ -94,7 +96,7 @@ func _floor_y_under_body() -> float:
|
|||
|
||||
|
||||
## One ray pass: max floor Y under footprint + whether any hit is an NS-19 bump (`ns19_bump` group).
|
||||
func _footprint_step_down_state() -> Dictionary:
|
||||
func _compute_footprint_step_down_state() -> Dictionary:
|
||||
var p: Vector3 = global_position
|
||||
var h: float = STEP_FOOTPRINT_HALF
|
||||
var oxz: Array[Vector3] = [
|
||||
|
|
@ -140,6 +142,14 @@ func _footprint_step_down_state() -> Dictionary:
|
|||
return {"max_y": best_y, "touches_ns19_bump": on_bump}
|
||||
|
||||
|
||||
func _footprint_step_down_state() -> Dictionary:
|
||||
var f: int = Engine.get_physics_frames()
|
||||
if f != _footprint_cache_frame:
|
||||
_footprint_cache = _compute_footprint_step_down_state()
|
||||
_footprint_cache_frame = f
|
||||
return _footprint_cache
|
||||
|
||||
|
||||
## 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:
|
||||
|
|
@ -190,9 +200,12 @@ func _physics_process(_delta: float) -> void:
|
|||
var full_to_goal: Vector3 = _auth_walk_goal - global_position
|
||||
var horiz_dist: float = Vector2(full_to_goal.x, full_to_goal.z).length()
|
||||
var vert_err_capsule: float = absf(full_to_goal.y)
|
||||
var footing_match: bool = (
|
||||
absf(_floor_y_under_body() - _destination_footing_y()) <= VERT_ARRIVE_EPS
|
||||
)
|
||||
var dest_foot_y: float = _destination_footing_y()
|
||||
var fp: Dictionary = _footprint_step_down_state()
|
||||
var max_foot_y: float = float(fp["max_y"])
|
||||
# Same lip issue as step-off: `_floor_y_under_body()` can read floor early and match `dest_foot_y`
|
||||
# while xz is within ARRIVE_EPS — false “arrived”, goal clears. Use footprint max_y.
|
||||
var footing_match: bool = absf(max_foot_y - dest_foot_y) <= VERT_ARRIVE_EPS
|
||||
if horiz_dist <= ARRIVE_EPS and (vert_err_capsule <= VERT_ARRIVE_EPS or footing_match):
|
||||
velocity = Vector3.ZERO
|
||||
_has_walk_goal = false
|
||||
|
|
|
|||
Loading…
Reference in New Issue