Ver Fonte

Add doc for navigation maps, different actor types, and actor locomotion

Adds documentation for navigation maps and how to support actors of different types (e.g. size) and with different locomotion states (e.g. crawling).
smix8 há 3 anos atrás
pai
commit
0babdc92d1

BIN
tutorials/navigation/img/nav_actor_locomotion.png


BIN
tutorials/navigation/img/nav_actor_sizes.png


BIN
tutorials/navigation/img/nav_maps.png


+ 3 - 0
tutorials/navigation/index.rst

@@ -7,3 +7,6 @@ Navigation
 
    navigation_introduction_2d.rst
    navigation_introduction_3d.rst
+   navigation_using_navigationmaps
+   navigation_different_actor_types
+   navigation_different_actor_locomotion

+ 43 - 0
tutorials/navigation/navigation_different_actor_locomotion.rst

@@ -0,0 +1,43 @@
+.. _doc_navigation_different_actor_locomotion:
+
+Support different actor locomotion
+==================================
+
+.. image:: img/nav_actor_locomotion.png
+
+To support different actor locomotion like crouching and crawling, a similar 
+map setup as supporting :ref:`doc_navigation_different_actor_types` is required.
+
+Bake different navigation meshes with an appropriate height for crouched 
+or crawling actors so they can find paths through those narrow sections in your game world.
+
+When an actor changes locomotion state, e.g. stands up, starts 
+crouching or crawling, query the appropriate map for a path.
+
+If the avoidance behavior should also change with the locomotion e.g. only avoid while standing or only avoid 
+other agents in the same locomotion state, switch the actors's avoidance agent to another avoidance map with each locomotion change.
+
+.. tabs::
+ .. code-tab:: gdscript GDScript
+    
+    func update_path():
+        
+        if actor_standing:
+            path = NavigationServer3D.map_get_path(standing_navigation_map_rid, start_position, target_position, true)
+        elif actor_crouching:
+            path = NavigationServer3D.map_get_path(crouched_navigation_map_rid, start_position, target_position, true)
+        elif actor_crawling:
+            path = NavigationServer3D.map_get_path(crawling_navigation_map_rid, start_position, target_position, true)
+    
+    func change_agent_avoidance_state():
+        
+        if actor_standing:
+            NavigationServer3D.agent_set_map(avoidance_agent_rid, standing_navigation_map_rid)
+        elif actor_crouching:
+            NavigationServer3D.agent_set_map(avoidance_agent_rid, crouched_navigation_map_rid)
+        elif actor_crawling:
+            NavigationServer3D.agent_set_map(avoidance_agent_rid, crawling_navigation_map_rid)
+
+.. note::
+
+    While a path query can be execute immediately for multiple maps, the avoidance agent map switch will only take effect after the next server synchronization.

+ 66 - 0
tutorials/navigation/navigation_different_actor_types.rst

@@ -0,0 +1,66 @@
+.. _doc_navigation_different_actor_types:
+
+Support different actor types
+=============================
+
+.. image:: img/nav_actor_sizes.png
+
+To support different actor types due to e.g. their sizes each type requires its own 
+navigation map and navigation mesh baked with an appropriated agent radius and height.
+The same approach can be used to distinguish between e.g. landwalking, swimming or flying agents.
+
+.. note::
+
+   Agents are exclusively defined by a radius and height value for baking navmeshes, pathfinding and avoidance. More complex shapes are not supported.
+
+.. tabs::
+ .. code-tab:: gdscript GDScript
+
+    # create navigationmesh resources for each actor size
+    var navmesh_standard_size : NavigationMesh = NavigationMesh.new()
+    var navmesh_small_size : NavigationMesh = NavigationMesh.new()
+    var navmesh_huge_size : NavigationMesh = NavigationMesh.new()
+    
+    # set appropriated agent parameters
+    navmesh_standard_size.agent_radius = 0.5
+    navmesh_standard_size.agent_height = 1.8
+    navmesh_small_size.agent_radius = 0.25
+    navmesh_small_size.agent_height = 0.7
+    navmesh_huge_size.agent_radius = 1.5
+    navmesh_huge_size.agent_height = 2.5
+    
+    # get the root node for the baking to parse geometry
+    var root_node : Node3D = get_node("NavmeshRootNode")
+    
+    # bake the navigation geometry for each agent size
+    NavigationMeshGenerator.bake(navmesh_standard_size, root_node)
+    NavigationMeshGenerator.bake(navmesh_small_size, root_node)
+    NavigationMeshGenerator.bake(navmesh_huge_size, root_node)
+    
+    # create different navigation maps on the NavigationServer
+    var nav_map_standard : RID = NavigationServer3D.map_create()
+    var nav_map_small : RID = NavigationServer3D.map_create()
+    var nav_map_huge : RID = NavigationServer3D.map_create()
+    
+    # create a region for each map
+    var nav_map_standard_region : RID = NavigationServer3D.region_create()
+    var nav_map_small_region : RID = NavigationServer3D.region_create()
+    var nav_map_huge_region : RID = NavigationServer3D.region_create()
+    
+    # set navigationmesh for each region
+    NavigationServer3D.region_set_navmesh(nav_map_standard_region, navmesh_standard_size)
+    NavigationServer3D.region_set_navmesh(nav_map_small_region, navmesh_small_size)
+    NavigationServer3D.region_set_navmesh(nav_map_huge_region, navmesh_huge_size)
+    
+    # add regions to maps
+    nav_map_standard_region.region_set_map(nav_map_standard_region, nav_map_standard)
+    nav_map_small_region.region_set_map(nav_map_small_region, nav_map_small)
+    nav_map_huge_region.region_set_map(nav_map_huge_region, nav_map_huge)
+    
+    # wait a physics frame for sync
+    await get_tree().physics_frame
+    
+    # query paths for each size
+    var path_standard_agent = NavigationServer3D.map_get_path(nav_map_standard, start_pos, end_pos, true)
+    var path_small_agent = NavigationServer3D.map_get_path(navmesh_small_size, start_pos, end_pos, true)
+    var path_huge_agent = NavigationServer3D.map_get_path(nav_map_huge, start_pos, end_pos, true)

+ 77 - 0
tutorials/navigation/navigation_using_navigationmaps.rst

@@ -0,0 +1,77 @@
+.. _doc_navigation_using_navigationmaps:
+
+Using NavigationMaps
+====================
+
+.. image:: img/nav_maps.png
+
+A NavigationMap is an abstract navigation world on the NavigationServer identified by a NavigationServer :ref:`RID<class_RID>`.
+
+A map can hold and connect a near infinite number of navigation regions with navigation meshes to build the traversable areas of a game world for pathfinding.
+
+A map can be joined by avoidance agents to process collision avoidance between the avoidance agents.
+
+.. note::
+
+    Different NavigationMaps are completely isolated from each other but navigation regions 
+    and avoidance agents can switch between different maps once every server synchronization.
+
+Default navigation maps
+~~~~~~~~~~~~~~~~~~~~~~~
+
+By default Godot creates a navigation map RID for each :ref:`World2D<class_World2D>` and :ref:`World3D<class_World3D>` of the root viewport.
+
+The 2D default navigation ``map`` can be obtained with ``get_world_2d().get_navigation_map()`` from any :ref:`Node2D<class_Node2D>` inheriting Node.
+
+The 3D default navigation ``map`` can be obtained with ``get_world_3d().get_navigation_map()`` from any :ref:`Node3D<class_Node3D>` inheriting Node.
+
+.. tabs::
+ .. code-tab:: gdscript GDScript
+
+    extends Node2D
+    
+    var default_2d_navigation_map_rid : RID = get_world_2d().get_navigation_map()
+
+.. tabs::
+ .. code-tab:: gdscript GDScript
+
+    extends Node3D
+    
+    var default_3d_navigation_map_rid : RID = get_world_3d().get_navigation_map()
+
+Creating new navigation maps
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The NavigationServer can create and support as many navigation maps as are required for specific gameplay.
+Additional navigation maps are created and maintained by using the NavigationServer API 
+directly e.g. to support different avoidance agent or actor locomotion types.
+
+For example uses of different navigation maps see :ref:`doc_navigation_different_actor_types` and :ref:`doc_navigation_different_actor_locomotion`.
+
+Each navigation map synchronizes queued changes to its navigation regions and avoidance agents individually. 
+A navigation map that has not received changes will consume little to no processing time. 
+Navigation regions and avoidance agents can only be part of a single navigations map but they can switch maps at any time.
+
+.. note::
+
+    A navigation map switch will take effect only after the next NavigationServer synchronization.
+
+.. tabs::
+ .. code-tab:: gdscript GDScript
+
+    extends Node2D
+    
+    var new_navigation_map : RID = NavigationServer2D.map_create()
+    NavigationServer2D.map_set_active(true)
+
+.. tabs::
+ .. code-tab:: gdscript GDScript
+
+    extends Node3D
+    
+    var new_navigation_map : RID = NavigationServer3D.map_create()
+    NavigationServer3D.map_set_active(true)
+
+.. note::
+
+    There is no difference between navigation maps created with the NavigationServer2D API or the NavigationServer3D API.