NEON-29: Require forward floor probe to keep walk snap/gravity sane off ledges
Walk support used any ray hit under the foot disk, so the center sample could still see the platform while the leading edge was over a void. is_on_floor() stayed true from the lip, snap stayed strong, and vy was zeroed each tick — horizontal skate until XZ arrival. Now require a center hit plus at least one forward-biased sample in the movement direction when horizontal intent is non-zero; use velocity XZ for probe direction so nav/path steering matches the rays.pull/41/head
parent
1f6625c659
commit
6bd1acd9e7
|
|
@ -365,16 +365,30 @@ func _walk_ray_hit_up_floor(space: PhysicsDirectSpaceState3D, off_xz: Vector2) -
|
|||
return n.dot(Vector3.UP) > WALK_SUPPORT_PROBE_MIN_UP_DOT
|
||||
|
||||
|
||||
## True if **any** sample under the foot disk hits walk-like ground within [member WALK_SUPPORT_PROBE_DEPTH].
|
||||
## Uses [param move_dir_xz] so the **leading** edge off a deck is checked (center-only rays stayed over mesh).
|
||||
## Walkable support for **continued** forward motion within [member WALK_SUPPORT_PROBE_DEPTH].
|
||||
## Requires a hit under the foot origin **and** at least one sample **ahead** in [param move_dir_xz]
|
||||
## (same construction as [method _walk_probe_xz_offsets]). If only the center hits while the leading
|
||||
## foot is over a void, [method CharacterBody3D.is_on_floor] can stay true from a lip — returning
|
||||
## true here would suppress gravity and keep moving snap until XZ arrival (ledge skate).
|
||||
## When [param move_dir_xz] is ~zero (idle / no horizontal intent), center-only is enough.
|
||||
func _walk_has_close_floor_probe_below(move_dir_xz: Vector2) -> bool:
|
||||
var w3d := get_world_3d()
|
||||
if w3d == null:
|
||||
return true
|
||||
var space: PhysicsDirectSpaceState3D = w3d.direct_space_state
|
||||
if not _walk_ray_hit_up_floor(space, Vector2.ZERO):
|
||||
return false
|
||||
var len2: float = move_dir_xz.length_squared()
|
||||
if len2 < 1e-10:
|
||||
return true
|
||||
var inv_len: float = 1.0 / sqrt(len2)
|
||||
var md := Vector2(move_dir_xz.x * inv_len, move_dir_xz.y * inv_len)
|
||||
for off2: Vector2 in _walk_probe_xz_offsets(move_dir_xz):
|
||||
if _walk_ray_hit_up_floor(space, off2):
|
||||
return true
|
||||
if off2.length_squared() < 1e-12:
|
||||
continue
|
||||
if off2.dot(md) > 0.0:
|
||||
if _walk_ray_hit_up_floor(space, off2):
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
|
|
@ -922,9 +936,10 @@ func _physics_process(delta: float) -> void:
|
|||
else:
|
||||
_set_horizontal_velocity_toward(_auth_walk_goal, want_goal_h)
|
||||
|
||||
var walk_move_dir_xz := Vector2(want_goal_h.x, want_goal_h.z)
|
||||
# Prefer actual horizontal velocity so probes match nav/path steering, not only click bearing.
|
||||
var walk_move_dir_xz := Vector2(velocity.x, velocity.z)
|
||||
if walk_move_dir_xz.length_squared() < 1e-10:
|
||||
walk_move_dir_xz = Vector2(velocity.x, velocity.z)
|
||||
walk_move_dir_xz = Vector2(want_goal_h.x, want_goal_h.z)
|
||||
|
||||
_apply_walk_air_gravity(delta, walk_move_dir_xz)
|
||||
floor_snap_length = _walk_floor_snap_length(feet_y, want_goal_h, walk_move_dir_xz)
|
||||
|
|
|
|||
Loading…
Reference in New Issue