obsidian/笔记文件/2.笔记/多边形地图漏斗寻路算法_第三章.md
2025-03-26 00:02:56 +08:00

4.5 KiB
Raw Blame History

通过A星算法计算开始和结束节点经过NavArea寻路区域的CalcAStarPolyPath接口先清空各个数据容器然后把开始区域先塞进检测队列m_detectQue

!Pasted image 20240408171718.png

继续使用while循环如果m_detectQue检测队列包含目标结束节点end就说明检测完毕了通过之前解析的GetPathNavAreas函数从结束节点end倒着依次拿到前面检测的区域作为最终经过的m_pathLst数据容器 然后Invoke触发ShowPathAreaView绘制逻辑break跳出while循环即可 还没检测到end结束节点的时候就是从m_detectQue出队通过共享边界的areaID1和areaID2拿到邻近的区域然后调用之前解析的DetectNeighborArea接口使用A星算法相关逻辑完成寻路检测和优先级设置

!Pasted image 20240408171853.png

对应的是,之前解析过的,绘制黄线逻辑

!Pasted image 20240408172520.png

运行游戏,表现正常

!Pasted image 20240408172624.png

重置A星算法相关数据逻辑ResetAStarData就是调用NavArea的Reset函数即可之前解析过复习

!Pasted image 20240408173255.png

!Pasted image 20240408173342.png

而漏斗算法是基于A星算法寻路逻辑得到的有效区域内进行寻路逻辑处理 其中的FunnelShirkEnum枚举就是用来判断寻路的方向逻辑例如左边向→左边、左边→右边、右边→左边、右边→右边、左边→中心 等; funnelPos就是寻路过程中用来计算的漏斗坐标节点 还有队列容器、方向、索引,都是左右相关;

!Pasted image 20240408173436.png

这是漏斗寻路算法的逻辑入口,先把位置队列容器,实例化出来,其中只包含一个开始节点; 最开始的时候漏斗坐标funnelPos也是设定为start开始节点 然后,清空左右寻路相关,队列容器;

!Pasted image 20240409112636.png

漏斗寻路算法是基于A星寻路算法得到的NavArea队列进行逻辑运算 IsFunnelInitArea接口传参的area是NavArea队列中的其中一个元素拿到区域area的两个边界索引和funnelPos当前是start开始节点进行换算 通过向量Dot点乘与Cross叉乘的概念及几何意义的正负,拿到当前寻路的左右索引和方向;

!Pasted image 20240409113551.png

如果正负都没返回false就好

!Pasted image 20240409114308.png

这是计算拿到对应area区域ID的接口就是调用了上述接口拿到区域ID

!Pasted image 20240409114424.png

拿到区域ID的调用也是确定当前寻路所在的area区域如果为-1说明end结束节点和start开始节点在同一个区域

!Pasted image 20240409114552.png

完成开始节点的初始化后,开始基于区域,拿到边界索引,计算偏移

!Pasted image 20240409114919.png

当前索引curIndex和边界的checkIndex索引比较得到最新的左右索引和方向进而可以下一步检测

!Pasted image 20240409115116.png

根据 左边边界方向,和左边检测方向, 通过叉乘,还是得到方向,进而设定寻路逻辑枚举,是左边 → 左边; 还是 右边边界方向,和左边检测方向,通过叉乘,设定寻路逻辑枚举,是左边 → 中心,或左边 → 右边;

!Pasted image 20240409115403.png

右边检测方向,相关计算,也是同理

!Pasted image 20240409115727.png

如果已经找到end节点就会开始调用CalcEndConner函数接口开始计算end所在的区域内寻路的方向和逻辑

!Pasted image 20240409115948.png

继续通过NormalXZ拿到单位向量通过AngleXZ里面的Mathf.Acos反余弦函数,得到弧度的Mathf.Abs绝对值,进而得到,对应的位置索引

!Pasted image 20240409120109.png

打断点可知数据容器只有一个end节点数据也就是目前只拿到最终节点end作为funnelPos加到路径队列容器PosLst完成最后一部分的换算即可

!Pasted image 20240409121137.png

回到漏斗寻路算法的函数入口,在完成之前的初始化后,如果已经遍历到,最终区域了; 就通过叉乘换算得到end节点在当前节点的左右方向进而判断传递左/右队列容器进行上述解析的CalcEndConner函数得到end节点的最后路径索引寻路计算

!Pasted image 20240409121351.png