2D 导航概述

Godot 提供了多种对象、类和服务器,可帮助 2D 和 3D 游戏实现基于栅格(Grid)或网格(Mesh)的导航和寻路。下文将对 Godot 中与 2D 场景导航相关的对象及其主要用途进行概述。

Godot 为 2D 导航提供了如下对象和类:

  • Astar2D

    Astar2D 对象能够在由具有权重的构成的图中查找最短路径。

    The AStar2D class is best suited for cell-based 2D gameplay that does not require actors to reach any possible position within an area but only predefined, distinct positions.

  • NavigationServer2D

    NavigationServer2D 提供了强大的服务器 API,能够在区域中查找两个位置之间的最短路径,区域由导航网格定义。

    The NavigationServer is best suited for 2D realtime gameplay that does require actors to reach any possible position within a navigation mesh defined area. Mesh-based navigation scales well with large game worlds as a large area can often be defined with a single polygon when it would require many, many grid cells.

    The NavigationServer holds different navigation maps that each consist of regions that hold navigation mesh data. Agents can be placed on a map for avoidance calculation. RIDs are used to reference internal maps, regions, and agents when communicating with the server.

    • NavigationServer 中可用的 RID 类型如下。

      • 导航地图 RID

        Reference to a specific navigation map that holds regions and agents. The map will attempt to join the navigation meshes of the regions by proximity. The map will synchronize regions and agents each physics frame.

      • 导航区块 RID

        Reference to a specific navigation region that can hold navigation mesh data. The region can be enabled / disabled or the use restricted with a navigation layer bitmask.

      • 导航链接 RID

        引用指定的导航链接,能够将两个导航网格上的位置进行连接,无视距离。

      • 导航代理 RID

        Reference to a specific avoidance agent. The avoidance is specified by a radius value.

      • 导航障碍物 RID

        Reference to a specific avoidance obstacle used to affect and constrain the avoidance velocity of agents.

The following scene tree nodes are available as helpers to work with the NavigationServer2D API.

  • NavigationRegion2D 节点

    存放 NavigationPolygon 资源的节点,该资源定义的是 NavigationServer2D 中的导航网格。

    • 区块可以启用/禁用。

    • 通过 navigation_layers 掩码,可以对其在寻路中的使用做进一步的限制。

    • The NavigationServer2D will join the navigation meshes of regions by proximity for a combined navigation mesh.

  • NavigationLink2D 节点

    A Node that connects two positions on navigation meshes over arbitrary distances for pathfinding.

    • 链接可以启用/禁用。

    • 链接可以设为单向或双向。

    • 通过 navigation_layers 掩码,可以对其在寻路中的使用做进一步的限制。

    链接会告诉寻路存在这样的连接、相关的消耗如何。实际的代理处理以及移动需要在自定义脚本中实现。

  • NavigationAgent2D 节点

    A helper Node used to facilitate common NavigationServer2D API calls for pathfinding and avoidance. Use this Node with a Node2D inheriting parent Node.

  • NavigationObstacle2D 节点

    A Node that can be used to affect and constrain the avoidance velocity of avoidance enabled agents. This Node does NOT affect the pathfinding of agents. You need to change the navigation meshes for that instead.

2D 导航网格由以下资源定义:

  • NavigationPolygon 资源

    A resource that holds 2D navigation mesh data. It provides polygon drawing tools to allow defining navigation areas inside the Editor as well as at runtime.

    • NavigationRegion2D 节点使用该资源定义其导航区域。

    • NavigationServer2D 使用该资源更新各个区块的导航网格。

    • TileSet 编辑器会定义图块的导航区域时在内部创建并使用该资源。

参见

可以使用 2D 导航演示项目使用 AStarGrid2D 进行基于栅格的导航 演示项目了解 2D 导航如何运作。

2D 场景的设置

The following steps show the basic setup for minimal viable navigation in 2D. It uses the NavigationServer2D and a NavigationAgent2D for path movement.

  1. 在场景中添加一个 NavigationRegion2D 节点。

  2. 单击该区块节点,向该节点添加一个新的 NavigationPolygon 资源。

    ../../_images/nav_2d_min_setup_step1.png

  3. 使用 NavigationPolygon 绘制工具定义可移动导航区域。

    ../../_images/nav_2d_min_setup_step2.png

    备注

    The navigation mesh defines the area where an actor can stand and move with its center. Leave enough margin between the navigation polygon edges and collision objects to not get path following actors repeatedly stuck on collision.

  4. 在场景中添加一个 CharacterBody2D 节点,设置基础的碰撞形状,添加一个精灵或网格方便观察。

  5. 在该角色节点下添加一个 NavigationAgent2D 节点。

    ../../_images/nav_2d_min_setup_step3.webp

  6. 为 CharacterBody3D 节点添加下面的脚本。场景完全加载后,我们确保设置移动目标,NavigationServer 有时间进行同步。

GDScriptC#

  1. extends CharacterBody2D
  2. var movement_speed: float = 200.0
  3. var movement_target_position: Vector2 = Vector2(60.0,180.0)
  4. @onready var navigation_agent: NavigationAgent2D = $NavigationAgent2D
  5. func _ready():
  6. # These values need to be adjusted for the actor's speed
  7. # and the navigation layout.
  8. navigation_agent.path_desired_distance = 4.0
  9. navigation_agent.target_desired_distance = 4.0
  10. # Make sure to not await during _ready.
  11. call_deferred("actor_setup")
  12. func actor_setup():
  13. # Wait for the first physics frame so the NavigationServer can sync.
  14. await get_tree().physics_frame
  15. # Now that the navigation map is no longer empty, set the movement target.
  16. set_movement_target(movement_target_position)
  17. func set_movement_target(movement_target: Vector2):
  18. navigation_agent.target_position = movement_target
  19. func _physics_process(delta):
  20. if navigation_agent.is_navigation_finished():
  21. return
  22. var current_agent_position: Vector2 = global_position
  23. var next_path_position: Vector2 = navigation_agent.get_next_path_position()
  24. velocity = current_agent_position.direction_to(next_path_position) * movement_speed
  25. move_and_slide()
  1. using Godot;
  2. public partial class MyCharacterBody2D : CharacterBody2D
  3. {
  4. private NavigationAgent2D _navigationAgent;
  5. private float _movementSpeed = 200.0f;
  6. private Vector2 _movementTargetPosition = new Vector2(70.0f, 226.0f);
  7. public Vector2 MovementTarget
  8. {
  9. get { return _navigationAgent.TargetPosition; }
  10. set { _navigationAgent.TargetPosition = value; }
  11. }
  12. public override void _Ready()
  13. {
  14. base._Ready();
  15. _navigationAgent = GetNode<NavigationAgent2D>("NavigationAgent2D");
  16. // These values need to be adjusted for the actor's speed
  17. // and the navigation layout.
  18. _navigationAgent.PathDesiredDistance = 4.0f;
  19. _navigationAgent.TargetDesiredDistance = 4.0f;
  20. // Make sure to not await during _Ready.
  21. Callable.From(ActorSetup).CallDeferred();
  22. }
  23. public override void _PhysicsProcess(double delta)
  24. {
  25. base._PhysicsProcess(delta);
  26. if (_navigationAgent.IsNavigationFinished())
  27. {
  28. return;
  29. }
  30. Vector2 currentAgentPosition = GlobalTransform.Origin;
  31. Vector2 nextPathPosition = _navigationAgent.GetNextPathPosition();
  32. Velocity = currentAgentPosition.DirectionTo(nextPathPosition) * _movementSpeed;
  33. MoveAndSlide();
  34. }
  35. private async void ActorSetup()
  36. {
  37. // Wait for the first physics frame so the NavigationServer can sync.
  38. await ToSignal(GetTree(), SceneTree.SignalName.PhysicsFrame);
  39. // Now that the navigation map is no longer empty, set the movement target.
  40. MovementTarget = _movementTargetPosition;
  41. }
  42. }

备注

On the first frame the NavigationServer map has not synchronized region data and any path query will return empty. Wait for the NavigationServer synchronization by awaiting one frame in the script.

Previous Next


© 版权所有 2014-present Juan Linietsky, Ariel Manzur and the Godot community (CC BY 3.0). Revision b1c660f7.

Built with Sphinx using a theme provided by Read the Docs.