Sfoglia il codice sorgente

Use NavigationAgent3D in 3D Navigation demo (#975)

Co-authored-by: Hugo Locurcio <[email protected]>
David Briscoe 1 anno fa
parent
commit
1b61bc4bb0

+ 45 - 0
3d/navigation/character.gd

@@ -0,0 +1,45 @@
+extends Marker3D
+
+
+const Line3D = preload("res://line3d.gd")
+
+@export var character_speed := 10.0
+@export var show_path := true
+
+@onready var _nav_agent := $NavigationAgent3D as NavigationAgent3D
+
+var _nav_path_line : Line3D
+
+
+func _ready():
+	_nav_path_line = Line3D.new()
+	add_child(_nav_path_line)
+	_nav_path_line.set_as_top_level(true)
+
+
+func _physics_process(delta):
+	if _nav_agent.is_navigation_finished():
+		return
+	var next_position := _nav_agent.get_next_path_position()
+	var offset := next_position - global_position
+	global_position = global_position.move_toward(next_position, delta * character_speed)
+
+	# Make the robot look at the direction we're traveling.
+	# Clamp y to 0 so the robot only looks left and right, not up/down.
+	offset.y = 0
+	look_at(global_position + offset, Vector3.UP)
+
+
+func set_target_position(target_position: Vector3):
+	_nav_agent.set_target_position(target_position)
+	# Get a full navigation path with the NavigationServer API.
+	if show_path:
+		var start_position := global_transform.origin
+		var optimize := true
+		var navigation_map := get_world_3d().get_navigation_map()
+		var path := NavigationServer3D.map_get_path(
+				navigation_map,
+				start_position,
+				target_position,
+				optimize)
+		_nav_path_line.draw_path(path)

+ 22 - 0
3d/navigation/line3d.gd

@@ -0,0 +1,22 @@
+extends MeshInstance3D
+
+
+func _ready():
+	set_mesh(ImmediateMesh.new())
+	var material := StandardMaterial3D.new()
+	material.flags_unshaded = true
+	material.albedo_color = Color.WHITE
+	set_material_override(material)
+
+
+func draw_path(path):
+	var im: ImmediateMesh = mesh
+	im.clear_surfaces()
+	im.surface_begin(Mesh.PRIMITIVE_POINTS, null)
+	im.surface_add_vertex(path[0])
+	im.surface_add_vertex(path[path.size() - 1])
+	im.surface_end()
+	im.surface_begin(Mesh.PRIMITIVE_LINE_STRIP, null)
+	for current_vector in path:
+		im.surface_add_vertex(current_vector)
+	im.surface_end()

+ 18 - 72
3d/navigation/navmesh.gd

@@ -1,84 +1,30 @@
 extends Node3D
 
-const SPEED := 10.0
 
-@export var show_path := true
+const Character = preload("res://character.gd")
 
-var cam_rotation := 0.0
-var path: PackedVector3Array
+@onready var _camera := $CameraBase/Camera3D as Camera3D
+@onready var _robot := $RobotBase as Character
 
-@onready var robot: Marker3D = $RobotBase
-@onready var camera: Camera3D = $CameraBase/Camera3D
-
-func _ready():
-	set_process_input(true)
-
-
-func _physics_process(delta: float):
-	var direction := Vector3()
-
-	# We need to scale the movement speed by how much delta has passed,
-	# otherwise the motion won't be smooth.
-	var step_size := delta * SPEED
-
-	if not path.is_empty():
-		# Direction is the difference between where we are now
-		# and where we want to go.
-		var destination := path[0]
-		direction = destination - robot.position
-
-		# If the next node is closer than we intend to 'step', then
-		# take a smaller step. Otherwise we would go past it and
-		# potentially go through a wall or over a cliff edge!
-		if step_size > direction.length():
-			step_size = direction.length()
-			# We should also remove this node since we're about to reach it.
-			path.remove_at(0)
-
-		# Move the robot towards the path node, by how far we want to travel.
-		# TODO: This information should be set to the CharacterBody properties instead of arguments.
-		# Note: For a CharacterBody3D, we would instead use move_and_slide
-		# so collisions work properly.
-		robot.position += direction.normalized() * step_size
-
-		# Lastly let's make sure we're looking in the direction we're traveling.
-		# Clamp y to 0 so the robot only looks left and right, not up/down.
-		direction.y = 0
-		if direction:
-			# Direction is relative, so apply it to the robot's location to
-			# get a point we can actually look at.
-			var look_at_point := robot.position + direction.normalized()
-			# Make the robot look at the point.
-			robot.look_at(look_at_point, Vector3.UP)
+var _cam_rotation := 0.0
 
 
 func _unhandled_input(event: InputEvent):
 	if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
-		var map := get_world_3d().navigation_map
-		var from := camera.project_ray_origin(event.position)
-		var to := from + camera.project_ray_normal(event.position) * 1000
-		var target_point := NavigationServer3D.map_get_closest_point_to_segment(map, from, to)
-
-		# Set the path between the robot's current location and our target.
-		path = NavigationServer3D.map_get_path(map, robot.position, target_point, true)
-
-		if show_path:
-			draw_path(path)
+		# Get closest point on navmesh for the current mouse cursor position.
+		var mouse_cursor_position = event.position
+		var camera_ray_length := 1000.0
+		var camera_ray_start := _camera.project_ray_origin(mouse_cursor_position)
+		var camera_ray_end := camera_ray_start + _camera.project_ray_normal(mouse_cursor_position) * camera_ray_length
+
+		var closest_point_on_navmesh := NavigationServer3D.map_get_closest_point_to_segment(
+			get_world_3d().navigation_map,
+			camera_ray_start,
+			camera_ray_end
+			)
+		_robot.set_target_position(closest_point_on_navmesh)
 
 	elif event is InputEventMouseMotion:
 		if event.button_mask & (MOUSE_BUTTON_MASK_MIDDLE + MOUSE_BUTTON_MASK_RIGHT):
-			cam_rotation += event.relative.x * 0.005
-			$CameraBase.set_rotation(Vector3(0, cam_rotation, 0))
-
-
-func draw_path(path_array: PackedVector3Array) -> void:
-	var im: ImmediateMesh = $DrawPath.mesh
-	im.clear_surfaces()
-	im.surface_begin(Mesh.PRIMITIVE_POINTS, null)
-	im.surface_add_vertex(path_array[0])
-	im.surface_add_vertex(path_array[path_array.size() - 1])
-	im.surface_end()
-	im.surface_begin(Mesh.PRIMITIVE_LINE_STRIP, null)
-	for current_vector in path:
-		im.surface_add_vertex(current_vector)
-	im.surface_end()
+			_cam_rotation += event.relative.x * 0.005
+			$CameraBase.set_rotation(Vector3.UP * _cam_rotation)

BIN
3d/navigation/navmesh.res


+ 11 - 16
3d/navigation/navmesh.tscn

@@ -1,9 +1,10 @@
-[gd_scene load_steps=10 format=3 uid="uid://dkhg8e00d02f2"]
+[gd_scene load_steps=9 format=3 uid="uid://dkhg8e00d02f2"]
 
 [ext_resource type="Script" path="res://navmesh.gd" id="1"]
-[ext_resource type="NavigationMesh" uid="uid://xl4o2ckjxava" path="res://navmesh.res" id="2_lcfvj"]
-[ext_resource type="ArrayMesh" uid="uid://gmytdjp2bcsq" path="res://level_mesh.res" id="3_1cas0"]
-[ext_resource type="ArrayMesh" uid="uid://prwe6io8p1iv" path="res://robot.res" id="5_ple0n"]
+[ext_resource type="NavigationMesh" uid="uid://ii7ckx3dvrs2" path="res://navmesh.res" id="2_lcfvj"]
+[ext_resource type="ArrayMesh" path="res://level_mesh.res" id="3_1cas0"]
+[ext_resource type="Script" path="res://character.gd" id="4_u7d3d"]
+[ext_resource type="ArrayMesh" path="res://robot.res" id="5_ple0n"]
 
 [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_ps07l"]
 sky_horizon_color = Color(0.64625, 0.65575, 0.67075, 1)
@@ -18,11 +19,6 @@ sky = SubResource("Sky_baxfs")
 tonemap_mode = 3
 tonemap_white = 6.0
 
-[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_noou6"]
-shading_mode = 0
-
-[sub_resource type="ImmediateMesh" id="ImmediateMesh_dvj5w"]
-
 [node name="Node3D" type="Node3D"]
 _import_path = NodePath(".")
 script = ExtResource("1")
@@ -31,24 +27,19 @@ script = ExtResource("1")
 environment = SubResource("Environment_c0if4")
 
 [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
-transform = Transform3D(0.623013, -0.733525, 0.271653, 0.321394, 0.55667, 0.766045, -0.713134, -0.389948, 0.582563, 10.0773, 5.02381, 0)
-light_energy = 5.0
+transform = Transform3D(-0.723713, -0.678436, -0.12635, -0.277002, 0.11789, 0.95361, -0.632068, 0.725139, -0.273247, 10.0773, 5.02381, 0)
 shadow_enabled = true
 directional_shadow_mode = 0
 directional_shadow_fade_start = 1.0
 directional_shadow_max_distance = 35.0
 
 [node name="NavigationRegion3D" type="NavigationRegion3D" parent="."]
-navmesh = ExtResource("2_lcfvj")
+navigation_mesh = ExtResource("2_lcfvj")
 
 [node name="LevelMesh" type="MeshInstance3D" parent="NavigationRegion3D"]
 transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, 0, -0.0452547, 0)
 mesh = ExtResource("3_1cas0")
 
-[node name="DrawPath" type="MeshInstance3D" parent="."]
-material_override = SubResource("StandardMaterial3D_noou6")
-mesh = SubResource("ImmediateMesh_dvj5w")
-
 [node name="CameraBase" type="Node3D" parent="."]
 transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.07475, 0, 1.96678)
 
@@ -58,8 +49,12 @@ fov = 50.0
 near = 0.1
 
 [node name="RobotBase" type="Marker3D" parent="."]
+script = ExtResource("4_u7d3d")
 
 [node name="Robot" type="MeshInstance3D" parent="RobotBase"]
 transform = Transform3D(-0.5, 0, -7.54979e-08, 0, 1, 0, 7.54979e-08, 0, -0.5, 0, 1, 0)
 gi_mode = 2
 mesh = ExtResource("5_ple0n")
+
+[node name="NavigationAgent3D" type="NavigationAgent3D" parent="RobotBase"]
+path_desired_distance = 0.1

BIN
3d/navigation/particle.png


+ 0 - 36
3d/navigation/particle.png.import

@@ -1,36 +0,0 @@
-[remap]
-
-importer="texture"
-type="CompressedTexture2D"
-uid="uid://c27ndr5sgvyr8"
-path.s3tc="res://.godot/imported/particle.png-c2ba3d91e96c62035d672392a1197218.s3tc.ctex"
-path.etc2="res://.godot/imported/particle.png-c2ba3d91e96c62035d672392a1197218.etc2.ctex"
-metadata={
-"imported_formats": ["s3tc", "etc2"],
-"vram_texture": true
-}
-
-[deps]
-
-source_file="res://particle.png"
-dest_files=["res://.godot/imported/particle.png-c2ba3d91e96c62035d672392a1197218.s3tc.ctex", "res://.godot/imported/particle.png-c2ba3d91e96c62035d672392a1197218.etc2.ctex"]
-
-[params]
-
-compress/mode=2
-compress/lossy_quality=0.7
-compress/hdr_compression=1
-compress/bptc_ldr=0
-compress/normal_map=0
-compress/channel_pack=0
-mipmaps/generate=false
-mipmaps/limit=-1
-roughness/mode=0
-roughness/src_normal=""
-process/fix_alpha_border=true
-process/premult_alpha=false
-process/normal_map_invert_y=false
-process/hdr_as_srgb=false
-process/hdr_clamp_exposure=false
-process/size_limit=0
-detect_3d/compress_to=1