NEON-29: Reliable descend lip peel + capped floor snap
Wall/slide heuristics missed many step→floor stalls (e.g. far floor clicks). While descending with is_on_floor, always add gravity to vy before move_and_slide. Cap floor_snap_length when feet stay meaningfully above the goal so strong snap cannot yank the capsule back onto the step internal edge; cap lifts near landing (feet within 8 cm of goal Y). Apply snap helper on nomap + descend branches.pull/41/head
parent
f70dbe8f88
commit
cc63e9bdd7
|
|
@ -28,6 +28,9 @@ const IDLE_MANUAL_CORRECTION_MAX_TICKS: int = 8
|
||||||
## Horizontal nudge per tick for rim / straddle settle (**`_maybe_idle_rim_settle_nudge`**).
|
## Horizontal nudge per tick for rim / straddle settle (**`_maybe_idle_rim_settle_nudge`**).
|
||||||
const IDLE_RIM_SETTLE_STEP: float = 0.004
|
const IDLE_RIM_SETTLE_STEP: float = 0.004
|
||||||
const DESCEND_GOAL_Y_MARGIN: float = 0.06
|
const DESCEND_GOAL_Y_MARGIN: float = 0.06
|
||||||
|
## Cap floor snap while descending from a step so Jolt cannot snap the capsule back onto the
|
||||||
|
## upper surface across an internal edge (lip hang). Relaxed once feet are near the goal height.
|
||||||
|
const DESCEND_LIP_SNAP_CAP: float = 0.12
|
||||||
## Y lift when blocked by wall-ish slide but nav goal is higher (stepped bumps).
|
## Y lift when blocked by wall-ish slide but nav goal is higher (stepped bumps).
|
||||||
const WALK_STEP_ASSIST_DELTA: float = 0.11
|
const WALK_STEP_ASSIST_DELTA: float = 0.11
|
||||||
## Skip assist when horizontal velocity already aligns enough with want-dir (corners slide slowly).
|
## Skip assist when horizontal velocity already aligns enough with want-dir (corners slide slowly).
|
||||||
|
|
@ -254,24 +257,28 @@ func _apply_walk_air_gravity(delta: float) -> void:
|
||||||
if not is_on_floor():
|
if not is_on_floor():
|
||||||
velocity += g_step
|
velocity += g_step
|
||||||
return
|
return
|
||||||
# Descending toward a lower surface (e.g. first terrace step → main floor): rim / internal
|
# Descending toward a lower surface: `is_on_floor()` can stay true on the upper step while
|
||||||
# edge contact can keep `is_on_floor()` true on the upper surface while the step's vertical
|
# horizontal motion is blocked (internal edge / lip). `is_on_wall()` is unreliable here, and
|
||||||
# face zeros horizontal motion. With vy forced to 0 by `_set_horizontal_velocity_toward`,
|
# a far floor click keeps large horiz delta so wall heuristics never ran. Always integrate
|
||||||
# no gravity ran and the capsule could hang until a new click retargeted. Shallow 0.3 m
|
# downward acceleration while on the upper surface; `move_and_slide` + floor collision
|
||||||
# drops hit this more often than taller platform→floor descents.
|
# absorbs it on flat spans, and it peels the capsule off the lip when forward motion stalls.
|
||||||
var feet_on_floor: float = capsule_feet_y(global_position.y, CAPSULE_HALF_HEIGHT + PLAYER_CAPSULE_RADIUS)
|
var feet_y: float = capsule_feet_y(global_position.y, CAPSULE_HALF_HEIGHT + PLAYER_CAPSULE_RADIUS)
|
||||||
var descending: bool = (
|
var descending: bool = (
|
||||||
_has_walk_goal and _auth_walk_goal.y < feet_on_floor - DESCEND_GOAL_Y_MARGIN
|
_has_walk_goal and _auth_walk_goal.y < feet_y - DESCEND_GOAL_Y_MARGIN
|
||||||
)
|
)
|
||||||
if descending and g_step.y < 0.0:
|
if descending and g_step.y < 0.0:
|
||||||
var wallish: bool = is_on_wall()
|
velocity.y += g_step.y
|
||||||
if not wallish:
|
|
||||||
for i: int in get_slide_collision_count():
|
|
||||||
if get_slide_collision(i).get_normal().y < 0.55:
|
func _walk_floor_snap_length(feet_y: float) -> float:
|
||||||
wallish = true
|
var fl: float = WALK_STEP_ASSIST_SNAP if _step_assist_active else FLOOR_SNAP_MOVING
|
||||||
break
|
if (
|
||||||
if wallish:
|
_has_walk_goal
|
||||||
velocity.y += g_step.y
|
and _auth_walk_goal.y < feet_y - DESCEND_GOAL_Y_MARGIN
|
||||||
|
and feet_y > _auth_walk_goal.y + 0.08
|
||||||
|
):
|
||||||
|
fl = minf(fl, DESCEND_LIP_SNAP_CAP)
|
||||||
|
return fl
|
||||||
|
|
||||||
|
|
||||||
## When the authoritative goal shares XZ with the capsule (e.g. terrace above), horizontal
|
## When the authoritative goal shares XZ with the capsule (e.g. terrace above), horizontal
|
||||||
|
|
@ -626,7 +633,9 @@ func _physics_process(delta: float) -> void:
|
||||||
if NavigationServer3D.map_get_iteration_id(nav_map) == 0:
|
if NavigationServer3D.map_get_iteration_id(nav_map) == 0:
|
||||||
_set_horizontal_velocity_toward(_auth_walk_goal, want_goal_h)
|
_set_horizontal_velocity_toward(_auth_walk_goal, want_goal_h)
|
||||||
_apply_walk_air_gravity(delta)
|
_apply_walk_air_gravity(delta)
|
||||||
floor_snap_length = WALK_STEP_ASSIST_SNAP if _step_assist_active else FLOOR_SNAP_MOVING
|
floor_snap_length = _walk_floor_snap_length(
|
||||||
|
capsule_feet_y(global_position.y, CAPSULE_HALF_HEIGHT + PLAYER_CAPSULE_RADIUS)
|
||||||
|
)
|
||||||
move_and_slide()
|
move_and_slide()
|
||||||
_after_walk_move_and_slide()
|
_after_walk_move_and_slide()
|
||||||
if _step_assist_active and (
|
if _step_assist_active and (
|
||||||
|
|
@ -647,7 +656,7 @@ func _physics_process(delta: float) -> void:
|
||||||
if _auth_walk_goal.y < feet_y - DESCEND_GOAL_Y_MARGIN:
|
if _auth_walk_goal.y < feet_y - DESCEND_GOAL_Y_MARGIN:
|
||||||
_set_horizontal_velocity_toward(_auth_walk_goal, want_goal_h)
|
_set_horizontal_velocity_toward(_auth_walk_goal, want_goal_h)
|
||||||
_apply_walk_air_gravity(delta)
|
_apply_walk_air_gravity(delta)
|
||||||
floor_snap_length = WALK_STEP_ASSIST_SNAP if _step_assist_active else FLOOR_SNAP_MOVING
|
floor_snap_length = _walk_floor_snap_length(feet_y)
|
||||||
move_and_slide()
|
move_and_slide()
|
||||||
_after_walk_move_and_slide()
|
_after_walk_move_and_slide()
|
||||||
if _step_assist_active and (
|
if _step_assist_active and (
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue