NS-23: Climb NS-19 bumps with 3D steer + vertical arrival + floor snap
parent
510422d8a2
commit
6d00070c00
|
|
@ -193,6 +193,7 @@ shape = SubResource("BoxShape3D_obstacle")
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 0.9, -5)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 0.9, -5)
|
||||||
collision_layer = 2
|
collision_layer = 2
|
||||||
collision_mask = 1
|
collision_mask = 1
|
||||||
|
floor_snap_length = 0.22
|
||||||
script = ExtResource("2_player")
|
script = ExtResource("2_player")
|
||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Player" unique_id=1695755590]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="Player" unique_id=1695755590]
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,14 @@ extends CharacterBody3D
|
||||||
|
|
||||||
## NS-23: Nav agent suggests waypoints; arrival uses stored server goal only (not agent “finished”).
|
## NS-23: Nav agent suggests waypoints; arrival uses stored server goal only (not agent “finished”).
|
||||||
## `is_navigation_finished()` / internal target can clear early while we are still far from goal.
|
## `is_navigation_finished()` / internal target can clear early while we are still far from goal.
|
||||||
|
## NS-19 bumps: allow limited Y in `velocity` so `move_and_slide` can step up/down shallow hits.
|
||||||
|
|
||||||
const MOVE_SPEED: float = 5.0
|
const MOVE_SPEED: float = 5.0
|
||||||
const ARRIVE_EPS: float = 0.35
|
const ARRIVE_EPS: float = 0.35
|
||||||
|
## Must match NS-19 shallow bumps (~0.15 m rise); don’t clear goal while still below pick Y.
|
||||||
|
const VERT_ARRIVE_EPS: float = 0.16
|
||||||
|
const MAX_CLIMB_SPEED: float = 2.6
|
||||||
|
const MAX_DESCENT_SPEED: float = 2.2
|
||||||
## Outside this XZ distance to server goal, use nav corners; inside, steer straight to goal.
|
## Outside this XZ distance to server goal, use nav corners; inside, steer straight to goal.
|
||||||
const DIRECT_APPROACH_RADIUS: float = 0.85
|
const DIRECT_APPROACH_RADIUS: float = 0.85
|
||||||
|
|
||||||
|
|
@ -40,17 +45,26 @@ func snap_to_server(world_pos: Vector3) -> void:
|
||||||
_nav_agent.set_target_position(world_pos)
|
_nav_agent.set_target_position(world_pos)
|
||||||
|
|
||||||
|
|
||||||
|
func _steer_toward_world_point(point: Vector3) -> void:
|
||||||
|
var delta: Vector3 = point - global_position
|
||||||
|
if delta.length_squared() < 1e-8:
|
||||||
|
velocity = Vector3.ZERO
|
||||||
|
return
|
||||||
|
var desired: Vector3 = delta.normalized() * MOVE_SPEED
|
||||||
|
desired.y = clampf(desired.y, -MAX_DESCENT_SPEED, MAX_CLIMB_SPEED)
|
||||||
|
velocity = desired
|
||||||
|
|
||||||
|
|
||||||
func _physics_process(_delta: float) -> void:
|
func _physics_process(_delta: float) -> void:
|
||||||
if not _has_walk_goal:
|
if not _has_walk_goal:
|
||||||
velocity = Vector3.ZERO
|
velocity = Vector3.ZERO
|
||||||
move_and_slide()
|
move_and_slide()
|
||||||
return
|
return
|
||||||
|
|
||||||
var to_goal: Vector3 = Vector3(
|
var full_to_goal: Vector3 = _auth_walk_goal - global_position
|
||||||
_auth_walk_goal.x - global_position.x, 0.0, _auth_walk_goal.z - global_position.z
|
var horiz_dist: float = Vector2(full_to_goal.x, full_to_goal.z).length()
|
||||||
)
|
var vert_err: float = absf(full_to_goal.y)
|
||||||
var dist_goal: float = to_goal.length()
|
if horiz_dist <= ARRIVE_EPS and vert_err <= VERT_ARRIVE_EPS:
|
||||||
if dist_goal <= ARRIVE_EPS:
|
|
||||||
velocity = Vector3.ZERO
|
velocity = Vector3.ZERO
|
||||||
_has_walk_goal = false
|
_has_walk_goal = false
|
||||||
_nav_agent.set_target_position(global_position)
|
_nav_agent.set_target_position(global_position)
|
||||||
|
|
@ -59,24 +73,20 @@ func _physics_process(_delta: float) -> void:
|
||||||
|
|
||||||
var nav_map: RID = _nav_agent.get_navigation_map()
|
var nav_map: RID = _nav_agent.get_navigation_map()
|
||||||
if NavigationServer3D.map_get_iteration_id(nav_map) == 0:
|
if NavigationServer3D.map_get_iteration_id(nav_map) == 0:
|
||||||
velocity = to_goal.normalized() * MOVE_SPEED
|
_steer_toward_world_point(_auth_walk_goal)
|
||||||
velocity.y = 0.0
|
|
||||||
move_and_slide()
|
move_and_slide()
|
||||||
return
|
return
|
||||||
|
|
||||||
var dir: Vector3
|
if horiz_dist <= DIRECT_APPROACH_RADIUS:
|
||||||
if dist_goal <= DIRECT_APPROACH_RADIUS:
|
_steer_toward_world_point(_auth_walk_goal)
|
||||||
dir = to_goal.normalized()
|
|
||||||
else:
|
else:
|
||||||
var next_path_position: Vector3 = _nav_agent.get_next_path_position()
|
var next_path_position: Vector3 = _nav_agent.get_next_path_position()
|
||||||
var to_next: Vector3 = Vector3(
|
var to_next_h: Vector3 = Vector3(
|
||||||
next_path_position.x - global_position.x, 0.0, next_path_position.z - global_position.z
|
next_path_position.x - global_position.x, 0.0, next_path_position.z - global_position.z
|
||||||
)
|
)
|
||||||
if to_next.length_squared() > 0.0025:
|
if to_next_h.length_squared() > 0.0025:
|
||||||
dir = to_next.normalized()
|
_steer_toward_world_point(next_path_position)
|
||||||
else:
|
else:
|
||||||
dir = to_goal.normalized()
|
_steer_toward_world_point(_auth_walk_goal)
|
||||||
|
|
||||||
velocity = dir * MOVE_SPEED
|
|
||||||
velocity.y = 0.0
|
|
||||||
move_and_slide()
|
move_and_slide()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue