用可视化的路径显示,告诉你为何自动寻路能力自带的移动不好用



  • 之所以发这个帖,是因为在群里看到了群友关于自动寻路能力的讨论,其中关于该能力的说法最多的是“这个能力不好用”,但是为什么不好用,似乎众说纷纭,列举的理由也是千奇百怪。
    从结果上有说是莫名其妙就卡住了的,从原因分析上有说是寻路算法不对的。
    前者是比较直观的结果体现,也是多数人的共识,后者则一直没有明确结论,本着“直接上手测试看看最能说明问题”的思路,我想,或许只要把寻路的路径进行可视化,就能最直观的说明这个问题了。
     
    如果对过程不感兴趣,只想知道结论的朋友,这里可以直接先说结论:
    寻路能力分[寻找路径]阶段和[沿路径移动]阶段,跟寻路算法有关的只有[寻找路径]阶段,而[沿路径移动]阶段只是按[寻路阶段]找出的路径节点进行圆滑移动,[沿路径移动]阶段跟寻路算法没有任何关系,其中不好用的是[沿路径移动]阶段。
     
    当然,这个结论只是根据我测试的结果来推断的,具体的原因肯定还是以官方的说明为准。那么如果你想了解这个结论是怎么得出的,就接着往下看吧。
    首先寻路算法没问题这个其实我觉得是很好理解的,因为从开发的角度来说,在已经有了许多成熟的寻路算法的情况下,唤境的研发大佬们不可能去自己重新构思一套寻路算法,肯定是用已有的成熟寻路算法,所以问题多半不可能出现在算法上,那“不好用”的原因就只能落在[沿路径移动]阶段了。
     
    为什么我会认为可以把寻路能力划分成[寻找路径]和[沿路径移动]两个独立部分呢?
    这个一方面是寻路能力自带的条件和动作部分已经做了这样的划分,另一方面是我发现在仅执行了“寻找路径”并成功找到路径后,就已经能通过该能力的一些表达式获取到寻路结果节点的各种信息了(如下图红框中的一些表达式),到目前为止都跟移动没关系,所以我暂时断定[沿路径移动]是该能力另一个独立的阶段。
    undefined
    那既然确认了这是两个独立的阶段,并且认为[寻找路径]阶段是没问题的,那只要比对“寻路算法得出的路径”和“沿路径移动的实际移动路径”,或许就能有进一步的信息发现主要的问题在哪了,也就是说,只要实现生成这两个实时路径,就能直观看到结果是怎样的。
    为了让结果尽量明显,首先需要看看自动寻路能力的一些能力属性,如下图:
    undefined
    【网格大小单位尺】指的就是寻路时要以多大尺寸的格子为一个路径单位,如下图红色椭圆框处,是每个寻路节点的位置,它只会是这个网格的中心处,所以该值越小,寻路就越精细(越能通过障碍物间细小的缝隙,当然,性能消耗也就越高)。
    【网格边界】官方tips说的是“检测障碍的额外尺寸。可以防止路径过于靠近障碍物”,这个说明很简明了。
    【障碍物】测试出的障碍物设定是“只要某个网格有一部分,与指定的障碍物的碰撞区域重叠,那该网格就会被判定成障碍格子”,如下图的红底格子是障碍格子,绿底格子是可通行格子。
    以上3个属性是会直接影响[寻找路径]阶段的,剩下的速度相关属性则是会影响[沿路径移动]阶段,还有一个比较特殊的属性是看起来两个阶段都会影响到的——对角线移动,对[寻找路径]阶段比较明显的影响是下图中右边那个黄色框中的情况,就很直观的会在对角线处生成寻路节点,而不是直角处生成寻路节点。
    undefined
    了解了这些属性的作用后,还要了解一下寻路对象有没有“体积”,这点我在向官方求证以及自己的测试后,发现寻路对象是没有“体积”的,什么意思呢?
    就是说寻路能力的对象,本身的碰撞区域是不会参与到寻路算法中的,如下图的紫框处,寻路对象都已经跟障碍物刚体重叠了,但是依旧能正常通过。
    也就是说,寻路算法只计算对象锚点这一个“点”是否能到达目标位置。
    undefined
    如果你已经理解了上面这部分内容,那你对自动寻路能力的运行应该会有一个大致的理解了,接下来我们来看测试结果吧,测试工程我也会附在最后给大家下载测试。
    测试图像说明如下:
    undefined
    测试结果如下,可以看到,虽然寻路路径和实际移动路径的起点和终点,以及直线移动部分基本是一致的,但只要有拐弯,两者就会出现很大的差异。
    undefined
    以上结果来看,实际移动路径进行拐弯时在移动表现上会很顺滑,似乎看起来没什么问题。是的,如果只是单次寻路,然后寻路对象到达目的地前都不执行其他操作的话,这个效果是很不错的,但是可以注意到,实际移动路径两次拐弯都擦到了障碍格子的区域,这会导致什么问题呢?
    是的,开头提到的“莫名其妙就卡住了”的情况就来源于此。
    因为大多数出现卡住情况的人使用寻路能力的时候,其实都不是只执行单次寻路并乖乖等寻路对象到达目的地的,而是会需要以较短间隔时间反复执行寻路操作,让寻路对象时刻追踪目标物,而只要寻路对象刚好移动到障碍格子并刚好触发新一次的寻路时,就会因为陷在障碍物里找不到出去的路径而导致寻路失败,进而卡住。
    但就算这样,上面这个测试结果来看,应该也还算小概率事件对吗,似乎与大家频繁卡住甚至必现卡住的情况还是有些差距,那可以看看下面这种情况的测试结果:在移动过程中执行一次新的寻路和移动,有可能出现如下情况,可以看到,起始那段拐弯都已经有一部分直接在障碍格子中“遨游”了。
    undefined
    那是否只要转弯转得够快,就能回避这种情况呢?我们把转向速度设得尽可能大,并且把可能影响拐弯的属性都修改如下:
    undefined
    虽然有些情况的表现不错,但还是可能出现以下这种情况。
    undefined
    那么到这里,其实我们基本可以得出结论了,那就是自动寻路能力自带的移动,也就是[沿路径移动]阶段,在应对复杂的寻路要求时,确实是很不好用,而且通过测试对比发现,影响[沿路径移动]阶段最大的属性是“转向速度”。
    以下是转向速度30和转向速度300的移动结果(相近的起点终点)对比图,其中其实还有实例的角度因素在影响实际移动路径,这里是挑了一个比较离谱的结果来展示,可以看到寻路路径是几乎一致的,但实际移动路径却差得很多,这也侧面说明了实际移动路径确实跟寻路算法没什么关系:
    undefined
    那么,总结一下吧:
    1、寻路能力的寻路算法,也即[寻找路径]阶段是没问题的(以上测试结果的蓝色路径都是在可通行格子中的,大家也可以之后下载测试工程来测试,不过需要注意测试工程的通行格子可视化没有考虑寻路能力的网格边界属性的自适应,所以不调整网格边界属性的结果才是准确的)
    2、寻路能力的圆滑移动适用性较低,也即[沿路径移动]阶段不好用。
    3、寻路能力自带的移动跟寻路算法没什么关系,只是根据寻路算法算出的结果节点来进行圆滑运动。

    以上就是测试过程了,希望对读到这里的朋友有所帮助,也希望官方能早日优化出更好的方案吧。

    或许还有朋友会问,那讲了这么多,目前的寻路能力不就是完全没用吗?毕竟移动都可能出现这么离谱的情况了。

    诶~此言差矣,就如上面的结论一样,既然我们可以确认只有寻路能力自带的移动有问题,那移动的部分自己写事件来实现,即可回避以上这些问题了,事实上,官方的塔防训练营教程以及RPG班的群文件都有相应的“纯按寻路路径移动”的事件范例,可以去了解一下,如果还是觉得麻烦,那还是建议等官方优化吧。当然,如果你不需要短时间间隔内反复寻路,而是只需要寻路一次,默认的这个移动也还是不错的,上面写事件自己实现移动的建议,也是针对有需求的朋友来说的。

    测试工程下载:寻路研究与测试.evk






  • @konoDIOda 不愧是dio!懂了


登录后回复