如何实现带有时间增量的到达行为

How to implement arriving behavior with time delta?

本文关键字:时间 何实现 实现      更新时间:2023-09-26

我正在尝试创建一个具有到达行为的自主代理,基于Reynolds的经典Boids论文,更具体地说是Dan Shiffman在natureofcode.com上的实现。这两种方法都很容易理解(和工作),但它们都假设一个固定的标称更新步骤,而不是查询自上次帧更新以来经过的时间,并在欧拉积分步骤中应用这个时间增量。他们的建议很简单:

//pseudocode
acceleration.add(force);
velocity.add(acceleration);
location.add(velocity);

然而,如果我想包含时间增量,那么各种物理论文建议我应该将其重写为:

//pseudocode
delta = timeElpasedSinceLastFrameUpdate();
acceleration.add(force);
deltaAcceleration = acceleration.mult(delta);
velocity.add(deltaAcceleration );
deltaVelocity = velocity.mult(delta);
location.add(deltaVelocity);

这也是有效的,直到我尝试实现转向行为,特别是到达行为。有关方法的参考,请参阅此处链接中的示例6.2:

代码引导行为的性质

有问题的步骤(在伪代码中)是steeringForce = desired - velocity;

在没有时间增量的情况下,"- velocity"对转向力的贡献正确地抵消了当前持有的速度矢量,并使物体在到达目的地时减速停止。

施加时间增量,然而,当我将加速度乘以δ时,转向力有效地由分数时间增量缓和,因此不会对累积速度施加足够的减速以使物体及时停止,并且我得到振荡行为。

我可以通过不将累积力(即加速度)乘以时间增量来"修复"这一点,但这似乎不正确。

我的问题是:

如何生成到达行为的方向力来解释可变的增量时间?

感谢任何帮助!

编辑:我错过了你问题的主要部分。有很多方法可以得到你想要的结果,但它们的方法不同。我能想到的最简单的方法可能是现在跳过steeringForce,而只是修改速度。

我们想要一个向量满足

desired_velocity = velocity + correction

这和你之前写的一样(除了'steeringForce'):

correction = desired_velocity - velocity

通过做velocity + correction,你会立即得到所需的速度,这通常不是你想要的,因为它会导致一个非常不稳定的运动。相反,你可以将修正值固定到某个值,这将导致更平滑的运动:

len = length(correction)
corr_length = len > max_correction ? max_correction : len
correction = correction/len*corr_length

现在你可以写

velocity += correction

这将导致某种程度的动态运动,而不会振荡。


显式时间步长积分(例如,在你的情况下一个前向欧拉)通常写成

new_acceleration = old_acceleration + (delta_t/mass)*force
                                              ^^ note

和类似的,

new_velocity = old_velocity + delta_t*acceleration
new_position = old_position + delta_t*velocity

所以要回答你的问题,你需要在累积之前乘以时间步长:

acceleration.add(force.mult(delta_t/mass));
velocity.add(acceleration.mult(delta_t));
location.add(velocity.mult(delta_t));