多年来使用各种游戏物理引擎进行开发,我注意到在同一台机器上我观察到运行之间物理模拟的结果差异很大。最近, Unity 引擎执行此操作,即使物理是按设定的时间间隔(FixedUpdate
)计算的 - 据我所知,它应该完全独立于帧速率
之前我曾在游戏论坛上问过这个问题,并被告知这是由于混乱动作:看到双摆。但是,如果起始条件得到精确控制,即使双摆也是确定性的,对吗?在同一台机器上,不应该浮点数学的行为方式相同吗?
我理解浮点数学准确性存在问题,但我理解这些问题(如here所述)不是相同硬件上的问题 - isn' t浮点不准确还是确定性的吗?我错过了什么?
tl; dr :如果在同一台机器上运行模拟,使用相同的浮点数学运算(?),模拟是否应该是确定性的?
非常感谢你的时间。
答案 0 :(得分:3)
是的,你是对的。在同一台机器上执行的程序每次都会给出相同的结果(至少理想情况下---可能有cosmic rays或影响记忆的其他外部因素,但我会说这些都不是我们关心的问题)。计算机上的所有计算都是确定性的,因此计算机的所有算法都必然是确定性的(这是[{3}})的原因!
您看到的随机性很可能是在程序中使用一些随机数生成器实现的,并且随机数的种子因运行而异。如果您使用相同的种子开始模拟,您将看到相同的结果。
编辑:我不熟悉Unity,但做更多的研究似乎表明FixedUpdate
例程可能是问题。
除音频线程外,如果你没有明确地启动你自己的线程,那么统一的所有内容都在主线程中完成。 FixedUpdate在与Update相同的线程上运行,除了它弥补了丢失的时间并模拟固定的时间步长。
it's so hard to make random number generators
如果是这种情况,那么函数本身看起来有点像:
void physicsUpdate(double currentTime, double lastTime)
{
double deltaT = currentTime - lastTime;
// do physics using `deltaT`
}
由于deltaT
在两个不同的运行中不相同,我们自然会得到不同的行为。这是根据后台运行的其他进程确定的,因为它们可能会延迟主线程。这个函数会被不规则地调用,你会看到不同的运行结果。请注意,这些不规则性主要是不是由于浮点精度,但由于进行集成时的不准确性。 (例如,速度通常由v = a*deltaT
计算,假设自上次更新以来持续加速。这通常不是真的。)
但是,如果函数看起来像这样:
void physicsUpdate(double deltaT)
{
// do physics using `deltaT`
}
每次使用此模拟进行模拟时,您将始终获得完全相同的结果。
答案 1 :(得分:0)
我没有太多使用Unity或其物理模拟的经验,但我发现以下forum post也链接到article,这似乎表明它是&#39 ;使用浮点计算降低精度。
正如你所提到的,很多人似乎不断重复这个问题!
该论坛还链接到此blog post,这可能会对此问题有所了解。