navigation_using_navigationmeshes.rst 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. .. _doc_navigation_using_navigationmeshes:
  2. Using NavigationMeshes
  3. ======================
  4. 2D and 3D version of the navigation mesh are available as
  5. :ref:`NavigationPolygon<class_NavigationPolygon>` and
  6. :ref:`NavigationMesh<class_NavigationMesh>` respectively.
  7. .. _doc_navigation_navmesh_baking:
  8. Creating 2D NavigationMeshes
  9. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  10. Navigation meshes in the 2D editor are created with the help of the NavigationPolygon draw tools
  11. that appear in the top bar of the editor when a NavigationRegion2D is selected.
  12. .. image:: img/nav_polydrawtool.png
  13. The NavigationPolygon draw tools can be used to create and edit navigation meshes by defining ``outline`` polygons.
  14. The outline polygons are later converted to real NavigationMesh resources for the NavigationServer regions.
  15. .. image:: img/nav_polymatroschka.png
  16. Multiple outlines can be added to the same NavPolygon resource as long as they **do not intersect or overlap**.
  17. Each additional outline will cut a hole in the polygon created by the larger outline.
  18. If the larger polygon is already a hole it will create a new navigation mesh polygon inside.
  19. Outlines are not a replacement if the intention is to merge aligned polygons e.g. from grid cells.
  20. Outlines, as the name would suggest, cannot intersect each other or have any overlapping vertex positions.
  21. .. image:: img/nav_polyoutlinefail.png
  22. Outline layouts like seen in this picture will fail the convex partitioning required by the navigation mesh generation.
  23. In this layout cases the outline tool cannot be used. Use the :ref:`Geometry2D<class_Geometry2D>` class for
  24. polygon merge or intersect operations to create a valid merged mesh for navigation.
  25. .. note::
  26. The NavigationServer does not connect navigation mesh islands from the same NavigationMesh resource.
  27. Do not create multiple disconnected islands in the same NavigationRegion2D and NavPoly resource if they should be later connected.
  28. For 2D no similar navigation mesh baking with geometry parsing exists like in 3D.
  29. The Geometry2D class functions for offset, merge, intersect and clip can be used
  30. to shrink or enlarge existing NavigationPolygons to different actor sizes.
  31. Creating 3D NavigationMeshes
  32. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  33. .. image:: img/baked_navmesh.png
  34. Navigation meshes in the 3D editor are created with the help of the
  35. :ref:`NavigationMeshGenerator<class_NavigationMeshGenerator>` singleton
  36. and the NavigationMesh bake settings that appear in the editor inspector.
  37. NavigationMesh baking is the process of creating a simplified mesh used for pathfinding out of (complex) 3D level geometry.
  38. For this process Godot parses scene geometry and hands the raw mesh or collision data to the
  39. third-party ReCast library for processing and creation of the final navigationmesh.
  40. The resulting NavigationMesh is an approximation of the source geometry surfaces
  41. for both performance and technical reasons. Do not expect the NavigationMesh
  42. to perfectly follow the original surfaces. Especially navigation polygons placed
  43. over ramps will not keep an equal distance to the ground surface. To align an
  44. actor perfectly with the ground use other means like physics.
  45. .. warning::
  46. Meshes need to be triangulated to work as navigation meshes. Other mesh face formats like quad or ngon are not supported.
  47. NavigationMesh rebaking at runtime
  48. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  49. To rebake a ``NavigationMesh`` at runtime, use the NavigationRegion3D.bake_navigation_mesh() function.
  50. Another option is to use the NavigationMeshGenerator.bake() Singleton function with the NavigationMesh resource directly.
  51. If the navigation mesh resource is already prepared, the region can be updated with the NavigationServer3D API directly as well.
  52. .. tabs::
  53. .. code-tab:: gdscript GDScript
  54. extends NavigationRegion3D
  55. func update_navigation_mesh():
  56. # use bake and update function of region
  57. var on_thread : bool = true
  58. bake_navigation_mesh(on_thread)
  59. # or use the NavigationMeshGenerator Singleton
  60. var _navigationmesh : NavigationMesh = navigation_mesh
  61. NavigationMeshGenerator.bake(_navigationmesh, self)
  62. # remove old resource first to trigger a full update
  63. navigation_mesh = null
  64. navigation_mesh = _navigationmesh
  65. # or use NavigationServer API to update region with prepared navigation mesh
  66. var region_rid : RID = get_region_rid()
  67. NavigationServer3D.region_set_navigation_mesh(region_rid, navigation_mesh)
  68. .. note::
  69. Baking a NavigationMesh at runtime is a costly operation.
  70. Complex navigation mesh take some time to bake and if done on the main thread can freeze a game.
  71. (Re)baking a large navigation mesh is preferably done in a separate thread.
  72. .. warning::
  73. Property values on a NavigationMesh resource like ``cell_size`` need
  74. to match the actual mesh data stored inside in order to merge
  75. different navigation meshes without issues.
  76. NavigationRegion2D and Navigation3D both use meshes to mark traversable areas, only the tools to create them are different.
  77. For 2D NavigationPolygon resources are used to draw outline points in the editor. From these outline points the NavigationServer2D creates a mesh to upload navigation data to the NavigationServer.
  78. For 3D NavigationMesh resources are used. Instead of providing draw tools the 3D variant
  79. provides an extensive amount of parameters to bake a navigation mesh directly from 3D source geometry.
  80. .. note::
  81. Technically there is no hard distinction between 2D and 3D how to use the given toolsets to create flat navigation meshes. The 2D drawing tool can be used to create a flat 3D navmesh and the 3D baking tool can be used to parse flat 3D geometry into 2D appropriated navigationmeshes.
  82. 2D Navmesh from CollisionPolygons
  83. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  84. The following script parses all child nodes of a NavigationRegion2D for CollisionPolygons
  85. and bakes their shape into the NavigationPolygon. As the NavigationPolygon creates the
  86. navigationmesh from outline data the shapes cannot overlap.
  87. .. tabs::
  88. .. code-tab:: gdscript GDScript
  89. extends NavigationRegion2D
  90. var new_navigation_polygon : NavigationPolygon = get_navigation_polygon()
  91. func _ready():
  92. parse_2d_collisionshapes(self)
  93. new_navigation_polygon.make_polygons_from_outlines()
  94. set_navigation_polygon(new_navigation_polygon)
  95. func parse_2d_collisionshapes(root_node : Node2D):
  96. for node in root_node.get_children():
  97. if node.get_child_count() > 0:
  98. parse_2d_collisionshapes(node)
  99. if node is CollisionPolygon2D:
  100. var new_collision_outline : PackedVector2Array = PackedVector2Array()
  101. var collisionpolygon_transform : Transform2D = node.get_global_transform()
  102. var collisionpolygon : CollisionPolygon2D = node.get_polygon()
  103. for vertex in collisionpolygon:
  104. new_collision_outline.append(collisionpolygon_transform.xform(vertex))
  105. new_navigation_polygon.add_outline(new_collision_outline)
  106. Procedual 2D NavigationMesh
  107. ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  108. The following script creates a new 2D navigation region and fills it with procedual generated navigation mesh data from a NavigationPolygon resource.
  109. .. tabs::
  110. .. code-tab:: gdscript GDScript
  111. extends Node2D
  112. var new_2d_region_rid : RID = NavigationServer2D.region_create()
  113. var default_2d_map_rid : RID = get_world_2d().get_navigation_map()
  114. NavigationServer2D.region_set_map(new_2d_region_rid, default_2d_map_rid)
  115. var new_navigation_polygon : NavigationPolygon = NavigationPolygon.new()
  116. var new_outline : PackedVector2Array = PackedVector2Array([
  117. Vector2(0.0, 0.0),
  118. Vector2(50.0, 0.0),
  119. Vector2(50.0, 50.0),
  120. Vector2(0.0, 50.0),
  121. ])
  122. new_navigation_polygon.add_outline(new_outline)
  123. new_navigation_polygon.make_polygons_from_outlines()
  124. NavigationServer2D.region_set_navigation_polygon(new_2d_region_rid, new_navigation_polygon)
  125. Procedual 3D NavigationMesh
  126. ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  127. The following script creates a new 3D navigation region and fills it with procedual generated navigation mesh data from a NavigationMesh resource.
  128. .. tabs::
  129. .. code-tab:: gdscript GDScript
  130. extends Node3D
  131. var new_3d_region_rid : RID = NavigationServer3D.region_create()
  132. var default_3d_map_rid : RID = get_world_3d().get_navigation_map()
  133. NavigationServer3D.region_set_map(new_3d_region_rid, default_3d_map_rid)
  134. var new_navigation_mesh : NavigationMesh = NavigationMesh.new()
  135. var new_plane_mesh : PlaneMesh = PlaneMesh.new()
  136. new_plane_mesh.size = Vector2(10.0, 10.0)
  137. new_navigation_mesh.create_from_mesh(new_plane_mesh)
  138. NavigationServer3D.region_set_navigation_mesh(new_3d_region_rid, new_navigation_mesh)
  139. Navmesh for 3D GridMaps
  140. ~~~~~~~~~~~~~~~~~~~~~~~
  141. The following script creates a new 3D navmesh from the mesh of a GridMap item, clears the current grid cells and adds new procedual grid cells with the new navmesh.
  142. .. tabs::
  143. .. code-tab:: gdscript GDScript
  144. extends GridMap
  145. # enable navigation mesh for grid items
  146. set_bake_navigation(true)
  147. # get mesh from grid item, bake and set a new navigation mesh for the library
  148. var gridmap_item_list : PackedInt32Array = mesh_library.get_item_list()
  149. for item in gridmap_item_list:
  150. var item_mesh : Mesh = mesh_library.get_item_mesh(item)
  151. var new_item_navigation_mesh : NavigationMesh = NavigationMesh.new()
  152. new_item_navigation_mesh.create_from_mesh(item_mesh)
  153. mesh_library.set_item_navigation_mesh(item, new_item_navigation_mesh)
  154. mesh_library.set_item_navigation_mesh_transform(item, Transform3D())
  155. # clear the cells
  156. clear()
  157. # add procedual cells using the first item
  158. var _position : Vector3i = Vector3i(global_transform.origin)
  159. var _item : int = 0
  160. var _orientation : int = 0
  161. for i in range(0,10):
  162. for j in range(0,10):
  163. _position.x = i
  164. _position.z = j
  165. gridmap.set_cell_item(_position, _item, _orientation)
  166. _position.x = -i
  167. _position.z = -j
  168. gridmap.set_cell_item(_position, _item, _orientation)