阻尼有什么用?
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或DAMPING
是digital 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.001
是 1.0
并且肯定已经包含在更新周期和用于表示 acceleration
和 velocity
的单位中。
另一种方法是使用真实单位,让编译器看到 * (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);