游戏networking物理碰撞

如何模拟两个客户控制的车辆在一个典型的客户/服务器networking游戏设置中(明智地)碰撞? 我没有阅读这个着名的博客文章如何做分布式networking物理(一般没有传统的客户端预测),但这个问题是具体如何处理拥有对象的冲突。

假设客户端A比服务器提前20ms,客户端B比服务器提前300ms(同时计算延迟和最大抖动)。 这意味着,当两辆车相撞时,两个客户将看到另一个320毫秒后面 – 与另一辆车的速度相反的方向。 在瑞典高速公路上的直接对比意味着16米/17.5码的差距!

什么不要尝试

实际上我们不可能外推这些位置,因为我也有非常复杂的车辆,所有车辆都有接头和车身,而这些车辆又有线性和angular度位置,速度和加速度,更不用说用户input的状态了。

我不知道一个完美的解决scheme,我有一种不存在的感觉。 即使您可以准确预测车辆的未来位置,您也无法预测用户操作控制的方式。 所以问题归结为最小化客户端/服务器滞后的负面影响。 考虑到这一点,我会从最不惊讶的原则的位置(从维基百科解释)来处理这个问题:

在用户界面devise中,最令人惊讶(或惊讶)的原则是,当一个界面的两个元素发生冲突或模棱两可时,行为应该是在冲突发生时,人类用户至less感到惊讶的行为。

在你的例子中,每个用户看到两辆车。 他们自己的,还有另一个球员的。 用户期望他们自己的车辆的行为与他们控制的方式完全一样,所以我们无法玩这个模拟的方面。 但是,用户不能确切地知道另一个用户如何控制他们的车辆,并且我会使用这种模糊来隐藏用户的滞后。

这里是基本的想法:

  1. 服务器必须做出关于即将发生的碰撞的决定。 碰撞检测algorithm不一定是100%完美的,它只需要足够接近以避免明显的不一致。
  2. 一旦服务器确定两个车辆将发生碰撞,它就向两个用户中的每一个发送指示即将发生碰撞的消息。
  3. 在客户A上,调整车辆B的位置(实际上)以确保发生碰撞。
  4. 在客户B上,调整车辆A的位置(实际上)以确保发生碰撞。
  5. 在碰撞后,每辆车的位置可以根据需要进行调整,以便最终的结果与游戏的其余部分保持一致。 这个部分正是医生在他的回答中提出的。

这样,每个用户仍然完全控制自己的车辆。 碰撞发生时,不会是意外的。 每个用户都会看到其他车辆向他们移动,他们仍然会有实时模拟的感觉。 好的是,这种方法在低滞后条件下反应良好。 如果两个客户端都有到服务器的低延迟连接,则调整量将很小。 当然,最终的结果会随着滞后的增加而变差,但这是不可避免的。 如果有人正在通过几秒钟的时间间隔进行一个快节奏的动作游戏,他们根本无法获得完整的体验。

也许你能做的最好的事情并不是真实地显示实际的碰撞,而是假设事情正在实时发生。

由于客户端在服务器后面(延迟),并且服务器需要显示碰撞的结果,所以客户端可能会做的事情是显示一个闪存或爆炸或其他graphics来分散用户并购买足够的在服务器端计算碰撞结果。完成预测后,将其发送回客户端进行演示。

不好意思回答“什么不要尝试”,但我从来没有听说过一个解决scheme,不涉及预测客户端的结果。 考虑一个简化的例子:

客户A静止不动,看着客户B的车辆靠近悬崖。 客户B的车辆能够立即将速度降低至0,并且在越过悬崖之前的最后时刻这样做。

如果客户A试图实时显示客户B的状态,则客户A别无select,只能预测客户B掉下悬崖。 在deviseMMORPG游戏时你会看到这样的情况,玩家的angular色在全速运行时能够立即停止。 否则,客户端A可能会在状态更新进入时显示客户端B的状态,但这是不可行的,因为客户端A需要能够在您的场景中实时与客户端B交互(我假设)。

你可以尝试简化碰撞模型,以便推断是可能的实时预测? 也许让你的“关节和身体遍布”有处理器较less密集的物理模型,像一些立方体或球体。 我不太熟悉如何提高碰撞检测的效率,但我认为这是通过检测比视觉模型复杂的模型的碰撞来完成的。

关于“什么不要尝试”。 你假设你需要完美的预测,但你永远不会find一个完美的解决scheme,在一个复杂的物理游戏。 一个近似值可能是你能做的最好的(例如,大多数商业物理引擎可以在物理场景中投射一个形状并返回第一个碰撞点)。

例如,我在Glenn(你提到的博客海报)的指导下,实施了Mercenaries 2networking物理的一些关键部分。 即使是一个单一的刚体,也不可能把所有必要的物理状态推过电线。 Havok物理学逐渐产生每个帧的接触点,所以当前的“接触stream形”是保持模拟确定性的物理状态的必要部分。 这也是太多的数据。 相反,我们发送了所需的变换和速度,并使用力和力矩轻轻地将身体推到位。 错误是不可避免的,所以你需要一个很好的纠错scheme。

我最终做的只是简单地跳过预测,简单地这样做:

  1. 客户对自己的立场有很多的说法,
  2. 服务器(几乎)只有在与另一个dynamic对象(即不是静态环境)发生“高能量”碰撞时才说明拥有客户端的位置。
  3. 客户端从服务器接收位置更新时采用meshoffset=meshpos-physpos ,然后设置每个帧的meshpos=physpos+meshoffset并逐渐减小meshoffset

在大多数情况下(在低延迟的情况下)看起来相当不错,我甚至不必为了得到平滑过渡而扯淡我的四元数。

跳过预测可能会给高延迟的客户一个可怕的经验,但如果我打算发行这个独立游戏,我没有时间详谈。 曾经有一段时间,创build一个半屁股的解决scheme,很好,但最好的。 ;)

编辑:我最终最终添加了Glen Fiedler(博客作者在问题中提到)为Mercenaries 2实现的“所有权”function:每个客户端获得它们碰撞一段时间的(dynamic)对象的所有权。 这是必要的,因为在高延迟和高速情况下穿透深度较深。 当您看到GDCvideo演示文稿时,这个解决scheme的效果与您想象的一样好,可以绝对推荐!

几个想法。

  1. 点对点更好地处理延迟和高速。

所以如果这是你自己的引擎,那么切换到点对点。 然后根据他们的buttoninput来推断另一个同伴的车辆,以向前移动到现在的位置。 你设置的碰撞,使你碰撞其他车辆,就好像它的世界。 也就是说你打了

这意味着当你碰撞对方时,你反弹了,在同伴的networking上,他们反弹了你,所以看起来大致正确。 延迟越低,效果越好。

  1. 如果你想去客户端/服务器,那么这将不如p2p

要尝试的事情o)在p2p中推断客户端以执行碰撞检测。 o)将冲突结果发送给客户并推断

请注意,这永远不会像p2p一样好。 基本上高速和延迟=错误,所以消除延迟是最好的策略。 P2P是这样做的。

除了在客户端预测其他用户可能在哪里并发送碰撞信息以及如何处理它到服务器之外,大多数MMO处理滞后的方式是服务器“过去”运行。 基本上他们缓冲最近的input,但是只对过去发生的事情做出反应。 这可以让你在需要的时候“窥探未来”(例如,当你的时间框架内发生碰撞时,你可以看缓冲input看看会发生什么,并决定碰撞是否是真实的)。

当然,这会给程序增加额外的复杂性,因为您必须考虑将什么数据发送给客户,以及他们应该如何应对。 例如,您可以将整个“未来”缓冲区发送给客户端,并让他们查看哪些可能的冲突实际发生,哪些不会发生。

罗斯有一个好点。 你可以简化你用来检测碰撞的模型,把它抽象成简单的体积(即车辆的粗糙的四方形轮廓)。 然后,您可以根据简单的体积和精确体积的详细计算来进行预测,同时让用户分心“爆炸”。 它可能不完美,但可以让你加速你的碰撞检测。