如何在路径(坐标列表)上行走时使角色变得流畅?


15

我有一个带有坐标的列表-从A *算法输出-我想使我的角色旋转顺畅地遵循此路径。

所以我有一个像A的东西,我想得到C

在此处输入图片说明

我怎样才能做到这一点 ?

编辑

为了使自己更清楚一点:

我对平滑转弯更感兴趣,因为我已经知道如何从一个节点转到另一个节点。

编辑

许多人认为这很有用(我也是如此),所以我发布了Daniel Shiffman的“代码的本质”的链接,他在其中讨论了许多游戏AI(和物理)问题,例如转向行为http://natureofcode.com/book/chapter- 6个自治代理/#chapter06_section8


寻路功能不是Unity内置的吗?
joltmode

@Tom是的,但是无论如何我都实现了我的版本。这个问题的重点是在小径上行走时要获得平稳的转弯(旋转)。
Patryk

3
在这方面,Google的一个很好的称呼是“转向行为” :)
Roy T.

3
@RoyT。当然 !我在这几周前已经读过这篇文章,并且已经忘记了:/这是一篇很棒的文章,后面有很棒的数学和物理解释natureofcode.com
Patryk 2013年

1
我只想感谢@Patryk提供的链接-看起来确实很有帮助,我一直在寻找有关操纵行为的好资源。
基督教徒

Answers:


7

如果要在基于图块的环境中使用平滑的路径,则无法在A *航路点上应用一些平滑的路径。在关于编程游戏AI的书中,马特·巴克兰(Matt Buckland)描述了一种简单且快速的算法来平滑路径(基本上删除所有可以消除的边缘,而不会与障碍物相交)。

一旦去除了像这样不必要的边缘,就解决了第一种情况(A-> B)。可以通过多种方法来平滑图形中的边缘。Hermite样条曲线很有可能会起作用(取决于您的障碍物密度和图块大小)。另一种选择是操纵行为,即您距当前目标只有半格的距离时便开始转向下一个航路点(这实际上取决于您的“特工”移动/转弯的速度)。


9

正如其他人提到的那样,在第二种情况下,您将需要实现某种样条或(实际上更适合您的示例)为单元提供某种操纵行为。

但是,对于第一种情况,存在一种比路径平滑既简单又给出更好结果的解决方案。它称为Theta *,是A *在网格上的简单扩展(相对较新),允许单元在网格点之间沿任何方向移动。

Theta *与路径平滑

有一个很好的文章,解释西塔*(从我偷了上面的图片)在这里


2

要进行更人性化的运动,请尝试与“转向行为”集成。(经典OpenSteer的C#版本http://sharpsteer.codeplex.com/),您将获得AStar的输出,并让操舵行为关心运动(其中一个示例完全显示了如何执行此操作,请按照路径进行导航)


1

在从点到点导航的情况下,我使用角度差异(当前玩家方向与从当前点到下一个点的方向),然后在移动发生时逐渐将角度更改为最终角度。在这里检查该游戏,飞机从一点移动到另一点,但转弯并不突然,但仔细观察,便可以识别出路径的点。(该游戏只能在移动设备上运行,但最好在iPhone / iPad上运行)。


这正是我最终要做的。
Patryk

1

我对Catmull-Rom样条曲线(@bummzack推荐的一种三次样条曲线)也有好运。关于这些的好处是,样条线将始终通过控制点,而其他许多点则不会。实现这样的事情:

t    = <time*>
t12  = t + 1.0
t23  = t
t34  = t - 1.0
t123 = (t + 1.0) / 2.0
t234 = t / 2

c1 = controlpoint[0];
c2 = controlpoint[1];
c3 = controlpoint[2];
c4 = controlpoint[3];

l12 = lerp(c1, c2, t12);
l23 = lerp(c2, c3, t23);
l34 = lerp(c3, c4, t34);
position = lerp(lerp(l12, l23, t123), lerp(l23, l34, t234), t);

* 时间是控制点1和2之间的值[0,1]。


0

A-> B可以通过使用导航网格而不是网格来解决。这暗示着寻路数据生成的巨大变化。

像C和D这样的情况只是切角:如果角色在路径中和“拐角”(上一个,当前,下一个单元格不在一条直线上的单元)内移动,则将其朝上一个和下一个单元格的方向推。唯一的问题是确定与实际位置的距离(推动距离)。这可能需要与当前单元格的距离作为输入。像这样:

push_dir = average( prevcell.pos, nextcell.pos ) - curcell.pos;
push_dist = cell_half_width - distance( char.pos, curcell.pos );
char.pos += push_dir * push_dist;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.