近日在做navigation2d加navigationPolygonInstance做寻路的时候遇到了一些坑,先记录下来。
使用的示例是官方自带的navigation2d示例,脚本没有进行修改,只改了相关的navigationPolygonInstance
1.如果在navigation2d的子孙节点里有多个NavigationPolygonInstance,且这些NavigationPolygonInstance不粘连,而当get_simple_path( Vector2 start, Vector2 end, bool optimize=true )传入的start和end跨越两个不粘连的NavigationPolygonInstance时,该函数不起作用,不过有时候也能以小概率在NavigationPolygonInstance的边缘卡进另外一个NavigationPolygonInstance。
如图:在navpoly和navpoly2不粘连的时候,即使是重叠,也不能使agent跑到navpoly2的区域上去
2.即使多个NavigationPolygonInstance紧贴在一起,如果紧贴的地方没有重合的顶点,则get_simple_path()函数返回绕过没重合顶点的路径数组,假如两个NavigationPolygonInstance完全没有重合顶点,则造成了问题一
下图为2个navpoly的形状,可以看到只有一对重合顶点。
最终运动效果:
结论:
1.要想navigation2d对所有子节点的navigationPolygonInstance起作用,就要让它们有重合的点。
2.最好用“依附”功能来做重合,因为navigationPolygonInstance里的每个顶点都是一个vector2,向量你懂的,xy都可以是小数,不知道算重合的精度是多少。
.............................
另外一个坑其实算小进阶,就是在已有的navigationPolygonInstance里挖个不能走的坑,比如你要在地图上放一个花盆,AI要绕过去,又不想手动改navigationPolygonInstance,就代码改改。
这个问题我在下面这个网址上看到的
https://www.reddit.com/r/godot/comments/7k4qos/why_does_this_script_created_hole_in_the/
然后试了下里面的代码,其实还有点旧了,可能那时候还没to_local和to_global函数,就还是用transform的逆矩阵乘另一个transform来获取本地transform,但这种方法也有局限性,说起来还挺麻烦,不说了,知道有局限就好(想了解矩阵的相关知识的可以点一下
https://www.bilibili.com/video/av6731067
这个b站的链接)。
再然后根据里面的代码改了下项目唯一的脚本navigation.gd:
1.添加变量Cutout,类型是polygon2d,在场景中添加一个polygon2d节点,弄个形状,使Cutout变量指向这个节点。
2.添加函数:
#调节polygon2d的位置
func adjustPolygonPosition(inTransform, inPolygon):
var outPolygon = PoolVector2Array()
#把顶点转换到本地坐标,要求navpoly和cutout要有相同的父节点,或各自父节点的transform相同
#var finalTransform = $navpoly.transform.inverse() * inTransform
for vertex in inPolygon:
#outPolygon.append(finalTransform.xform(vertex))
#下面这个方法就没有父节点限制
var finalPos = $navpoly.to_local(Cutout.to_global(vertex))
outPolygon.append(finalPos)
return outPolygon
#重新修改节点
func modifyNavPoly():
#其实outline就是顶点数组,输出一下就知道了
$navpoly.navpoly.add_outline(adjustPolygonPosition(Cutout.transform, Cutout.polygon))
$navpoly.navpoly.make_polygons_from_outlines()
#下面这些是必须的,用于更新navpoly
$navpoly.enabled = false
$navpoly.enabled = true
3.在_ready()里添加一行代码:
modifyNavPoly()
就ok了,要注意的是,cutout不能挖到navpoly外面,不然就没效果。
下图是我的节点结构:
把cutout放在Node2D下面是为了测试我自己改了的代码和原本的代码有没有区别,可以移动一下Node2D节点对比下新旧代码效果。
navpoly就是被挖的NavigationPolygonInstance,而navpoly2是我测试看两个粘合的NavigationPolygonInstance能不能一起挖,发现是不能的。
至于再怎么填回去。。。
Emmm
我自己也没做,但可以猜测下。
首先NavigationPolygonInstance的get_outline(0)返回的是本身的顶点数组,然后每调用一次add_outline()就会使outline数加一,也就是这时候用get_outline(1)会获得新加上去的顶点数组,然后你就可以用remove_outline()函数来试试咯。
另外,如果各位小伙伴在测试上面这些内容的时候发现有问题请留言!我看到会马上改的!万分感激!
有时间可以考虑追加一篇介绍navigation2d节点的日志
@Justus:好,有空一定做