navigation_introduction_2d.rst 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. .. _doc_navigation_overview_2d:
  2. 2D Navigation Overview
  3. ======================
  4. Godot provides multiple objects, classes and servers to facilitate grid-based or mesh-based navigation and pathfinding for 2D and 3D games.
  5. The following section provides a quick overview over all available navigation related objects in Godot for 2D scenes and their primary use.
  6. Godot provides the following objects and classes for 2D navigation:
  7. - :ref:`Astar2D<class_Astar2D>`
  8. ``Astar2D`` objects provide an option to find the shortest path in a graph of weighted **points**.
  9. The AStar2D class is best suited for cellbased 2D gameplay that does not require actors to reach any possible position within an area but only predefined, distinct positions.
  10. - :ref:`NavigationServer2D<class_NavigationServer2D>`
  11. ``NavigationServer2D`` provides a powerful server API to find the shortest path between two positions on a area defined by a navigation mesh.
  12. The NavigationServer is best suited for 2D realtime gameplay that does require actors to reach any possible position within an navmesh defined area.
  13. Meshbased navigation scales well with large gameworlds as a large area can often be defined with a single polygon when it would require many, many grid cells.
  14. The NavigationServer holds different navigation maps that each consist of regions that hold navigation mesh data.
  15. Agents can be placed on a map for avoidance calculation.
  16. RIDs are used to reference the internal maps, regions and agents when communicating with the server.
  17. The following NavigationServer RID types are available.
  18. - NavMap RID
  19. Reference to a specific navigation map that holds regions and agents.
  20. The map will attempt to join changed navigation meshes of regions by proximity.
  21. The map will synchronize regions and agents each physics frame.
  22. - NavRegion RID
  23. Reference to a specific navigation region that can hold navigation mesh data.
  24. The region can be enabled / disabled or the use restricted with a navigationlayer bitmask.
  25. - NavLink RID
  26. Reference to a specific navigation link that connects two navigation mesh positions over arbitrary distances.
  27. - NavAgent RID
  28. Reference to a specific avoidance agent with a radius value use solely in avoidance.
  29. The following SceneTree Nodes are available as helpers to work with the NavigationServer2D API.
  30. - :ref:`NavigationRegion2D<class_NavigationRegion2D>` Node
  31. A Node that holds a NavigationPolygon resource that defines a navigation mesh for the NavigationServer2D.
  32. - The region can be enabled / disabled.
  33. - The use in pathfinding can be further restricted through the navigationlayers bitmask.
  34. - Regions can join their navigation meshes by proximity for a combined navigation mesh.
  35. - :ref:`NavigationLink2D<class_NavigationLink2D>` Node
  36. A Node that connects two positions on navigation mesh over arbitrary distances for pathfinding.
  37. - The link can be enabled / disabled.
  38. - The link can be made one-way or bidirectional.
  39. - The use in pathfinding can be further restricted through the navigationlayers bitmask.
  40. Links tell the pathfinding that a connection exists and at what cost. The actual agent handling and movement needs to happen in custom scripts.
  41. - :ref:`NavigationAgent2D<class_NavigationAgent2D>` Node
  42. An optional helper Node to facilitate common NavigationServer2D API calls for pathfinding and avoidance
  43. for a Node2D inheriting parent Node.
  44. - :ref:`NavigationObstacle2D<class_NavigationObstacle2D>` Node
  45. A Node that acts as an agent with avoidance radius, to work it needs to be added under a Node2D
  46. inheriting parent Node. Obstacles are intended as a last resort option for constantly moving objects
  47. that cannot be re(baked) to a navigation mesh efficiently. This node also only works if RVO processing
  48. is being used.
  49. The 2D navigation meshes are defined with the following resources:
  50. - :ref:`NavigationPolygon<class_NavigationPolygon>` Resource
  51. A resource that holds 2D navigation mesh data and provides polygon drawtools to define navigation areas inside the Editor as well as at runtime.
  52. - The NavigationRegion2D Node uses this resource to define its navigation area.
  53. - The NavigationServer2D uses this resource to update navmesh of individual regions.
  54. - The TileSet Editor creates and uses this resource internally when defining tile navigation areas.
  55. .. seealso::
  56. You can see how 2D navigation works in action using the
  57. `2D Navigation Polygon <https://github.com/godotengine/godot-demo-projects/tree/master/2d/navigation>`__
  58. and `Grid-based Navigation with AStarGrid2D <https://github.com/godotengine/godot-demo-projects/tree/master/2d/navigation_astar>`__
  59. demo projects.
  60. Setup for 2D scene
  61. ------------------
  62. The following steps show the basic setup for a minimum viable navigation in 2D that uses the
  63. NavigationServer2D and a NavigationAgent2D for path movement.
  64. #. Add a NavigationRegion2D Node to the scene.
  65. #. Click on the region node and add a new NavigationPolygon Resource to the region node.
  66. .. image:: img/nav_2d_min_setup_step1.png
  67. #. Define the moveable navigation area with the NavigationPolygon draw tool.
  68. .. image:: img/nav_2d_min_setup_step2.png
  69. .. note::
  70. The navigation mesh defines the area where an actor can stand and move with its center.
  71. Leave enough margin between the navpolygon edges and collision objects to not get path
  72. following actors repeatedly stuck on collision.
  73. #. Add a CharacterBody2D node in the scene with a basic collision shape and a sprite or mesh
  74. for visuals.
  75. #. Add a NavigationAgent2D node below the character node.
  76. .. image:: img/nav_2d_min_setup_step3.webp
  77. #. Add the following script to the CharacterBody2D node. We make sure to set a movement target
  78. after the scene has fully loaded and the NavigationServer had time to sync.
  79. .. tabs::
  80. .. code-tab:: gdscript GDScript
  81. extends CharacterBody2D
  82. var movement_speed: float = 200.0
  83. var movement_target_position: Vector2 = Vector2(60.0,180.0)
  84. @onready var navigation_agent: NavigationAgent2D = $NavigationAgent2D
  85. func _ready():
  86. # These values need to be adjusted for the actor's speed
  87. # and the navigation layout.
  88. navigation_agent.path_desired_distance = 4.0
  89. navigation_agent.target_desired_distance = 4.0
  90. # Make sure to not await during _ready.
  91. call_deferred("actor_setup")
  92. func actor_setup():
  93. # Wait for the first physics frame so the NavigationServer can sync.
  94. await get_tree().physics_frame
  95. # Now that the navigation map is no longer empty, set the movement target.
  96. set_movement_target(movement_target_position)
  97. func set_movement_target(movement_target: Vector2):
  98. navigation_agent.target_position = movement_target
  99. func _physics_process(delta):
  100. if navigation_agent.is_navigation_finished():
  101. return
  102. var current_agent_position: Vector2 = global_position
  103. var next_path_position: Vector2 = navigation_agent.get_next_path_position()
  104. var new_velocity: Vector2 = next_path_position - current_agent_position
  105. new_velocity = new_velocity.normalized()
  106. new_velocity = new_velocity * movement_speed
  107. velocity = new_velocity
  108. move_and_slide()
  109. .. code-tab:: csharp C#
  110. using Godot;
  111. public partial class MyCharacterBody2D : CharacterBody2D
  112. {
  113. private NavigationAgent2D _navigationAgent;
  114. private float _movementSpeed = 200.0f;
  115. private Vector2 _movementTargetPosition = new Vector2(70.0f, 226.0f);
  116. public Vector2 MovementTarget
  117. {
  118. get { return _navigationAgent.TargetPosition; }
  119. set { _navigationAgent.TargetPosition = value; }
  120. }
  121. public override void _Ready()
  122. {
  123. base._Ready();
  124. _navigationAgent = GetNode<NavigationAgent2D>("NavigationAgent2D");
  125. // These values need to be adjusted for the actor's speed
  126. // and the navigation layout.
  127. _navigationAgent.PathDesiredDistance = 4.0f;
  128. _navigationAgent.TargetDesiredDistance = 4.0f;
  129. // Make sure to not await during _Ready.
  130. Callable.From(ActorSetup).CallDeferred();
  131. }
  132. public override void _PhysicsProcess(double delta)
  133. {
  134. base._PhysicsProcess(delta);
  135. if (_navigationAgent.IsNavigationFinished())
  136. {
  137. return;
  138. }
  139. Vector2 currentAgentPosition = GlobalTransform.Origin;
  140. Vector2 nextPathPosition = _navigationAgent.GetNextPathPosition();
  141. Vector2 newVelocity = (nextPathPosition - currentAgentPosition).Normalized();
  142. newVelocity *= _movementSpeed;
  143. Velocity = newVelocity;
  144. MoveAndSlide();
  145. }
  146. private async void ActorSetup()
  147. {
  148. // Wait for the first physics frame so the NavigationServer can sync.
  149. await ToSignal(GetTree(), SceneTree.SignalName.PhysicsFrame);
  150. // Now that the navigation map is no longer empty, set the movement target.
  151. MovementTarget = _movementTargetPosition;
  152. }
  153. }
  154. .. note::
  155. On the first frame the NavigationServer map has not synchronized region data and any path query
  156. will return empty. Await one frame to pause scripts until the NavigationServer had time to sync.