mirror of
https://github.com/godotengine/godot-docs.git
synced 2026-01-03 05:48:42 +03:00
Add doc for 2D & 3D navigationmesh generation
Adds documentation how to create navigationmesh / navpolygons for 2D and 3D both with editor tools as well with scripts + some technical background stuff.
This commit is contained in:
BIN
tutorials/navigation/img/nav_polydrawtool.png
Normal file
BIN
tutorials/navigation/img/nav_polydrawtool.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
tutorials/navigation/img/nav_polymatroschka.png
Normal file
BIN
tutorials/navigation/img/nav_polymatroschka.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
BIN
tutorials/navigation/img/nav_polyoutlinefail.png
Normal file
BIN
tutorials/navigation/img/nav_polyoutlinefail.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.9 KiB |
@@ -11,3 +11,4 @@ Navigation
|
||||
navigation_different_actor_types
|
||||
navigation_different_actor_locomotion
|
||||
navigation_using_navigationobstacles
|
||||
navigation_using_navigationmeshes
|
||||
|
||||
246
tutorials/navigation/navigation_using_navigationmeshes.rst
Normal file
246
tutorials/navigation/navigation_using_navigationmeshes.rst
Normal file
@@ -0,0 +1,246 @@
|
||||
.. _doc_navigation_using_navigationmeshes:
|
||||
|
||||
Using NavigationMeshes
|
||||
======================
|
||||
|
||||
2D and 3D version of the navigation mesh are available as
|
||||
:ref:`NavigationPolygon<class_NavigationPolygon>` and
|
||||
:ref:`NavigationMesh<class_NavigationMesh>` respectively.
|
||||
|
||||
.. _doc_navigation_navmesh_baking:
|
||||
|
||||
Creating 2D NavigationMeshes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Navigation meshes in the 2D editor are created with the help of the NavigationPolygon draw tools
|
||||
that appear in the top bar of the editor when a NavigationRegion2D is selected.
|
||||
|
||||
.. image:: img/nav_polydrawtool.png
|
||||
|
||||
The NavigationPolygon draw tools can be used to create and edit navigation meshes by defining ``outline`` polygons.
|
||||
The outline polygons are later converted to real NavigationMesh resources for the NavigationServer regions.
|
||||
|
||||
.. image:: img/nav_polymatroschka.png
|
||||
|
||||
Multiple outlines can be added to the same NavPolygon resource as long as they **do not intersect or overlap**.
|
||||
Each additional outline will cut a hole in the polygon created by the larger outline.
|
||||
If the larger polygon is already a hole it will create a new navigation mesh polygon inside.
|
||||
|
||||
Outlines are not a replacement if the intention is to merge aligned polygons e.g. from grid cells.
|
||||
Outlines, as the name would suggest, cannot intersect each other or have any overlapping vertex positions.
|
||||
|
||||
.. image:: img/nav_polyoutlinefail.png
|
||||
|
||||
Outline layouts like seen in this picture will fail the convex partitioning required by the navigation mesh generation.
|
||||
In this layout cases the outline tool cannot be used. Use the :ref:`Geometry2D<class_Geometry2D>` class for
|
||||
polygon merge or intersect operations to create a valid merged mesh for navigation.
|
||||
|
||||
.. note::
|
||||
|
||||
The NavigationServer does not connect navigation mesh islands from the same NavigationMesh resource.
|
||||
Do not create multiple disconnected islands in the same NavigationRegion2D and NavPoly resource if they should be later connected.
|
||||
|
||||
For 2D no similar navigation mesh baking with geometry parsing exists like in 3D.
|
||||
The Geometry2D class functions for offset, merge, intersect and clip can be used
|
||||
to shrink or enlarge existing NavigationPolygons to different actor sizes.
|
||||
|
||||
Creating 3D NavigationMeshes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. image:: img/baked_navmesh.png
|
||||
|
||||
Navigation meshes in the 3D editor are created with the help of the
|
||||
:ref:`NavigationMeshGenerator<class_NavigationMeshGenerator>` singleton
|
||||
and the NavigationMesh bake settings that appear in the editor inspector.
|
||||
|
||||
NavigationMesh baking is the process of creating a simplified mesh used for pathfinding out of (complex) 3D level geometry.
|
||||
For this process Godot parses scene geometry and hands the raw mesh or collision data to the
|
||||
third-party ReCast library for processing and creation of the final navigationmesh.
|
||||
|
||||
The resulting NavigationMesh is an approximation of the source geometry surfaces
|
||||
for both performance and technical reasons. Do not expect the NavigationMesh
|
||||
to perfectly follow the original surfaces. Especially navigation polygons placed
|
||||
over ramps will not keep an equal distance to the ground surface. To align an
|
||||
actor perfectly with the ground use other means like physics.
|
||||
|
||||
.. warning::
|
||||
|
||||
Meshes need to be triangulated to work as navigation meshes. Other mesh face formats like quad or ngon are not supported.
|
||||
|
||||
NavigationMesh rebaking at runtime
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To rebake a ``NavigationMesh`` at runtime, use the NavigationRegion3D.bake_navigation_mesh() function.
|
||||
Another option is to use the NavigationMeshGenerator.bake() Singleton function with the NavigationMesh resource directly.
|
||||
If the navmesh resource is already prepared, the region can be updated with the NavigationServer3D API directly as well.
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
extends NavigationRegion3D
|
||||
|
||||
func update_navmesh():
|
||||
|
||||
# use bake and update function of region
|
||||
var on_thread : bool = true
|
||||
bake_navigation_mesh(on_thread)
|
||||
|
||||
# or use the NavigationMeshGenerator Singleton
|
||||
var navigationmesh : NavigationMesh = navmesh
|
||||
NavigationMeshGenerator.bake(navigationmesh, self)
|
||||
# remove old resource first to trigger a full update
|
||||
navmesh = null
|
||||
navmesh = navigationmesh
|
||||
|
||||
# or use NavigationServer API to update region with prepared navmesh
|
||||
var region_rid : RID = get_region_rid()
|
||||
NavigationServer3D.region_set_navmesh(region_rid, navmesh)
|
||||
|
||||
.. note::
|
||||
|
||||
Baking a NavigationMesh at runtime is a costly operation.
|
||||
Complex navmesh take some time to bake and if done on the main thread can freeze a game.
|
||||
(Re)baking a large navmesh is preferably done in a separate thread.
|
||||
|
||||
.. warning::
|
||||
|
||||
Property values on a NavigationMesh resource like ``cell_size`` need
|
||||
to match the actual mesh data stored inside in order to merge
|
||||
different navigation meshes without issues.
|
||||
|
||||
NavigationRegion2D and Navigation3D both use meshes to mark traversable areas, only the tools to create them are different.
|
||||
|
||||
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.
|
||||
|
||||
For 3D NavigationMesh resources are used. Instead of providing draw tools the 3D variant
|
||||
provides an extensive amount of parameters to bake a navigation mesh directly from 3D source geometry.
|
||||
|
||||
.. note::
|
||||
|
||||
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.
|
||||
|
||||
2D Navmesh from CollisionPolygons
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following script parses all child nodes of a NavigationRegion2D for CollisionPolygons
|
||||
and bakes their shape into the NavigationPolygon. As the NavigationPolygon creates the
|
||||
navigationmesh from outline data the shapes cannot overlap.
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
extends NavigationRegion2D
|
||||
|
||||
var navigationpolygon : NavigationPolygon = get_navigation_polygon()
|
||||
|
||||
func _ready():
|
||||
|
||||
parse_2d_collisionshapes(self)
|
||||
|
||||
navigationpolygon.make_polygons_from_outlines()
|
||||
set_navigation_polygon(navigationpolygon)
|
||||
|
||||
func parse_2d_collisionshapes(root_node : Node2D):
|
||||
|
||||
for node in root_node.get_children():
|
||||
|
||||
if node.get_child_count() > 0:
|
||||
parse_2d_collisionshapes(node)
|
||||
|
||||
if node is CollisionPolygon2D:
|
||||
|
||||
var new_collision_outline : PackedVector2Array = PackedVector2Array()
|
||||
var collisionpolygon_transform : Transform2D = node.get_global_transform()
|
||||
var collisionpolygon : CollisionPolygon2D = node.get_polygon()
|
||||
|
||||
for vertex in collisionpolygon:
|
||||
new_collision_outline.append(collisionpolygon_transform.xform(vertex))
|
||||
|
||||
navigationpolygon.add_outline(new_collision_outline)
|
||||
|
||||
Procedual 2D Navmesh
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following script creates a new 2D navigation region and fills it with procedual generated navmesh data from a NavigationPolygon resource.
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
extends Node2D
|
||||
|
||||
var new_2d_region_rid : RID = NavigationServer2D.region_create()
|
||||
|
||||
var default_2d_map_rid : RID = get_world_2d().get_navigation_map()
|
||||
NavigationServer2D.region_set_map(new_2d_region_rid, default_2d_map_rid)
|
||||
|
||||
var new_navpoly : NavigationPolygon = NavigationPolygon.new()
|
||||
var new_outline : PackedVector2Array = PackedVector2Array([
|
||||
Vector2(0.0, 0.0),
|
||||
Vector2(50.0, 0.0),
|
||||
Vector2(50.0, 50.0),
|
||||
Vector2(0.0, 50.0),
|
||||
])
|
||||
new_navpoly.add_outline(new_outline)
|
||||
new_navpoly.make_polygons_from_outlines()
|
||||
|
||||
NavigationServer2D.region_set_navpoly(new_2d_region_rid, new_navpoly)
|
||||
|
||||
Procedual 3D Navmesh
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following script creates a new 3D navigation region and fills it with procedual generated navmesh data from a NavigationMesh resource.
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
extends Node3D
|
||||
|
||||
var new_3d_region_rid : RID = NavigationServer3D.region_create()
|
||||
|
||||
var default_3d_map_rid : RID = get_world_3d().get_navigation_map()
|
||||
NavigationServer3D.region_set_map(new_3d_region_rid, default_3d_map_rid)
|
||||
|
||||
var new_navmesh : NavigationMesh = NavigationMesh.new()
|
||||
var new_plane_mesh : PlaneMesh = PlaneMesh.new()
|
||||
new_plane_mesh.size = Vector2(10.0, 10.0)
|
||||
new_navmesh.create_from_mesh(new_plane_mesh)
|
||||
|
||||
NavigationServer3D.region_set_navmesh(new_3d_region_rid, new_navmesh)
|
||||
|
||||
Navmesh for 3D GridMaps
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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.
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
extends GridMap
|
||||
|
||||
# enable navmesh for grid items
|
||||
set_bake_navigation(true)
|
||||
|
||||
# get mesh from grid item, bake and set a new navmesh for the library
|
||||
var gridmap_item_list : PackedInt32Array = mesh_library.get_item_list()
|
||||
for item in gridmap_item_list:
|
||||
var item_mesh : Mesh = mesh_library.get_item_mesh(item)
|
||||
var navmesh : NavigationMesh = NavigationMesh.new()
|
||||
navmesh.create_from_mesh(item_mesh)
|
||||
mesh_library.set_item_navmesh(item, item_mesh)
|
||||
mesh_library.set_item_navmesh_transform(item, Transform3D())
|
||||
|
||||
# clear the cells
|
||||
clear()
|
||||
|
||||
# add procedual cells using the first item
|
||||
var _position : Vector3i = Vector3i(global_transform.origin)
|
||||
var _item : int = 0
|
||||
var _orientation : int = 0
|
||||
for i in range(0,10):
|
||||
for j in range(0,10):
|
||||
_position.x = i
|
||||
_position.z = j
|
||||
gridmap.set_cell_item(_position, _item, _orientation)
|
||||
_position.x = -i
|
||||
_position.z = -j
|
||||
gridmap.set_cell_item(_position, _item, _orientation)
|
||||
Reference in New Issue
Block a user