阻尼有什么用?

What is damping for?

考虑以下用于在游戏中的积分过程中更新物理对象速度的语句:

velocity = velocity * 0.999f + acceleration;

将速度乘以一个略小于1的值称为“阻尼”,0.999f是“阻尼系数”。据说阻尼是消除数值不稳定造成的多余能量所必需的。

我不明白这个。我也可以使用 1.001f 作为“阻尼因子”,并声称它是为了增加由数值不稳定性引起的缺失能量(而不是超过能量):

velocity = velocity * 1.001f + acceleration;

对吧?我错过了什么?

我不是在谈论阻力,是吗?好吧,毕竟,0.999f 阻力系数正在移除与速度成正比的部分。阻尼只是阻力吗?

如果您使用 *1.001f 方法,您的对象将倾向于人为加速。事实上,他们很快就会离开你的 game-world,可能是因为移动速度极快。

另一方面,*0.999f 方法不会导致这样的 conspicuous/weird 行为,因为玩家的大脑很容易将其解释为“阻力”(如果他们注意到的话) .

更改知识来源,正弦显然作者在物理模拟领域知识不足。

看起来有些人使用了 Forward Euler method 不守恒的系统总能量。作者不理解这个问题并使用“欺骗”作为邪恶的黑客。

正确的解决方案是使用不同的算法。最简单的就是Verlets algorithm (simple as Euler method). Other alternative is called Leap-Frog,也很容易理解。

还有其他更复杂的算法来模拟物理。

Forward Euler method 有什么问题吗?在这个近似中,每一步都会引入一个系统误差。在每个步骤中,系统都会获得一点能量。错误不是计算精度有限的结果,而是算法如何工作的问题。更改时间步长可以减少此问题,但速度不够快。经典的例子是行星轨道的模拟,在这个算法中它不是椭圆形的(它应该是),而是螺旋形的,每个轨道都会使行星远离太阳。

如果为我描述了补救措施It is said that damping is necessary to remove excess energy caused by numerical instability.,这清楚地表明作者不知道还有其他算法的数字复杂度相同,但没有这个弱点。这里加拖拽力是一种作弊

现在,如果您使用物理实现游戏,这种“作弊”是无害的。如果您正在模拟某些物理过程,那么这是最糟糕的方法,会产生错误的结果。

在替代算法中,错误不是系统性的,系统会节省总能量。

阻尼系数0.999f或DAMPINGdigital low-pass filter中的α来平滑计算出的速度。


OP 有

Consider the following statement for updating the velocity of a physical object during the integration process in a game:

velocity = velocity * 0.999f + acceleration;

What am I missing?

缺少的是隐含的时间比例缩小 1/1000。

//         old velocity         new velocity
//         v------v             v------------v 
velocity = velocity * 0.999f  + acceleration*t*0.001;
//                    factor1                  factor2, their sum is 1.0

t*0.0011.0 并且肯定已经包含在更新周期和用于表示 accelerationvelocity 的单位中。


另一种方法是使用真实单位,让编译器看到 * (mm_to_m * UPDATE_PERIOD * DAMPING) 正在缩放 1 并且将发出信任高效的代码。

double acceleration; // mm/s/s
double velocity;     // m/s
#define UPDATE_PERIOD (1.0 /* seconds */)
#define DAMPING 0.001
#define mm_to_m 1000.0

velocity = velocity * (1.0 - DAMPING) + acceleration * (mm_to_m * UPDATE_PERIOD * DAMPING);