mirror of
https://github.com/godotengine/godot-docs.git
synced 2026-01-05 22:09:56 +03:00
Update pages for 2D/3D Navigation Overview
- Add C# examples. - Fix the list formatting. - Fix punctuation. - Reference 2D explanation of the await in the 3D page. - Simplify comments in the 2D GDScript example.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
2D Navigation Overview
|
||||
======================
|
||||
|
||||
Godot provides multiple objects, classes and servers to facilitate grid-based or mesh-based navigation and pathfinding for 2D and 3D games.
|
||||
Godot provides multiple objects, classes and servers to facilitate grid-based or mesh-based navigation and pathfinding for 2D and 3D games.
|
||||
The following section provides a quick overview over all available navigation related objects in Godot for 2D scenes and their primary use.
|
||||
|
||||
Godot provides the following objects and classes for 2D navigation:
|
||||
@@ -67,33 +67,31 @@ Setup for 2D scene
|
||||
The following steps show the basic setup for a minimum viable navigation in 2D that uses the
|
||||
NavigationServer2D and a NavigationAgent2D for path movement.
|
||||
|
||||
1.) Add a NavigationRegion2D Node to the scene.
|
||||
#. Add a NavigationRegion2D Node to the scene.
|
||||
|
||||
2.) Click on the region node and add a new NavigationPolygon Resource to the region node
|
||||
#. Click on the region node and add a new NavigationPolygon Resource to the region node.
|
||||
|
||||
.. image:: img/nav_2d_min_setup_step1.png
|
||||
.. image:: img/nav_2d_min_setup_step1.png
|
||||
|
||||
3.) Define the moveable navigation area with the NavigationPolygon draw tool
|
||||
#. Define the moveable navigation area with the NavigationPolygon draw tool.
|
||||
|
||||
.. image:: img/nav_2d_min_setup_step2.png
|
||||
.. image:: img/nav_2d_min_setup_step2.png
|
||||
|
||||
.. note::
|
||||
.. note::
|
||||
|
||||
The navigation mesh defines the area where an actor can stand and move with its center.
|
||||
Leave enough margin between the navpolygon edges and collision objects to not get path following actors repeatedly stuck on collision.
|
||||
The navigation mesh defines the area where an actor can stand and move with its center.
|
||||
Leave enough margin between the navpolygon edges and collision objects to not get path
|
||||
following actors repeatedly stuck on collision.
|
||||
|
||||
4.) Add a CharacterBody2D below the region node with a basic collision shape and a sprite or mesh for visuals.
|
||||
#. Add a CharacterBody2D below the region node with a basic collision shape and a sprite or mesh
|
||||
for visuals.
|
||||
|
||||
5.) Add a NavigationAgent2D node below the character node
|
||||
#. Add a NavigationAgent2D node below the character node.
|
||||
|
||||
.. image:: img/nav_2d_min_setup_step3.png
|
||||
.. image:: img/nav_2d_min_setup_step3.png
|
||||
|
||||
6.) Add the following script to the CharacterBody2D node. Set a movement target with the set_movement_target() function after the scene has fully loaded and the NavigationServer had time to sync.
|
||||
|
||||
.. note::
|
||||
|
||||
On the first frame the NavigationServer map has not synchronised region data and any path query will return empty.
|
||||
Use ``await get_tree().physics_frame`` to pause scripts until the NavigationServer had time to sync.
|
||||
#. Add the following script to the CharacterBody2D node. We make sure to set a movement target
|
||||
after the scene has fully loaded and the NavigationServer had time to sync.
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
@@ -106,28 +104,25 @@ NavigationServer2D and a NavigationAgent2D for path movement.
|
||||
@onready var navigation_agent : NavigationAgent2D = $NavigationAgent2D
|
||||
|
||||
func _ready():
|
||||
# these values need to be adjusted for the actor's speed
|
||||
# and the navpolygon layout as each crossed edge will create a path point
|
||||
# If the actor moves to fast it might overshoot
|
||||
# multiple path points in one frame and start to backtrack
|
||||
# These values need to be adjusted for the actor's speed
|
||||
# and the navigation layout.
|
||||
navigation_agent.path_desired_distance = 4.0
|
||||
navigation_agent.target_desired_distance = 4.0
|
||||
|
||||
# make a deferred function call to assure the entire Scenetree is loaded
|
||||
# Make sure to not await during _ready.
|
||||
call_deferred("actor_setup")
|
||||
|
||||
func actor_setup():
|
||||
# wait for the first physics frame so the NavigationServer can sync
|
||||
# Wait for the first physics frame so the NavigationServer can sync.
|
||||
await get_tree().physics_frame
|
||||
|
||||
# now that the navigation map is no longer empty set the movement target
|
||||
# Now that the navigation map is no longer empty, set the movement target.
|
||||
set_movement_target(movement_target_position)
|
||||
|
||||
func set_movement_target(movement_target : Vector2):
|
||||
navigation_agent.set_target_location(movement_target)
|
||||
|
||||
func _physics_process(delta):
|
||||
|
||||
if navigation_agent.is_target_reached():
|
||||
return
|
||||
|
||||
@@ -141,3 +136,70 @@ NavigationServer2D and a NavigationAgent2D for path movement.
|
||||
set_velocity(new_velocity)
|
||||
|
||||
move_and_slide()
|
||||
|
||||
.. code-tab:: csharp C#
|
||||
|
||||
using Godot;
|
||||
|
||||
public partial class MyCharacterBody2D : CharacterBody2D
|
||||
{
|
||||
private NavigationAgent2D _navigationAgent;
|
||||
|
||||
private float _movementSpeed = 200.0f;
|
||||
private Vector2 _movementTargetPosition = new Vector2(70.0f, 226.0f);
|
||||
|
||||
public Vector2 MovementTarget
|
||||
{
|
||||
get { return _navigationAgent.TargetLocation; }
|
||||
set { _navigationAgent.TargetLocation = value; }
|
||||
}
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
base._Ready();
|
||||
|
||||
_navigationAgent = GetNode<NavigationAgent2D>("NavigationAgent2D");
|
||||
|
||||
// These values need to be adjusted for the actor's speed
|
||||
// and the navigation layout.
|
||||
_navigationAgent.PathDesiredDistance = 4.0f;
|
||||
_navigationAgent.TargetDesiredDistance = 4.0f;
|
||||
|
||||
// Make sure to not await during _Ready.
|
||||
Callable.From(ActorSetup).CallDeferred();
|
||||
}
|
||||
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
base._PhysicsProcess(delta);
|
||||
|
||||
if (_navigationAgent.IsTargetReached())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 currentAgentPosition = GlobalTransform.origin;
|
||||
Vector2 nextPathPosition = _navigationAgent.GetNextLocation();
|
||||
|
||||
Vector2 newVelocity = (nextPathPosition - currentAgentPosition).Normalized();
|
||||
newVelocity *= _movementSpeed;
|
||||
|
||||
Velocity = newVelocity;
|
||||
|
||||
MoveAndSlide();
|
||||
}
|
||||
|
||||
private async void ActorSetup()
|
||||
{
|
||||
// Wait for the first physics frame so the NavigationServer can sync.
|
||||
await ToSignal(GetTree(), SceneTree.SignalName.PhysicsFrame);
|
||||
|
||||
// Now that the navigation map is no longer empty, set the movement target.
|
||||
MovementTarget = _movementTargetPosition;
|
||||
}
|
||||
}
|
||||
|
||||
.. note::
|
||||
|
||||
On the first frame the NavigationServer map has not synchronised region data and any path query
|
||||
will return empty. Await one frame to pause scripts until the NavigationServer had time to sync.
|
||||
|
||||
@@ -72,31 +72,34 @@ Setup for 3D scene
|
||||
The following steps show how to setup a minimum viable navigation in 3D that uses the NavigationServer3D and
|
||||
a NavigationAgent3D for path movement.
|
||||
|
||||
1.) Add a NavigationRegion3D Node to the scene.
|
||||
#. Add a NavigationRegion3D Node to the scene.
|
||||
|
||||
2.) Click on the region node and add a new :ref:`NavigationMesh<class_NavigationMesh>` Resource to the region node
|
||||
#. Click on the region node and add a new :ref:`NavigationMesh<class_NavigationMesh>` Resource to
|
||||
the region node.
|
||||
|
||||
.. image:: img/nav_3d_min_setup_step1.png
|
||||
.. image:: img/nav_3d_min_setup_step1.png
|
||||
|
||||
3.) Add a new MeshInstance3D node as a child of the region node
|
||||
#. Add a new MeshInstance3D node as a child of the region node.
|
||||
|
||||
4.) Select the MeshInstance3D node and add a new PlaneMesh and increase the xy size to 10.
|
||||
#. Select the MeshInstance3D node and add a new PlaneMesh and increase the xy size to 10.
|
||||
|
||||
5.) Select the region node again and press the "Bake Navmesh" button on the top bar
|
||||
#. Select the region node again and press the "Bake Navmesh" button on the top bar.
|
||||
|
||||
.. image:: img/nav_3d_min_setup_step2.png
|
||||
.. image:: img/nav_3d_min_setup_step2.png
|
||||
|
||||
7.) Now a transparent navigation mesh appeared that hovers some distance on top the planemesh.
|
||||
#. Now a transparent navigation mesh appeared that hovers some distance on top the planemesh.
|
||||
|
||||
.. image:: img/nav_3d_min_setup_step3.png
|
||||
.. image:: img/nav_3d_min_setup_step3.png
|
||||
|
||||
8.) Add a CharacterBody3D below the region node with a basic collision shape and some mesh for visuals.
|
||||
#. Add a CharacterBody3D below the region node with a basic collision shape and some mesh for visuals.
|
||||
|
||||
9.) Add a NavigationAgent3D node below the character node
|
||||
#. Add a NavigationAgent3D node below the character node.
|
||||
|
||||
.. image:: img/nav_3d_min_setup_step4.png
|
||||
.. image:: img/nav_3d_min_setup_step4.png
|
||||
|
||||
10.) Add a script to the CharacterBody3D node with the following content.
|
||||
#. Add a script to the CharacterBody3D node with the following content. Set a movement target after
|
||||
the scene has fully loaded and the NavigationServer had time to sync. Also, add a Camera3D and some
|
||||
light and environment to see something.
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
@@ -122,10 +125,48 @@ a NavigationAgent3D for path movement.
|
||||
set_velocity(new_velocity)
|
||||
move_and_slide()
|
||||
|
||||
Set a movement target with the set_movement_target() function after the scene has fully loaded.
|
||||
Also add a Camera3D and some light and environment to see something.
|
||||
.. code-tab:: csharp C#
|
||||
|
||||
.. warning::
|
||||
using Godot;
|
||||
|
||||
On the first frame the NavigationServer map has not synchronised region data and any path query will return empty.
|
||||
Use ``await get_tree().physics_frame`` to pause scripts until the NavigationServer had time to sync.
|
||||
public partial class MyCharacterBody3D : CharacterBody3D
|
||||
{
|
||||
private float _movementSpeed = 0.3f;
|
||||
|
||||
private NavigationAgent3D _navigationAgent;
|
||||
|
||||
public Vector3 MovementTarget
|
||||
{
|
||||
get { _navigationAgent.TargetLocation; }
|
||||
set { _navigationAgent.TargetLocation = value; }
|
||||
}
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
base._Ready();
|
||||
|
||||
_navigationAgent = GetNode<NavigationAgent3D>("NavigationAgent3D");
|
||||
}
|
||||
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
base._PhysicsProcess(delta);
|
||||
|
||||
Vector3 currentAgentPosition = GlobalTransform.origin;
|
||||
Vector3 nextPathPosition = _navigationAgent.GetNextLocation();
|
||||
|
||||
Vector3 newVelocity = (nextPathPosition - currentAgentPosition).Normalized();
|
||||
newVelocity *= _movementSpeed;
|
||||
|
||||
Velocity = newVelocity;
|
||||
|
||||
MoveAndSlide();
|
||||
}
|
||||
}
|
||||
|
||||
.. note::
|
||||
|
||||
On the first frame the NavigationServer map has not synchronised region data and any path query
|
||||
will return empty. Await one frame to pause scripts until the NavigationServer had time to sync.
|
||||
|
||||
You can find more details about this in the :ref:`2D Navigation Overview page <doc_navigation_overview_2d>`.
|
||||
|
||||
Reference in New Issue
Block a user