NEON-29: Ledge peel via move_and_collide + fallback gravity
Direct global_position.y edits may not stick vs Jolt after move_and_slide. Use move_and_collide for the peel step so motion goes through physics. If get_gravity() is near zero, use -9.81 for peel, walk air, and idle air.pull/41/head
parent
fb1ac80fb0
commit
a78b44263c
|
|
@ -85,6 +85,8 @@ const WALK_CONTINUATION_MAX_BELOW_FEET: float = 0.14
|
|||
## ~0.42 m: **TerracePlatformB** top (~0.6 m) → floor (0) qualifies; **TerraceStepB** (~0.3 m) → floor does
|
||||
## not — shallow drops still rely on [method _walk_has_close_floor_probe_below].
|
||||
const WALK_DEEP_DESCENT_FEET_ABOVE_GOAL: float = 0.42
|
||||
## [method get_gravity] can be ~0 with missing/odd project defaults; ledge peel + airborne walk still need a pull.
|
||||
const WALK_FALLBACK_GRAVITY_Y: float = -9.81
|
||||
## CapsuleShape3D in scene: height = 1.0 (cylinder portion), radius = 0.4.
|
||||
## Total half-height from body origin to physical bottom = 0.5 + 0.4 = 0.9
|
||||
## (`CAPSULE_HALF_HEIGHT + PLAYER_CAPSULE_RADIUS`).
|
||||
|
|
@ -454,7 +456,7 @@ func _walk_has_close_floor_probe_below(move_dir_xz: Vector2) -> bool:
|
|||
## velocity does **not** move the body off a terrace lip; use [method _apply_walk_post_slide_ledge_peel].
|
||||
func _apply_walk_air_gravity(delta: float, _feet_y: float, _move_dir_xz: Vector2 = Vector2.ZERO) -> void:
|
||||
if not is_on_floor():
|
||||
velocity += get_gravity() * delta
|
||||
velocity += _effective_gravity(delta) * delta
|
||||
|
||||
|
||||
## After [method move_and_slide], peel the capsule down when the authoritative goal is below the feet
|
||||
|
|
@ -479,8 +481,11 @@ func _apply_walk_post_slide_ledge_peel(
|
|||
if not peel:
|
||||
_walk_ledge_peel_vy = 0.0
|
||||
return
|
||||
_walk_ledge_peel_vy += get_gravity().y * delta
|
||||
global_position.y += _walk_ledge_peel_vy * delta
|
||||
_walk_ledge_peel_vy += _effective_gravity(delta).y * delta
|
||||
var dy: float = _walk_ledge_peel_vy * delta
|
||||
if absf(dy) > 1e-9:
|
||||
# Raw [code]global_position[/code] edits can be ignored/overwritten vs Jolt sync after [method move_and_slide].
|
||||
move_and_collide(Vector3(0.0, dy, 0.0), false, safe_margin, false)
|
||||
|
||||
|
||||
func _walk_floor_snap_length(
|
||||
|
|
@ -576,6 +581,13 @@ func _set_horizontal_velocity_from_nav_path_or_goal(fallback_goal_xz: Vector3) -
|
|||
velocity.y = 0.0
|
||||
|
||||
|
||||
func _effective_gravity(_delta: float) -> Vector3:
|
||||
var g: Vector3 = get_gravity()
|
||||
if g.length_squared() < 0.25:
|
||||
return Vector3(0.0, WALK_FALLBACK_GRAVITY_Y, 0.0)
|
||||
return g
|
||||
|
||||
|
||||
static func capsule_feet_y(body_origin_y: float, capsule_half_height: float) -> float:
|
||||
return body_origin_y - capsule_half_height
|
||||
|
||||
|
|
@ -595,7 +607,7 @@ func _physics_idle_tick(delta: float) -> void:
|
|||
# cannot reach the lower floor — the capsule idles in mid-air until a new walk goal runs.
|
||||
velocity.x = 0.0
|
||||
velocity.z = 0.0
|
||||
velocity += get_gravity() * delta
|
||||
velocity += _effective_gravity(delta) * delta
|
||||
floor_snap_length = FLOOR_SNAP_MOVING
|
||||
move_and_slide()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue