Box2D 物理是否依赖于帧速率?

Uwa*_*s A 2 android frame-rate box2d game-physics

我正在为 Android 制作 2D 横向卷轴游戏,并考虑使用 Box2D 来实现物理效果。我想知道在使用 Box2D 时,如果设备的帧速率从 60 fps(Android 的上限)下降到例如 30 fps,所有物理效果都会随之减慢吗?

详细来说,我将使用实时在线多人游戏,因此不能将帧速率视为恒定值。因此,如果多人游戏中的一个设备以 60 fps 运行,另一个设备以 30 fps 运行,并且一个物体应以 10 米/秒的速度移动,那么在较慢的设备上它会以 5 米/秒的速度移动吗?

我想使用Box2D,所以如果是这种情况,有办法解决吗?

Fuz*_*ers 5

我认为你的问题实际上是两个问题。

1)是否应该在模拟过程中改变物理时间步长的速率。

不,你不应该。。您可以在游戏循环的一个时间步长期间多次迭代引擎(Step(...)使用相同的步长值多次调用该函数)。

来自 2.3.0 Box2D 手册的 2.4 节:

可变的时间步长会产生不同的结果,这使得调试变得困难。因此,不要将时间步长与帧速率联系起来(除非您真的非常需要)。

2)如何连接两个实时物理模拟并将它们的物理更新周期相互关联。

曾几何时,有一款改变类型的游戏,名为《帝国时代》。它拥有数千个人工智能单元在 28.8 网络上近乎实时地互相战斗。它的效果非常好,有人写了一篇关于他们是如何做到的文章:

  1. 文章。
  2. 文章的 pdf 版本。

我为我的更新循环调整了该技术和下面的代码,以便我可以控制在两台不同 iPad 上相互运行的两款游戏的帧速率。

void GameManager::UpdateGame()
{
   const uint32 MAXIMUM_FRAME_RATE = Constants::DEFAULT_OBJECT_CYCLES_PER_SECOND();
   const uint32 MINIMUM_FRAME_RATE = 10;
   const uint32 MAXIMUM_CYCLES_PER_FRAME = (MAXIMUM_FRAME_RATE/MINIMUM_FRAME_RATE);
   const double UPDATE_INTERVAL = (1.0/MAXIMUM_FRAME_RATE);

   static double lastFrameTime = 0.0;
   static double cyclesLeftOver = 0.0;

   double currentTime;
   double updateIterations;

   currentTime = CACurrentMediaTime();
   updateIterations = ((currentTime - lastFrameTime) + cyclesLeftOver);

   if(updateIterations > (MAXIMUM_CYCLES_PER_FRAME*UPDATE_INTERVAL))
   {
      updateIterations = MAXIMUM_CYCLES_PER_FRAME*UPDATE_INTERVAL;
   }

   while (updateIterations >= UPDATE_INTERVAL)
   {
      //      DebugLogCPP("Frame Running");
      updateIterations -= UPDATE_INTERVAL;
      // Set the random seed for this cycle.
      RanNumGen::SetSeed(_cycleManager->GetObjectCycle());
      // Dispatch messages.
      _messageManager->SendMessages();
      // Update all entities.
      _entityManager->Update();
      // Update the physics
      _gameWorldManager->Update(Constants::DEFAULT_OBJECT_CYCLE_SECONDS());
      // Advance the cycle clock.
      _cycleManager->Update();
   }

   cyclesLeftOver = updateIterations;
   lastFrameTime = currentTime;
}
Run Code Online (Sandbox Code Playgroud)

这段代码使执行的迭代次数保持在上限和下限之间平衡。需要注意的一个关键问题是,如果没有及时收到来自其他玩家的消息,则不会实际调用此函数。这有效地将两个物理系统结合在一起。

3)你(也许)真正应该知道的部分

如果您计划在两台设备上使用 Box2D 来独立运行物理,那么您几乎肯定会在短时间内看到它们出现分歧。我在 iPad 2 和 iPad 3 上运行游戏,发现几秒钟后它们出现了分歧(其中一个发生了冲突,而另一个则没有)。这是因为浮点数的舍入行为因多种因素而异。对于一些快速计算来说,没有问题。但是,当这些值通过积分器不断循环时,小的差异会渗透到低阶位并累积(例如,正如您在物理模拟中看到的那样)。双精度有一点帮助,但最终没有帮助。

通过在多个 CPU 上的弹跳球场中查看特定弹跳球的一些简单测试(例如,对于完全相同的代码,iPad 2 与 iPad 3)将显示这一点。运动几秒钟后,错误就会逐渐出现,突然间,您的速度/位置就足以产生影响。

定点数学是解决这个问题的方法,但这种方法也会导致其自身的疯狂。曾经,Box2D 有一个定点版本,但这个时间已经过去了。

我什至尝试过制作一个定点版本的 Box2D,但被另一个项目(太空蜘蛛必须死!)分散了注意力。有一天...

对于您的特定情况(即您没有进行独立模拟或没有按照预期工作的方式进行模拟),这可能不是问题,如果不是,也不必担心。

您可以在我的博客上看到许多其他 Box2D 内容(但不是这个游戏......它还没有出现)。

这个有帮助吗?