概述
Godot4.0改进了2D部分的导航,NavigationRegion2D
基本可以看做是3.X的Navigation2D
的进化版本。
它的基本用法就是先绘制navigation_polygon
,也就是导航网格,或者直白点就是“可通行区域”。然后将带有碰撞形状和NavigationAgent2D
子节点的玩家放置到这个可通行区域,然后在_physics_process
中判断并移动就可以了。
案例
创建地图
从网上随便找一了一张2D游戏的地形素材。(仅做学习使用)
我们创建一个2D场景,将地形素材拖入场景,根节点下自动创建Sprite2D
节点,更名为map,然后继续添加一个NavigationRegion2D
节点。
选中NavigationRegion2D
节点,为我们导入的地形素材手工绘制可通行区域的多边形。
:::danger
注意
- 多个闭合多边形虽然可以被画出来,但即便有重合区域,却不被认为是可互相通行的;
因此,最好是一气呵成的绘制。
:::
创建玩家
用CharacterBody2D
类型创建玩家场景,用工程自带的icon.svg
作为玩家样貌(可以适当缩放),添加圆形碰撞形状。
除此之外,添加一个NavigationAgent2D
。
为玩家创建如下代码:
# player.gd
extends CharacterBody2D
var move_speed = 200.0
var target_pos:Vector2:
set(val):
target_pos = val
nav.target_position = val
@onready var nav = $NavigationAgent2D
func _physics_process(delta):
if nav.is_navigation_finished():
return
if nav.is_target_reachable():
var next_pos = nav.get_next_path_position()
velocity = global_position.direction_to(next_pos) * move_speed
move_and_slide()
其中:
- 第6行:定义
target_pos
变量,并通过Setter函数,传递给NavigationAgent2D
的target_position
属性。 - 在
_physics_process
中我们通过NavigationAgent2D
的get_next_path_position()
方法获取下一个可以到达的位置,并通过获取当前位置(也就是玩家的global_position)到下一位置的方向乘以移动速度来获取玩家的速度向量,然后执行move_and_slide()进行移动。 - 当玩家到达指定位置后,
NavigationAgent2D
的is_navigation_finished()
就会变为true,直接return就可以了。 - 通过
is_target_reachable()
可以判断,多指定的点是否可以到达。但是设置后,玩家不会尽量像目标位置移动,而是直接不走了。
为world2场景添加Palyer场景实例,并将玩家放置在可通行区域内。
为world2场景根节点添加如下代码:
# world2.gd
extends Node2D
@onready var player = $Player
func _input(event):
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed():
player.target_pos = get_global_mouse_position()
其核心是通过鼠标左键点击,将鼠标的全局位置传递给player的target_pos
属性,也就是间接的传递给Player
下NavigationAgent2D
的target_position
属性。
运行效果
运行后的效果如下:
## 总结
可以看到,这种导航形式非常简单,通过在地图上绘制可通行区域,在角色身上添加导航代理,然后将想要到达的位置传递给导航代理,再在物理帧处理函数中不断地获取下一个位置,并动态计算速度向量,然后move_and_slide()
的就可以了。
参考
- 【Godot 4】2D寻路教程-2D Pathfinding Tutorial_哔哩哔哩_bilibili