Godot2D角色导航-自动寻路教程(Godot设置导航代理的目标位置)

文章目录

创建导航

首先,创建一个基本的场景,下面的文章讲解了如何创建一个基本的导航场景,点击如下链接前往该文章:
Godot2D角色导航-自动寻路教程

创建场景之后,我们就来讲一讲NavigationAgent2D这个节点。该节点用于2D的导航代理,它将寻路至某个位置,并且在寻路的过程中能够躲避障碍物,这个障碍物包括静态障碍物和动态障碍物。

躲避动态障碍物使用的是 RVO 防撞算法。

我们可以通过如下代码来获取节点,节点的路径要如实填写,也就是GetNode的参数。

csharp 复制代码
private NavigationAgent2D navigationAgent;

navigationAgent = GetNode<NavigationAgent2D>("NavigationAgent2D");

设置目标位置

使用代理,那我们就需要告诉他一个目标位置,然后让它告诉我们移动到那个位置的路径,这个位置我们可以通过设置TargetPosition属性来告诉我们的NavigationAgent2D节点。当TargetPosition属性被设置为一个特定的2D坐标时,导航代理会自动计算并选择路径,以选择尽可能快地路径移动到这个目标位置。

一旦TargetPosition被设置,会向 NavigationServer 请求一条新的从当前代理位置到TargetPosition的导航路径。然后,我们可以通过这个路径,使该节点沿着路径移动,以达到指定的目标位置。

该属性接收一个Vector2类型的值,我们可以为其赋值,代码如下所示:

csharp 复制代码
navigationAgent.TargetPosition=new Vector2(500.0f, 200.0f);

这样或许有些麻烦,因为我们需要打节点名,再打属性名,我们可以使用属性来对其进行一次封装,如下所示:

csharp 复制代码
	public Vector2 MovementTarget
	{
		get { return navigationAgent.TargetPosition; }
		set { navigationAgent.TargetPosition = value; }
	}

需要注意的是,之前我们说过了,TargetPosition被设置后,会向 NavigationServer 请求一条新的从当前代理位置到TargetPosition的导航路径。而只有在第一帧物理模拟,NavigationServer才可以进行同步,而在第一帧物理模拟之前,导航服务器是无法正常同步的。

这意味着,我们如果直接在_Ready()方法中设置,是会导致错误的,因为_Ready方法会在物理模拟之前执行。此时导航服务器尚未初始化。导航服务器需要先完成初始化和同步,才能够有效地进行导航操作。

所以,我们使用异步等待的方法,来等待第一帧物理模拟,以便导航服务器可以同步。

我们通过使用 async 关键字来声明异步方法。异步方法可以在执行耗时操作时,使程序能够在此期间继续执行其他工作,而不会阻塞线程。这表示我们可以在异步方法内部编写一些长时间运行的操作或需要等待的异步操作。比如说,我们一直等待,直到第一帧物理模拟,然后再为TargetPosition赋值。具体代码如下所示:

csharp 复制代码
	private async void ActorSetup()
	{
		// 等待第一帧物理模拟,以便导航服务器可以同步。
		await ToSignal(GetTree(), SceneTree.SignalName.PhysicsFrame);
		// 现在导航网格不再为空,可以设置移动目标。
		MovementTarget = _movementTargetPosition;
	}

在 ActorSetup() 方法中,我们使用了 await 关键字来等待第一帧物理模拟开始的型号。这意味着代码会暂停执行,直到接收到 PhysicsFrame 信号后才会继续执行下面的代码。

ToSignal 方法,该方法用于监听指定节点的信号。它返回一个 SignalAwaiter对象,配置完成时为指定的节点发出了指定的信号。

ToSignal 方法的参数有两个:

  • source:要监听信号的节点对象。
  • signal:要监听的信号的名称。

而GetTree方法,会返回包含此节点的 SceneTree。

然后我们调用该方法,代码如下所示:

csharp 复制代码
Callable.From(ActorSetup).CallDeferred();

首先,通过使用 Callable.From() 方法,将方法 ActorSetup 转换为一个可调用对象。

接下来,使用 CallDeferred 方法对可调用对象进行延迟调用。延迟调用意味着该方法将在空闲帧期间调用,而不会立即执行。延迟调用的作用是将方法推迟到稍后的时间点执行,以便其他任务有机会执行。CallDeferred 方法可以接收参数,这些参数应与方法的参数列表相匹配。在调用时,传递的参数将作为对应方法的实际参数进行使用。

另外,我们设置了目标位置后,还需要做其他的工作,这就与Unity有所不同,Unity设置好目标后,就可以自动的向着目标点移动,而在Godot中,我们需要在代码中,自动编写移动逻辑,设置了目标点后,只是让引擎来帮你计算到目标点的路径而已,并不帮你移动。移动代码,我们要自己做。

其他文章

关于信号的讲解可以查看如下文章:

Godot信号教程(使用C#语言)

相关推荐
串流游戏联盟41 分钟前
steam新品节游戏推荐!手机怎么玩steam游戏!
游戏·远程工作
霜绛1 小时前
Unity:UGUI笔记(一)——三大基础控件、组合控件
笔记·学习·unity·游戏引擎
YuanlongWang2 小时前
c# 泛型的详细介绍
c#
麦麦大数据4 小时前
F029 vue游戏推荐大数据可视化系统vue+flask+mysql|steam游戏平台可视化
vue.js·游戏·信息可视化·flask·推荐算法·游戏推荐
嵌入式学习和实践4 小时前
C# WinForms 多窗口交互通信的示例-主窗口子窗口交互通信
c#·交互·主窗口-子窗口通信
专注VB编程开发20年4 小时前
C#,VB.NET数组去重复,提取键名和重复键和非重复键
c#·.net·linq·取唯一键·去重复·重复数量
YuanlongWang5 小时前
Entity Framework Core和SqlSugar的区别,详细介绍
c#
小趴菜82277 小时前
Android中加载unity aar包实现方案
android·unity·游戏引擎
unicrom_深圳市由你创科技7 小时前
工业上位机,用Python+Qt还是C#+WPF?
python·qt·c#
今夕资源网15 小时前
牛童三国单机游戏Unity源码 免费开源
游戏·unity·单机游戏·游戏源码·unity源码·unity游戏