diff --git a/client/scripts/player.gd b/client/scripts/player.gd index 064670e..3e66592 100644 --- a/client/scripts/player.gd +++ b/client/scripts/player.gd @@ -491,8 +491,13 @@ 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() + # Use actual capsule bottom (CAPSULE_HALF_HEIGHT + PLAYER_CAPSULE_RADIUS = 0.9) so that a + # step-surface goal (e.g. Y=0.3) is never considered "arrived" while the player is still at + # floor height. Using only CAPSULE_HALF_HEIGHT (0.5) gives code-feet at Y=0.4, which is too + # close to step surfaces and causes premature arrival when Jolt nudges the body down to ~0.8 + # while the capsule hemisphere contacts the step edge. var vert_err: float = vertical_arrival_error( - _auth_walk_goal.y, global_position.y, CAPSULE_HALF_HEIGHT + _auth_walk_goal.y, global_position.y, CAPSULE_HALF_HEIGHT + PLAYER_CAPSULE_RADIUS ) if horiz_dist <= ARRIVE_EPS and vert_err <= VERT_ARRIVE_EPS: velocity = Vector3.ZERO diff --git a/client/test/player_test.gd b/client/test/player_test.gd index 50aee13..a912ae6 100644 --- a/client/test/player_test.gd +++ b/client/test/player_test.gd @@ -119,6 +119,33 @@ func test_vertical_arrival_error_stays_large_for_origin_height_only_match() -> v assert_that(absf(err - 0.5)).is_less(0.000001) +func test_arrival_vert_err_large_for_step_goal_from_floor() -> void: + # Player at floor height (body Y=0.9). Goal at step surface (Y=0.3). + # Using actual capsule bottom (CAPSULE_HALF_HEIGHT + PLAYER_CAPSULE_RADIUS) the error + # must exceed VERT_ARRIVE_EPS so the arrival check does NOT fire prematurely. + var goal_y := 0.3 + var body_y := 0.9 + var full_half: float = ( + PLAYER_SCRIPT.get("CAPSULE_HALF_HEIGHT") as float + + PLAYER_SCRIPT.get("PLAYER_CAPSULE_RADIUS") as float + ) + var err: float = PLAYER_SCRIPT.vertical_arrival_error(goal_y, body_y, full_half) + assert_that(err).is_greater(PLAYER_SCRIPT.get("VERT_ARRIVE_EPS") as float) + + +func test_arrival_vert_err_zero_when_standing_on_step() -> void: + # Player body centred at goal_y + total_half_height (i.e. actually standing on the step). + # Error must be within VERT_ARRIVE_EPS so arrival fires correctly once the player is up. + var goal_y := 0.3 + var full_half: float = ( + PLAYER_SCRIPT.get("CAPSULE_HALF_HEIGHT") as float + + PLAYER_SCRIPT.get("PLAYER_CAPSULE_RADIUS") as float + ) + var body_y: float = goal_y + full_half + var err: float = PLAYER_SCRIPT.vertical_arrival_error(goal_y, body_y, full_half) + assert_that(err).is_less_equal(PLAYER_SCRIPT.get("VERT_ARRIVE_EPS") as float) + + func test_flat_floor_goal_is_not_below_feet_height_margin() -> void: var goal_y := 0.0 var body_origin_y := 0.4