navigation_using_navigationmeshes.rst 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. .. _doc_navigation_using_navigationmeshes:
  2. Using navigation meshes
  3. =======================
  4. .. image:: img/nav_meshes.webp
  5. 2D and 3D versions of the navigation mesh are available as
  6. :ref:`NavigationPolygon<class_NavigationPolygon>` and
  7. :ref:`NavigationMesh<class_NavigationMesh>` respectively.
  8. .. note::
  9. A navigation mesh only describes a traversable area for an agent's center position. Any radius values an agent may have are ignored.
  10. If you want pathfinding to account for an agent's (collision) size you need to shrink the navigation mesh accordingly.
  11. Navigation works independently from other engine parts like rendering or physics.
  12. Navigation meshes are the only things considered when doing pathfinding, e.g. visuals and collision shapes for example are completely ignored by the navigation system.
  13. If you need to take other data (like visuals for example) into account when doing pathfinding, you need to adapt your navigation meshes accordingly.
  14. The process of factoring in navigation restrictions in navigation meshes is commonly referred to as navigation mesh baking.
  15. .. figure:: img/nav_mesh_vs_physics.webp
  16. :align: center
  17. :alt: Navigation mesh polygon convex vs concave comparison
  18. A navigation mesh describes a surface that an agent can stand on safely with its center compared to physics shapes that describe outer collision bounds.
  19. If you experience clipping or collision problems while following navigation paths, always remember that you need to tell the navigation system what your intentions are through an appropriate navigation mesh.
  20. By itself the navigation system will never know "this is a tree / rock / wall collision shape or visual mesh" because it only knows that "here I was told I can path safely because it is on a navigation mesh".
  21. .. _doc_navigation_navmesh_baking:
  22. Navigation mesh baking can be done either by using a :ref:`NavigationRegion2D<class_NavigationRegion2D>` or :ref:`NavigationRegion3D<class_NavigationRegion3D>`, or by using the
  23. :ref:`NavigationServer2D<class_NavigationServer2D>` and :ref:`NavigationServer3D<class_NavigationServer3D>` API directly.
  24. .. _doc_navigation_using_navigationmeshes_baking_navigation_mesh_with_navigationregion:
  25. Baking a navigation mesh with a NavigationRegion
  26. ------------------------------------------------
  27. .. figure:: img/nav_mesh_baking_steps.gif
  28. :align: center
  29. :alt: Navigation mesh baking steps
  30. Baking a navigation mesh with agent radius offset from geometry.
  31. The navigation mesh baking is made more accessible with the NavigationRegion node. When baking with a NavigationRegion
  32. node, the individual parsing, baking, and region update steps are all combined into one function.
  33. The nodes are available in 2D and 3D as :ref:`NavigationRegion2D<class_NavigationRegion2D>` and :ref:`NavigationRegion3D<class_NavigationRegion3D>` respectively.
  34. .. tip::
  35. The navigation mesh ``source_geometry_mode`` can be switched to parse specific node group names so nodes that should be baked can be placed anywhere in the scene.
  36. .. tabs::
  37. .. tab:: Baking with a NavigationRegion2D
  38. When a NavigationRegion2D node is selected in the Editor, bake options as well as polygon draw tools appear in the top bar of the Editor.
  39. .. image:: img/nav_region_baking_01.webp
  40. In order for the region to work a :ref:`NavigationPolygon<class_NavigationPolygon>` resource needs to be added.
  41. The properties to parse and bake a navigation mesh are then part of the used resource and can be found in the resource Inspector.
  42. .. image:: img/nav_region_baking_02.webp
  43. The result of the source geometry parsing can be influenced with the following properties.
  44. - The ``parsed_geometry_type`` that filters if visual objects or physics objects or both should be parsed from the :ref:`SceneTree<class_SceneTree>`.
  45. For more details on what objects are parsed and how, see the section about parsing source geometry below.
  46. - The ``collision_mask`` filters which physics collision objects are included when the ``parsed_geometry_type`` includes static colliders.
  47. - The ``source_geometry_mode`` that defines on which node(s) to start the parsing, and how to traverse the :ref:`SceneTree<class_SceneTree>`.
  48. - The ``source_geometry_group_name`` is used when only a certain node group should be parsed. Depends on the selected ``source_geometry_mode``.
  49. With the source geometry added, the result of the baking can be controlled with the following properties.
  50. - The ``cell_size`` sets the rasterization grid size and should match the navigation map size.
  51. - The ``agent_radius`` shrinks the baked navigation mesh to have enough margin for the agent (collision) size.
  52. The NavigationRegion2D baking can also be used at runtime with scripts.
  53. .. tabs::
  54. .. code-tab:: gdscript GDScript
  55. var on_thread: bool = true
  56. bake_navigation_polygon(on_thread)
  57. .. code-tab:: csharp
  58. bool onThread = true;
  59. BakeNavigationPolygon(onThread);
  60. To quickly test the 2D baking with default settings:
  61. - Add a :ref:`NavigationRegion2D<class_NavigationRegion2D>`.
  62. - Add a :ref:`NavigationPolygon<class_NavigationPolygon>` resource to the NavigationRegion2D.
  63. - Add a :ref:`Polygon2D<class_Polygon2D>` below the NavigationRegion2D.
  64. - Draw 1 NavigationPolygon outline with the selected NavigationRegion2D draw tool.
  65. - Draw 1 Polygon2D outline inside the NavigationPolygon outline with the selected Polygon2D draw tool.
  66. - Hit the Editor bake button and a navigation mesh should appear.
  67. .. image:: img/nav_region_baking_01.webp
  68. .. image:: img/nav_mesh_mini_2d.webp
  69. .. tab:: Baking with a NavigationRegion3D
  70. When a NavigationRegion3D node is selected in the Editor, bake options appear in the top bar of the Editor.
  71. .. image:: img/nav_mesh_bake_toolbar.webp
  72. In order for the region to work a :ref:`NavigationMesh<class_NavigationMesh>` resource needs to be added.
  73. The properties to parse and bake a navigation mesh are then part of the used resource and can be found in the resource Inspector.
  74. .. image:: img/nav_region3d_baking_01.webp
  75. The result of the source geometry parsing can be influenced with the following properties.
  76. - The ``parsed_geometry_type`` that filters if visual objects or physics objects or both should be parsed from the :ref:`SceneTree<class_SceneTree>`.
  77. For more details on what objects are parsed and how, see the section about parsing source geometry below.
  78. - The ``collision_mask`` filters which physics collision objects are included when the ``parsed_geometry_type`` includes static colliders.
  79. - The ``source_geometry_mode`` that defines on which node(s) to start the parsing, and how to traverse the :ref:`SceneTree<class_SceneTree>`.
  80. - The ``source_geometry_group_name`` is used when only a certain node group should be parsed. Depends on the selected ``source_geometry_mode``.
  81. With the source geometry added, the result of the baking can be controlled with the following properties.
  82. - The ``cell_size`` and ``cell_height`` sets the rasterization voxel grid size and should match the navigation map size.
  83. - The ``agent_radius`` shrinks the baked navigation mesh to have enough margin for the agent (collision) size.
  84. - The ``agent_height`` excludes areas from the navigation mesh where the agent is too tall to fit in.
  85. - The ``agent_max_climb`` and ``agent_max_slope`` removes areas where the height difference between neighboring voxels is too large, or where their surface is too steep.
  86. .. warning::
  87. A too small ``cell_size`` or ``cell_height`` can create so many voxels that it has the potential to freeze the game or even crash.
  88. The NavigationRegion3D baking can also be used at runtime with scripts.
  89. .. tabs::
  90. .. code-tab:: gdscript GDScript
  91. var on_thread: bool = true
  92. bake_navigation_mesh(on_thread)
  93. .. code-tab:: csharp
  94. bool onThread = true;
  95. BakeNavigationMesh(onThread);
  96. To quickly test the 3D baking with default settings:
  97. - Add a :ref:`NavigationRegion3D<class_NavigationRegion3D>`.
  98. - Add a :ref:`NavigationMesh<class_NavigationMesh>` resource to the NavigationRegion3D.
  99. - Add a :ref:`MeshInstance3D<class_MeshInstance3D>` below the NavigationRegion3D.
  100. - Add a :ref:`PlaneMesh<class_PlaneMesh>` to the MeshInstance3D.
  101. - Hit the Editor bake button and a navigation mesh should appear.
  102. .. image:: img/nav_mesh_bake_toolbar.webp
  103. .. image:: img/nav_mesh_mini_3d.webp
  104. .. _doc_navigation_using_navigationmeshes_baking_navigation_mesh_with_navigationserver:
  105. Baking a navigation mesh with the NavigationServer
  106. --------------------------------------------------
  107. The :ref:`NavigationServer2D<class_NavigationServer2D>` and :ref:`NavigationServer3D<class_NavigationServer3D>` have API functions to call each step of the navigation mesh baking process individually.
  108. - ``parse_source_geometry_data()`` can be used to parse source geometry to a reusable and serializable resource.
  109. - ``bake_from_source_geometry_data()`` can be used to bake a navigation mesh from already parsed data e.g. to avoid runtime performance issues with (redundant) parsing.
  110. - ``bake_from_source_geometry_data_async()`` is the same but bakes the navigation mesh deferred with threads, not blocking the main thread.
  111. Compared to a NavigationRegion, the NavigationServer offers finer control over the navigation mesh baking process.
  112. In turn it is more complex to use but also provides more advanced options.
  113. Some other advantages of the NavigationServer over a NavigationRegion are:
  114. - The server can parse source geometry without baking, e.g. to cache it for later use.
  115. - The server allows selecting the root node at which to start the source geometry parsing manually.
  116. - The server can accept and bake from procedurally generated source geometry data.
  117. - The server can bake multiple navigation meshes in sequence while (re)using the same source geometry data.
  118. To bake navigation meshes with the NavigationServer, source geometry is required.
  119. Source geometry is geometry data that should be considered in a navigation mesh baking process.
  120. Both navigation meshes for 2D and 3D are created by baking them from source geometry.
  121. 2D and 3D versions of the source geometry resources are available as
  122. :ref:`NavigationMeshSourceGeometryData2D<class_NavigationMeshSourceGeometryData2D>` and
  123. :ref:`NavigationMeshSourceGeometryData3D<class_NavigationMeshSourceGeometryData3D>` respectively.
  124. Source geometry can be geometry parsed from visual meshes, from physics collision,
  125. or procedural created arrays of data, like outlines (2D) and triangle faces (3D).
  126. For convenience, source geometry is commonly parsed directly from node setups in the SceneTree.
  127. For runtime navigation mesh (re)bakes, be aware that the geometry parsing always happens on the main thread.
  128. .. note::
  129. The SceneTree is not thread-safe. Parsing source geometry from the SceneTree can only be done on the main thread.
  130. .. warning::
  131. The data from visual meshes and polygons needs to be received from the GPU, stalling the RenderingServer in the process.
  132. For runtime (re)baking prefer using physics shapes as parsed source geometry.
  133. Source geometry is stored inside resources so the created geometry can be reused for multiple bakes.
  134. E.g. baking multiple navigation meshes for different agent sizes from the same source geometry.
  135. This also allows to save source geometry to disk so it can be loaded later, e.g. to avoid the overhead of parsing it again at runtime.
  136. The geometry data should be in general kept very simple. As many edges as are required but as few as possible.
  137. Especially in 2D duplicated and nested geometry should be avoided as it forces polygon hole calculation that can result in flipped polygons.
  138. An example for nested geometry would be a smaller StaticBody2D shape placed completely inside the bounds of another StaticBody2D shape.
  139. Baking navigation mesh chunks for large worlds
  140. ----------------------------------------------
  141. .. figure:: img/navmesh_chunk_build.gif
  142. :align: center
  143. :alt: Building navigation mesh chunks
  144. Building and updating individual navigation mesh chunks at runtime.
  145. .. seealso::
  146. You can see the navigation mesh chunk baking in action in the
  147. `Navigation Mesh Chunks 2D <https://github.com/godotengine/godot-demo-projects/tree/master/2d/navigation_mesh_chunks>`__
  148. and `Navigation Mesh Chunks 3D <https://github.com/godotengine/godot-demo-projects/tree/master/3d/navigation_mesh_chunks>`__
  149. demo projects.
  150. To avoid misaligned edges between different region chunks the navigation meshes have two important properties
  151. for the navigation mesh baking process. The baking bound and the border size.
  152. Together they can be used to ensure perfectly aligned edges between region chunks.
  153. .. figure:: img/navmesh_bound_bordersize.webp
  154. :align: center
  155. :alt: Navigation mesh chunk with bake bound and border size
  156. Navigation mesh chunk baked with bake bound or baked with additional border size.
  157. The baking bound, which is an axis-aligned :ref:`Rect2<class_Rect2>` for 2D and :ref:`AABB<class_AABB>` for 3D,
  158. limits the used source geometry by discarding all the geometry that is outside of the bounds.
  159. The :ref:`NavigationPolygon<class_NavigationPolygon>` properties ``baking_rect`` and ``baking_rect_offset``
  160. can be used to create and place the 2D baking bound.
  161. The :ref:`NavigationMesh<class_NavigationMesh>` properties ``filter_baking_aabb`` and ``filter_baking_aabb_offset``
  162. can be used to create and place the 3D baking bound.
  163. With only the baking bound set another problem still exists. The resulting navigation mesh will
  164. inevitably be affected by necessary offsets like the ``agent_radius`` which makes the edges not align properly.
  165. .. figure:: img/navmesh_chunk_gaps.webp
  166. :align: center
  167. :alt: Navigation mesh chunks with gaps
  168. Navigation mesh chunks with noticeable gaps due to baked agent radius offset.
  169. This is where the ``border_size`` property for navigation mesh comes in. The border size is an inward margin
  170. from the baking bound. The important characteristic of the border size is that it is unaffected by most
  171. offsets and postprocessing like the ``agent_radius``.
  172. Instead of discarding source geometry, the border size discards parts of the final surface of the baked navigation mesh.
  173. If the baking bound is large enough the border size can remove the problematic surface
  174. parts so that only the intended chunk size is left.
  175. .. figure:: img/navmesh_chunks.webp
  176. :align: center
  177. :alt: Navigation mesh chunks without gaps
  178. Navigation mesh chunks with aligned edges and without gaps.
  179. .. note::
  180. The baking bounds need to be large enough to include a reasonable amount of source geometry from all the neighboring chunks.
  181. .. warning::
  182. In 3D the functionality of the border size is limited to the xz-axis.
  183. Navigation mesh baking common problems
  184. --------------------------------------
  185. There are some common user problems and important caveats to consider when creating or baking navigation meshes.
  186. - Navigation mesh baking creates frame rate problems at runtime
  187. The navigation mesh baking is by default done on a background thread, so as long as the platform supports threads, the actual baking is
  188. rarely the source of any performance issues (assuming a reasonably sized and complex geometry for runtime rebakes).
  189. The common source for performance issues at runtime is the parsing step for source geometry that involves nodes and the SceneTree.
  190. The SceneTree is not thread-safe so all the nodes need to be parsed on the main thread.
  191. Some nodes with a lot of data can be very heavy and slow to parse at runtime, e.g. a TileMap has one or more polygons for every single used cell and TileMapLayer to parse.
  192. Nodes that hold meshes need to request the data from the RenderingServer stalling the rendering in the process.
  193. To improve performance, use more optimized shapes, e.g. collision shapes over detailed visual meshes, and merge and simplify as much geometry as possible upfront.
  194. If nothing helps, don't parse the SceneTree and add the source geometry procedural with scripts. If only pure data arrays are used as source geometry, the entire baking process can be done on a background thread.
  195. - Navigation mesh creates unintended holes in 2D.
  196. The navigation mesh baking in 2D is done by doing polygon clipping operations based on outline paths.
  197. Polygons with "holes" are a necessary evil to create more complex 2D polygons but can become unpredictable for users with many complex shapes involved.
  198. To avoid any unexpected problems with polygon hole calculations, avoid nesting any outlines inside other outlines of the same type (traversable / obstruction).
  199. This includes the parsed shapes from nodes. E.g. placing a smaller StaticBody2D shape inside a larger StaticBody2D shape can result in the resulting polygon being flipped.
  200. - Navigation mesh appears inside geometry in 3D.
  201. The navigation mesh baking in 3D has no concept of "inside". The voxel cells used to rasterize the geometry are either occupied or not.
  202. Remove the geometry that is on the ground inside the other geometry. If that is not possible, add smaller "dummy" geometry inside with as few triangles as possible so the cells
  203. are occupied with something.
  204. A :ref:`NavigationObstacle3D<class_NavigationObstacle3D>` shape set to bake with navigation mesh can be used to discard geometry as well.
  205. .. figure:: img/nav_mesh_obstacles_discard.webp
  206. :align: center
  207. :alt: NavigationObstacle3D unwanted geometry discard
  208. A NavigationObstacle3D shape can be used to discard unwanted navigation mesh parts.
  209. Navigation mesh script templates
  210. --------------------------------
  211. The following script uses the NavigationServer to parse source geometry from the scene tree, bakes a navigation mesh, and updates a navigation region with the updated navigation mesh.
  212. .. tabs::
  213. .. code-tab:: gdscript 2D GDScript
  214. extends Node2D
  215. var navigation_mesh: NavigationPolygon
  216. var source_geometry : NavigationMeshSourceGeometryData2D
  217. var callback_parsing : Callable
  218. var callback_baking : Callable
  219. var region_rid: RID
  220. func _ready() -> void:
  221. navigation_mesh = NavigationPolygon.new()
  222. navigation_mesh.agent_radius = 10.0
  223. source_geometry = NavigationMeshSourceGeometryData2D.new()
  224. callback_parsing = on_parsing_done
  225. callback_baking = on_baking_done
  226. region_rid = NavigationServer2D.region_create()
  227. # Enable the region and set it to the default navigation map.
  228. NavigationServer2D.region_set_enabled(region_rid, true)
  229. NavigationServer2D.region_set_map(region_rid, get_world_2d().get_navigation_map())
  230. # Some mega-nodes like TileMap are often not ready on the first frame.
  231. # Also the parsing needs to happen on the main-thread.
  232. # So do a deferred call to avoid common parsing issues.
  233. parse_source_geometry.call_deferred()
  234. func parse_source_geometry() -> void:
  235. source_geometry.clear()
  236. var root_node: Node2D = self
  237. # Parse the obstruction outlines from all child nodes of the root node by default.
  238. NavigationServer2D.parse_source_geometry_data(
  239. navigation_mesh,
  240. source_geometry,
  241. root_node,
  242. callback_parsing
  243. )
  244. func on_parsing_done() -> void:
  245. # If we did not parse a TileMap with navigation mesh cells we may now only
  246. # have obstruction outlines so add at least one traversable outline
  247. # so the obstructions outlines have something to "cut" into.
  248. source_geometry.add_traversable_outline(PackedVector2Array([
  249. Vector2(0.0, 0.0),
  250. Vector2(500.0, 0.0),
  251. Vector2(500.0, 500.0),
  252. Vector2(0.0, 500.0)
  253. ]))
  254. # Bake the navigation mesh on a thread with the source geometry data.
  255. NavigationServer2D.bake_from_source_geometry_data_async(
  256. navigation_mesh,
  257. source_geometry,
  258. callback_baking
  259. )
  260. func on_baking_done() -> void:
  261. # Update the region with the updated navigation mesh.
  262. NavigationServer2D.region_set_navigation_polygon(region_rid, navigation_mesh)
  263. .. code-tab:: csharp 2D C#
  264. using Godot;
  265. public partial class MyNode2D : Node2D
  266. {
  267. private NavigationPolygon _navigationMesh;
  268. private NavigationMeshSourceGeometryData2D _sourceGeometry;
  269. private Callable _callbackParsing;
  270. private Callable _callbackBaking;
  271. private Rid _regionRid;
  272. public override void _Ready()
  273. {
  274. _navigationMesh = new NavigationPolygon();
  275. _navigationMesh.AgentRadius = 10.0f;
  276. _sourceGeometry = new NavigationMeshSourceGeometryData2D();
  277. _callbackParsing = Callable.From(OnParsingDone);
  278. _callbackBaking = Callable.From(OnBakingDone);
  279. _regionRid = NavigationServer2D.RegionCreate();
  280. // Enable the region and set it to the default navigation map.
  281. NavigationServer2D.RegionSetEnabled(_regionRid, true);
  282. NavigationServer2D.RegionSetMap(_regionRid, GetWorld2D().NavigationMap);
  283. // Some mega-nodes like TileMap are often not ready on the first frame.
  284. // Also the parsing needs to happen on the main-thread.
  285. // So do a deferred call to avoid common parsing issues.
  286. CallDeferred(MethodName.ParseSourceGeometry);
  287. }
  288. private void ParseSourceGeometry()
  289. {
  290. _sourceGeometry.Clear();
  291. Node2D rootNode = this;
  292. // Parse the obstruction outlines from all child nodes of the root node by default.
  293. NavigationServer2D.ParseSourceGeometryData(
  294. _navigationMesh,
  295. _sourceGeometry,
  296. rootNode,
  297. _callbackParsing
  298. );
  299. }
  300. private void OnParsingDone()
  301. {
  302. // If we did not parse a TileMap with navigation mesh cells we may now only
  303. // have obstruction outlines so add at least one traversable outline
  304. // so the obstructions outlines have something to "cut" into.
  305. _sourceGeometry.AddTraversableOutline(new Vector2[]
  306. {
  307. new Vector2(0.0f, 0.0f),
  308. new Vector2(500.0f, 0.0f),
  309. new Vector2(500.0f, 500.0f),
  310. new Vector2(0.0f, 500.0f),
  311. });
  312. // Bake the navigation mesh on a thread with the source geometry data.
  313. NavigationServer2D.BakeFromSourceGeometryDataAsync(_navigationMesh, _sourceGeometry, _callbackBaking);
  314. }
  315. private void OnBakingDone()
  316. {
  317. // Update the region with the updated navigation mesh.
  318. NavigationServer2D.RegionSetNavigationPolygon(_regionRid, _navigationMesh);
  319. }
  320. }
  321. .. code-tab:: gdscript 3D GDScript
  322. extends Node3D
  323. var navigation_mesh: NavigationMesh
  324. var source_geometry : NavigationMeshSourceGeometryData3D
  325. var callback_parsing : Callable
  326. var callback_baking : Callable
  327. var region_rid: RID
  328. func _ready() -> void:
  329. navigation_mesh = NavigationMesh.new()
  330. navigation_mesh.agent_radius = 0.5
  331. source_geometry = NavigationMeshSourceGeometryData3D.new()
  332. callback_parsing = on_parsing_done
  333. callback_baking = on_baking_done
  334. region_rid = NavigationServer3D.region_create()
  335. # Enable the region and set it to the default navigation map.
  336. NavigationServer3D.region_set_enabled(region_rid, true)
  337. NavigationServer3D.region_set_map(region_rid, get_world_3d().get_navigation_map())
  338. # Some mega-nodes like GridMap are often not ready on the first frame.
  339. # Also the parsing needs to happen on the main-thread.
  340. # So do a deferred call to avoid common parsing issues.
  341. parse_source_geometry.call_deferred()
  342. func parse_source_geometry() -> void:
  343. source_geometry.clear()
  344. var root_node: Node3D = self
  345. # Parse the geometry from all mesh child nodes of the root node by default.
  346. NavigationServer3D.parse_source_geometry_data(
  347. navigation_mesh,
  348. source_geometry,
  349. root_node,
  350. callback_parsing
  351. )
  352. func on_parsing_done() -> void:
  353. # Bake the navigation mesh on a thread with the source geometry data.
  354. NavigationServer3D.bake_from_source_geometry_data_async(
  355. navigation_mesh,
  356. source_geometry,
  357. callback_baking
  358. )
  359. func on_baking_done() -> void:
  360. # Update the region with the updated navigation mesh.
  361. NavigationServer3D.region_set_navigation_mesh(region_rid, navigation_mesh)
  362. .. code-tab:: csharp 3D C#
  363. using Godot;
  364. public partial class MyNode3D : Node3D
  365. {
  366. private NavigationMesh _navigationMesh;
  367. private NavigationMeshSourceGeometryData3D _sourceGeometry;
  368. private Callable _callbackParsing;
  369. private Callable _callbackBaking;
  370. private Rid _regionRid;
  371. public override void _Ready()
  372. {
  373. _navigationMesh = new NavigationMesh();
  374. _navigationMesh.AgentRadius = 0.5f;
  375. _sourceGeometry = new NavigationMeshSourceGeometryData3D();
  376. _callbackParsing = Callable.From(OnParsingDone);
  377. _callbackBaking = Callable.From(OnBakingDone);
  378. _regionRid = NavigationServer3D.RegionCreate();
  379. // Enable the region and set it to the default navigation map.
  380. NavigationServer3D.RegionSetEnabled(_regionRid, true);
  381. NavigationServer3D.RegionSetMap(_regionRid, GetWorld3D().NavigationMap);
  382. // Some mega-nodes like GridMap are often not ready on the first frame.
  383. // Also the parsing needs to happen on the main-thread.
  384. // So do a deferred call to avoid common parsing issues.
  385. CallDeferred(MethodName.ParseSourceGeometry);
  386. }
  387. private void ParseSourceGeometry ()
  388. {
  389. _sourceGeometry.Clear();
  390. Node3D rootNode = this;
  391. // Parse the geometry from all mesh child nodes of the root node by default.
  392. NavigationServer3D.ParseSourceGeometryData(
  393. _navigationMesh,
  394. _sourceGeometry,
  395. rootNode,
  396. _callbackParsing
  397. );
  398. }
  399. private void OnParsingDone()
  400. {
  401. // Bake the navigation mesh on a thread with the source geometry data.
  402. NavigationServer3D.BakeFromSourceGeometryDataAsync(_navigationMesh, _sourceGeometry, _callbackBaking);
  403. }
  404. private void OnBakingDone()
  405. {
  406. // Update the region with the updated navigation mesh.
  407. NavigationServer3D.RegionSetNavigationMesh(_regionRid, _navigationMesh);
  408. }
  409. }
  410. The following script uses the NavigationServer to update a navigation region with procedurally generated navigation mesh data.
  411. .. tabs::
  412. .. code-tab:: gdscript 2D GDScript
  413. extends Node2D
  414. var navigation_mesh: NavigationPolygon
  415. var region_rid: RID
  416. func _ready() -> void:
  417. navigation_mesh = NavigationPolygon.new()
  418. region_rid = NavigationServer2D.region_create()
  419. # Enable the region and set it to the default navigation map.
  420. NavigationServer2D.region_set_enabled(region_rid, true)
  421. NavigationServer2D.region_set_map(region_rid, get_world_2d().get_navigation_map())
  422. # Add vertices for a convex polygon.
  423. navigation_mesh.vertices = PackedVector2Array([
  424. Vector2(0.0, 0.0),
  425. Vector2(100.0, 0.0),
  426. Vector2(100.0, 100.0),
  427. Vector2(0.0, 100.0),
  428. ])
  429. # Add indices for the polygon.
  430. navigation_mesh.add_polygon(
  431. PackedInt32Array([0, 1, 2, 3])
  432. )
  433. NavigationServer2D.region_set_navigation_polygon(region_rid, navigation_mesh)
  434. .. code-tab:: csharp 2D C#
  435. using Godot;
  436. public partial class MyNode2D : Node2D
  437. {
  438. private NavigationPolygon _navigationMesh;
  439. private Rid _regionRid;
  440. public override void _Ready()
  441. {
  442. _navigationMesh = new NavigationPolygon();
  443. _regionRid = NavigationServer2D.RegionCreate();
  444. // Enable the region and set it to the default navigation map.
  445. NavigationServer2D.RegionSetEnabled(_regionRid, true);
  446. NavigationServer2D.RegionSetMap(_regionRid, GetWorld2D().NavigationMap);
  447. // Add vertices for a convex polygon.
  448. _navigationMesh.Vertices = new Vector2[]
  449. {
  450. new Vector2(0, 0),
  451. new Vector2(100.0f, 0),
  452. new Vector2(100.0f, 100.0f),
  453. new Vector2(0, 100.0f),
  454. };
  455. // Add indices for the polygon.
  456. _navigationMesh.AddPolygon(new int[] { 0, 1, 2, 3 });
  457. NavigationServer2D.RegionSetNavigationPolygon(_regionRid, _navigationMesh);
  458. }
  459. }
  460. .. code-tab:: gdscript 3D GDScript
  461. extends Node3D
  462. var navigation_mesh: NavigationMesh
  463. var region_rid: RID
  464. func _ready() -> void:
  465. navigation_mesh = NavigationMesh.new()
  466. region_rid = NavigationServer3D.region_create()
  467. # Enable the region and set it to the default navigation map.
  468. NavigationServer3D.region_set_enabled(region_rid, true)
  469. NavigationServer3D.region_set_map(region_rid, get_world_3d().get_navigation_map())
  470. # Add vertices for a convex polygon.
  471. navigation_mesh.vertices = PackedVector3Array([
  472. Vector3(-1.0, 0.0, 1.0),
  473. Vector3(1.0, 0.0, 1.0),
  474. Vector3(1.0, 0.0, -1.0),
  475. Vector3(-1.0, 0.0, -1.0),
  476. ])
  477. # Add indices for the polygon.
  478. navigation_mesh.add_polygon(
  479. PackedInt32Array([0, 1, 2, 3])
  480. )
  481. NavigationServer3D.region_set_navigation_mesh(region_rid, navigation_mesh)
  482. .. code-tab:: csharp 3D C#
  483. using Godot;
  484. public partial class MyNode3D : Node3D
  485. {
  486. private NavigationMesh _navigationMesh;
  487. private Rid _regionRid;
  488. public override void _Ready()
  489. {
  490. _navigationMesh = new NavigationMesh();
  491. _regionRid = NavigationServer3D.RegionCreate();
  492. // Enable the region and set it to the default navigation map.
  493. NavigationServer3D.RegionSetEnabled(_regionRid, true);
  494. NavigationServer3D.RegionSetMap(_regionRid, GetWorld3D().NavigationMap);
  495. // Add vertices for a convex polygon.
  496. _navigationMesh.Vertices = new Vector3[]
  497. {
  498. new Vector3(-1.0f, 0.0f, 1.0f),
  499. new Vector3(1.0f, 0.0f, 1.0f),
  500. new Vector3(1.0f, 0.0f, -1.0f),
  501. new Vector3(-1.0f, 0.0f, -1.0f),
  502. };
  503. // Add indices for the polygon.
  504. _navigationMesh.AddPolygon(new int[] { 0, 1, 2, 3 });
  505. NavigationServer3D.RegionSetNavigationMesh(_regionRid, _navigationMesh);
  506. }
  507. }