NS-23: skip nav waypoints on NS-19 bump plateaus only
Restore obstacle routing via waypoints elsewhere; on bump tops nav often prefers a downward segment and breaks departure. Detect plateau with is_on_floor + flat normal + ray down into group ns19_bump; then steer only toward authoritative goal xz. Slopes keep waypoint pathing.pull/23/head
parent
a5ec8df4a7
commit
db1fe0f46b
|
|
@ -138,7 +138,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.95, 0.22, -1.05)
|
||||||
mesh = SubResource("BoxMesh_marker")
|
mesh = SubResource("BoxMesh_marker")
|
||||||
surface_material_override/0 = SubResource("Mat_marker_base")
|
surface_material_override/0 = SubResource("Mat_marker_base")
|
||||||
|
|
||||||
[node name="NS19BumpA" type="StaticBody3D" parent="World/NavigationRegion3D" unique_id=1900001 groups=["walkable"]]
|
[node name="NS19BumpA" type="StaticBody3D" parent="World/NavigationRegion3D" unique_id=1900001 groups=["walkable", "ns19_bump"]]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.4, 0.075, -2.6)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.4, 0.075, -2.6)
|
||||||
collision_layer = 1
|
collision_layer = 1
|
||||||
|
|
||||||
|
|
@ -149,7 +149,7 @@ surface_material_override/0 = SubResource("Mat_ns19_bump")
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="World/NavigationRegion3D/NS19BumpA" unique_id=1900003]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="World/NavigationRegion3D/NS19BumpA" unique_id=1900003]
|
||||||
shape = SubResource("Convex_ns19a_frustum")
|
shape = SubResource("Convex_ns19a_frustum")
|
||||||
|
|
||||||
[node name="NS19BumpB" type="StaticBody3D" parent="World/NavigationRegion3D" unique_id=1900011 groups=["walkable"]]
|
[node name="NS19BumpB" type="StaticBody3D" parent="World/NavigationRegion3D" unique_id=1900011 groups=["walkable", "ns19_bump"]]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.85, 0.06, -4.1)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.85, 0.06, -4.1)
|
||||||
collision_layer = 1
|
collision_layer = 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
extends CharacterBody3D
|
extends CharacterBody3D
|
||||||
|
|
||||||
## NS-23: Nav waypoints + stored server goal for arrival.
|
## NS-23: Nav waypoints + stored server goal for arrival.
|
||||||
## NS-19: bump collision is one convex frustum (plateau + slopes); no autostep.
|
## NS-19: convex frustum bumps; `ns19_bump` group — on flat plateau skip nav waypoints (departure).
|
||||||
|
|
||||||
const MOVE_SPEED: float = 5.0
|
const MOVE_SPEED: float = 5.0
|
||||||
const ARRIVE_EPS: float = 0.35
|
const ARRIVE_EPS: float = 0.35
|
||||||
|
|
@ -11,6 +11,8 @@ const VERT_ARRIVE_EPS: float = 0.055
|
||||||
const MAX_CLIMB_SPEED: float = 2.6
|
const MAX_CLIMB_SPEED: float = 2.6
|
||||||
const MAX_DESCENT_SPEED: float = 2.2
|
const MAX_DESCENT_SPEED: float = 2.2
|
||||||
const DIRECT_APPROACH_RADIUS: float = 0.85
|
const DIRECT_APPROACH_RADIUS: float = 0.85
|
||||||
|
## Floor normal must be this “flat” to count as bump plateau (slopes use nav waypoints).
|
||||||
|
const NS19_BUMP_TOP_NORMAL_DOT: float = 0.992
|
||||||
|
|
||||||
var _has_walk_goal: bool = false
|
var _has_walk_goal: bool = false
|
||||||
var _auth_walk_goal: Vector3 = Vector3.ZERO
|
var _auth_walk_goal: Vector3 = Vector3.ZERO
|
||||||
|
|
@ -41,6 +43,33 @@ func snap_to_server(world_pos: Vector3) -> void:
|
||||||
_nav_agent.set_target_position(world_pos)
|
_nav_agent.set_target_position(world_pos)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_ns19_bump_plateau() -> bool:
|
||||||
|
if not is_on_floor():
|
||||||
|
return false
|
||||||
|
if get_floor_normal().dot(Vector3.UP) < NS19_BUMP_TOP_NORMAL_DOT:
|
||||||
|
return false
|
||||||
|
return _raycast_down_hits_group("ns19_bump", 2.5)
|
||||||
|
|
||||||
|
|
||||||
|
func _raycast_down_hits_group(group_name: String, cast_len: float) -> bool:
|
||||||
|
var space: PhysicsDirectSpaceState3D = get_world_3d().direct_space_state
|
||||||
|
var from: Vector3 = global_position
|
||||||
|
var to: Vector3 = from + Vector3(0.0, -cast_len, 0.0)
|
||||||
|
var q: PhysicsRayQueryParameters3D = PhysicsRayQueryParameters3D.create(from, to)
|
||||||
|
q.collision_mask = 1
|
||||||
|
q.exclude = [get_rid()]
|
||||||
|
var hit: Dictionary = space.intersect_ray(q)
|
||||||
|
if hit.is_empty():
|
||||||
|
return false
|
||||||
|
var col: Variant = hit.get("collider")
|
||||||
|
var n: Node = col as Node
|
||||||
|
while n:
|
||||||
|
if n.is_in_group(group_name):
|
||||||
|
return true
|
||||||
|
n = n.get_parent()
|
||||||
|
return false
|
||||||
|
|
||||||
|
|
||||||
func _steer_toward_world_point(point: Vector3) -> void:
|
func _steer_toward_world_point(point: Vector3) -> void:
|
||||||
var pos := global_position
|
var pos := global_position
|
||||||
var delta_h: Vector3 = Vector3(point.x - pos.x, 0.0, point.z - pos.z)
|
var delta_h: Vector3 = Vector3(point.x - pos.x, 0.0, point.z - pos.z)
|
||||||
|
|
@ -94,6 +123,14 @@ func _physics_process(_delta: float) -> void:
|
||||||
move_and_slide()
|
move_and_slide()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Nav waypoints on the plateau often point down the slope first; goal-only + horizontal steer
|
||||||
|
# matches the NS-19 departure fix. Slopes stay on waypoints so obstacle routing still applies
|
||||||
|
# when crossing the district.
|
||||||
|
if _on_ns19_bump_plateau():
|
||||||
|
_steer_toward_world_point(_auth_walk_goal)
|
||||||
|
move_and_slide()
|
||||||
|
return
|
||||||
|
|
||||||
if horiz_dist <= DIRECT_APPROACH_RADIUS:
|
if horiz_dist <= DIRECT_APPROACH_RADIUS:
|
||||||
_steer_toward_world_point(_auth_walk_goal)
|
_steer_toward_world_point(_auth_walk_goal)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue