diff --git a/client/scripts/player.gd b/client/scripts/player.gd index a99c0ce..3e20d4e 100644 --- a/client/scripts/player.gd +++ b/client/scripts/player.gd @@ -87,6 +87,9 @@ const WALK_CONTINUATION_MAX_BELOW_FEET: float = 0.14 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 +## Multiplier on project gravity for walk ledge peel, walk-airborne, and idle-airborne — snappier than +## real-world 9.81 m/s² for prototype feel; also offsets move_and_collide step coarseness at 120 Hz. +const PLAYER_VERTICAL_ACCEL_MULTIPLIER: float = 2.45 ## 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`). @@ -456,7 +459,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 += _effective_gravity(delta) * delta + velocity += _player_vertical_accel(delta) * delta ## After [method move_and_slide], peel the capsule down when the authoritative goal is below the feet @@ -471,7 +474,13 @@ func _apply_walk_post_slide_ledge_peel( if not is_on_floor(): _walk_ledge_peel_vy = 0.0 return - if _auth_walk_goal.y >= feet_y - DESCEND_GOAL_Y_MARGIN: + # Do not use [member DESCEND_GOAL_Y_MARGIN] here: it stopped peel while feet were still ~6 cm above + # the goal surface → slow “float to rest” at XZ destination. Only stop once vertical arrival matches. + var cap_half: float = CAPSULE_HALF_HEIGHT + PLAYER_CAPSULE_RADIUS + if vertical_arrival_error(_auth_walk_goal.y, global_position.y, cap_half) <= VERT_ARRIVE_EPS: + _walk_ledge_peel_vy = 0.0 + return + if _auth_walk_goal.y > feet_y + 0.04: _walk_ledge_peel_vy = 0.0 return var peel: bool = ( @@ -481,7 +490,7 @@ func _apply_walk_post_slide_ledge_peel( if not peel: _walk_ledge_peel_vy = 0.0 return - _walk_ledge_peel_vy += _effective_gravity(delta).y * delta + _walk_ledge_peel_vy += _player_vertical_accel(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]. @@ -588,6 +597,10 @@ func _effective_gravity(_delta: float) -> Vector3: return g +func _player_vertical_accel(_delta: float) -> Vector3: + return _effective_gravity(_delta) * PLAYER_VERTICAL_ACCEL_MULTIPLIER + + static func capsule_feet_y(body_origin_y: float, capsule_half_height: float) -> float: return body_origin_y - capsule_half_height @@ -607,7 +620,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 += _effective_gravity(delta) * delta + velocity += _player_vertical_accel(delta) * delta floor_snap_length = FLOOR_SNAP_MOVING move_and_slide()