载具的物理同步方案

1. 载具的物理模拟

游戏中经常被使用的载具种类有很多,如汽车、摩托、船艇和飞机等。其中,汽车是最为常见的载具。在没有特别说明的前提下,载具通常默认表示汽车。

当然,无论是哪种载具,其在现实世界中的运动状态都很复杂。如何对载具的运动状态进行合理的简化和解耦,建立合适的物理模拟模型,让玩家能感受到真实的物理效果,对载具的物理模拟至关重要。

以游戏中最常见的汽车为例,为了最大程度还原真实的驾驶体验,需要模拟在通过障碍物时悬挂的缓冲效果、踩下油门之后引擎驱动汽车的加速效果,以及转动方向盘时控制轮胎朝向的转向效果。

一般来说,不同物理引擎上的汽车物理模拟都大同小异,可大致抽象为如下所示的流程:

Image


2. 载具物理同步的难点

与大部分游戏场景中的需要进行物理同步的物体相比,载具的运动状态更为复杂,网络同步的难度更高,其主要难点体现在以下几个方面:

  1. 移动速度快:载具在游戏中最主要的作用就是提高玩家所操纵角色的移动速度,因此载具的运动速度在大部分情况下都很快,即便是细微的网络延迟都会造成很大的误差;
  2. 物理交互多:玩家在驾驶载具时可能会频繁与场景中的其他物体发生碰撞、摩擦或者挤压等物理交互。而这些物理交互都会导致载具的运动状态(速度大小、方向,以及朝向)发生剧烈改变,进一步加大了物理同步的难度;
  3. 质量要求高:载具的运动轨迹是平滑的曲线,对物理同步质量的要求更高。频繁拉扯所形成的不自然轨迹会立刻引起玩家注意,影响玩家的游戏体验;
  4. 输入预测难:从1. 载具的物理模拟流程一节中不难知道,载具的运动状态很大程度上由输入数据决定。而输入数据来自于玩家的操作,其变化很难预测,其对载具运动状态所造成的变化自然也就很难预测;

3. 载具物理同步方案

物理同步的基本思路是预测+纠错。载具也是如此。只是与普通物体相比有以下几个区别:

  1. 载具的运动状态由当前的运动状态输入数据一起决定,仅同步载具的运动状态无法满足预测的要求;
  2. 玩家在操作载具时,客户端上的输入数据要立刻生效,否则网络传输带来的输入延迟会极大地影响玩家的操作体验;

为了满足上面的限制,最简单直接的方案是,主控端直接使用输入数据修改载具的运动状态,然后将输入数据发给服务器,再由服务器广播给其他模拟端,并在服务器模拟端上分别使用输入数据修改载具的运动状态。最后,再通过物理同步的方式,纠正不确定性物理引擎在模拟过程中的差异。

Image(1)

红色虚线的圆圈表示服务器同步过来的运动状态,绿色虚线的圆圈表示在相同时刻下服务器的预测结果,而黑色实线的圆圈则表示当前的运动状态。

从上图可以看到,为了满足输入数据立刻生效的要求,载具在服务器上的运动状态一定是滞后于主控端的。此时,当服务器给主控端下发运动状态并尝试进行物理同步时,主控端既要根据输入数据进行物理模拟,又要按照物理同步的处理逻辑修正运动状态。

如何权衡这两者的关系,是载具物理同步的重点之一。如果用服务器下发的滞后数据去纠正主控端的运动状态,那么主控端可能出现拉扯问题。而如果以主控端的物理模拟结果为准去纠正服务器的运动状态,则会面临玩家作弊的风险。

此外,因为模拟端上的数据都来自于服务器,所以即便是在模拟端上进行预测也只能缩小与服务器的延迟。而先行预测的主控端明显快于服务器,因此模拟端与主控端一定会存在延迟。如何缩小模拟端与主控端的延迟,是载具物理同步的另外一个重点。

3.2 UE4的原生方案

UE4使用导航预测算法实现了一套适用于许多应用场景的物理同步方案。因此,UE4并未针对载具的物理同步做过多的额外处理,依然使用其通用的物理同步方案,以服务器下发的运动状态为准强行纠正客户端的运动状态。

更多关于UE4物理同步的细节,可以看UE4的物理同步一文。

同时,主控端每帧都会将最新的输入数据发给服务器,确保主控端与服务器运动状态相差不大。

Image(2)

因此,当网络延迟较大,主控端的输入数据无法及时发给服务器时,主控端会在物理同步逻辑的影响下不断将载具的运动状态纠正至服务器所下发的运动状态。而此时服务器下发的运动状态是使用较长时间之前的输入数据进行物理模拟的结果,所以玩家会感觉到此时载具会失去控制,无法及时响应其输入数据。

网络延迟较大时出现明显的卡顿、滞后感

此外,即便网络延迟较小,玩家在操作载具时也会出现载具来回摆动的现象,这主要有两个原因:

  1. 由于外插值算法的缺陷,UE4的物理同步方案在处理持续转弯的物体时会出现频繁抖动的问题;
  2. 主控端的物理模拟结果和物理同步的结果冲突;

网络较好时也会出现轻微的卡顿

总体来说,在处理载具的物理同步上,UE4的原生方案有多致命的缺陷,并非一个好的方案。

3.3 预测一切:来自《火箭联盟》的启发

根据火箭联盟在GDC 2018上的演讲,可以知道作为一个以载具与球之间的物理交互作为核心玩法的多人PC游戏,火箭联盟更具挑战的点在于不仅需要处理载具的物理同步问题,同时还需要处理因为网络延迟所带来的碰撞问题。

首先,作为一个PC游戏,使用一个权威服务器防止玩家作弊是必不可少的。在此基础上,为了让玩家拥有零延迟的操作体验(No Input Delay),火箭联盟采用的策略是客户端在收到输入数据时马上对操纵的载具进行物理模拟,也就是客户端提前预测

姑且先不讨论客户端模拟结果与服务器结果模拟不一致之后如何纠错的问题,这个方案会带来一个很致命的问题:在同一个客户端上,玩家操作的载具是快于服务器的,而玩家准备踢的球则是慢于服务器的。

玩家踢的球慢于服务器并不难理解,既然要用权威服务器来防止玩家作弊,那么对于影响游戏结果的球来说,其物理状态(位置和速度)由服务器同步给客户端,客户端只负责渲染是一个很合理的方案。

未来的载具准备踢过去的球,自然会出现玩家认为自己踢到了球,而服务器却认为玩家根本没碰到球的问题。

球从左往右运动,载具从上往下运动准备踢球

如何解决这一问题?如果直接使用FPS游戏里常用的延迟补偿(Lag Compension)方案,那么则会出现低延迟的玩家在马上踢到球时,发现球在其他高延迟玩家的交互下突然从身边飞走了。

延迟补偿的具体实现
在客户端踢到球时将载具和球的数据一起发送给服务器,服务器在收到数据包之后,将球拉回到网络延迟前的位置并确认客户端是否踢到了球。如果校验通过,那么服务器则会接受客户端的结果,认为客户端踢到了球并纠正球的物理状态。

让高延迟的玩家影响低延迟玩家的游戏体验显然是无法接受的。为了兼顾所有玩家的游戏体验,最终火箭联盟采用了类似于守望先锋的关键帧同步方案

  1. 客户端在接收到输入数据时直接开始物理模拟,然后记录下当前的物理帧号所有物体的物理状态作为当前的关键帧,并将关键帧数据存入关键帧缓存队列中;

  2. 客户端将输入数据以及对应的物理帧号发送给服务器;

  3. 服务器收到客户端同步的数据数据之后开始物理模拟,然后将当前的物理帧号所有物体的物理状态同步给客户端;

  4. 客户端收到服务器同步的数据时,从关键帧缓存队列里找出对应的关键帧数据进行比对,对于差距比较大的物体,将其物理状态直接回溯到服务器同步过来的状态;

  5. 回溯结束之后,从关键帧缓存队列中取出后续的输入操作,然后一次性执行多次物理模拟,直到将全部输入数据都消耗完为止,确保客户端以正确的状态重新进行预测;

如下图所示,客户端在接收到输入数据时让载具直接移动,而此时客户端的球因为缺少服务器同步过来的数据处于静止的状态。直到后面服务器将数据同步过来时,才发现从第1帧开始球的状态就与服务器出现不同步,而载具则因为输入数据没有发生变化而与服务器保持同步。

全预测方案的具体步骤

此时,客户端先回溯到第1帧,然后将球的状态纠正至服务器同步下来的状态。因为客户端的最新物理帧为4,所以会一次性执行3次物理模拟,同时对载具和球以正确的状态进行预测,确保客户端上的载具和球都快于服务器。这样,客户端上的载具在踢球时,就是以未来的载具未来的球。只要客户端的网络稳定,那么客户端的预测结果就与服务器相差不大,客户端也就感受不到任何延迟。

因为客户端会对所有物体(玩家操作的载具、其他玩家操作的载具和球)的物理状态进行预测,确保其物理状态处于相同的时间线,所以这个预测策略被称为客户端全预测(Client Predict Everything)

在梳理清楚火箭联盟的物理同步方案之后,不难知道在预测失败时需要在一帧内完成回溯以及多次物理模拟的操作,CPU开销很大。为了尽可能地避免客户端预测失败的问题,火箭联盟将服务器和客户端的物理帧率都设置为120帧,以减少每次物理模拟时的差异,但过高的物理帧率无疑会进一步的增加CPU的开销。因此,火箭联盟的物理同步方案比较适合PC或者主机游戏,而不太适合手机游戏。此外,当游戏中的物体过多时,每次回溯的CPU开销和关键帧需要保存的数据也会快速增长,因此也并不适合场景过大、物体较多的游戏。

当然,即便火箭联盟的物理同步方案在应用上存在诸多限制,但其回溯+纠正+重新预测的方案确实可以有效解决服务器的同步数据与客户端的预测数据冲突时的拉扯问题。

3.4 苦痛之路:打满补丁的《看门狗2》

在2017年的GDC上,育碧的开发人员详细地分享了《看门狗2》关于载具物理同步的策略。

《看门狗2》的网络模型是基于状态同步的P2P,主控端在接收到输入数据时直接进行物理模拟,然后将载具的物理状态同步给模拟端,并在模拟端上使用导航预测算法进行预测以减少载具的延迟。因为模拟端并没有使用载具的输入数据进行物理模拟,所以在载具转弯时会出现因为频繁预测失败而出现抖动的现象。

本来最佳的解决方案应该是使用输入数据驱动载具的物理模拟系统,然后根据轮胎的朝向和速度等物理属性来预测载具的转向变化。但《看门狗2》的开发团队觉得这个很复杂,所以使用了更为简单的方案,直接用载具的角速度进行外插值来预测载具的转向,结果确实平滑了很多但仍能看到有轻微的抖动。

也正是因为预测机制的缺陷导致载具的运动轨迹会被频繁纠正,所以《看门狗2》又打了个补丁:使用主控端同步给模拟端的快照(Sanpshot,也就是载具的物理状态)对模拟端的载具进行内插值,从而得到更为准确的运动轨迹。

但内插值会增加载具在模拟端上的延迟,而外插值可以减小延迟所带来的运动状态差异。因此,《看门狗2》使用了内插值和外插值混合的策略,以尽可能缩小模拟端上的载具与主控端的差异。下图演示了这个策略的具体工作原理:

其实这个策略很简单,总结起来就一个原则:有最新的快照就优先用内插值得到较为准确的轨迹,如果没有就使用外插值尽可能缩小与主控端的差异。

内插值和外插值的混合策略

如上图所示,模拟端在收到第一个SnapShot(红色的点)时,因为没有下一个SanpShot用于内插值,此时执行的是外插值,所以模拟端的运动轨迹和主控端不一致。等收到第二个SnapShot的时候,开始内插值,此时模拟端则可以以一个较为准确的运动轨迹追上主控端。最后,模拟端与客户端的延迟为3帧,而如果单纯用内插值,延迟则为5帧。

细谈网络同步在游戏历史中的发展变化(下)一文中,关于这一过程的解读明显是错的。

此外,在网络比较好的情况下,有可能模拟端在追上最新的SnapShot之前,又收到了一个新的SanpShot。此时,如何决定外插值和内插值的比例是一个很大的问题。如果外插值比例过大,那么载具运动轨迹的准确性会变差。而如果内插值的比例过大,那么载具的延迟会增加。

因此,《看门狗2》引入了TimeOffset的概念,用TimeOffset来决定内插值和外插值的比例。TimeOffset的大小为网络平均延迟加上一个由载具速度决定的修正值,并且限制其最大不超过300ms。

(1)TimeOffset必须大于网络延迟是合理的。如下图所示,如果外插值的预测完全正确,那么模拟端载具的物理状态在时刻T一定可以与主控端载具的物理状态(SnapShot 3同步下来的数据),此时再进行外插值反而会加大模拟端和主控端的差异;
(2)综合考虑网络的波动性和预测的不准确性,在网络延迟的基础上加上一个修正值是很有必要的,只是这个修正值是一个经验数值;

TimeOffset的用法

当然,外插值和内插值混合的方案只能减少延迟而不能完全消除延迟。玩家操作的载具在与其他玩家操作的载具碰撞时,依旧会出现玩家当前的载具撞击了其他玩家过去的载具的问题,也就是《火箭联盟》面临的问题。更要命的是,这个方案在载具相互碰撞时会出现bug。

如下图所示,不妨假设下面两个车相互撞击。此时模拟端上的白车在与蓝车碰撞之后,因为还没收到主控端下发的SnapShot,所以会使用外插值继续向前行驶。而白车在主控端上则因为碰撞向后运动,并随后向模拟端下发一个向后运动的Snap Shot。当模拟端的白车在收到该Snap Shot之后,则会因为外插值而向后运动更长的距离。

撞击时载具的运动图解

因为《看门狗2》没有权威服务器,没有一个权威的碰撞结果让客户端有机会纠正网络延迟带来的差异。所以为了让载具有更为自然的碰撞表现,《看门狗2》又打上了物理模拟融合(Physsics Simulation Blending)补丁:在碰撞时让模拟端的载具完全受物理模拟的控制,随后不断减小物理模拟的权重增大网络同步的权重,从而让载具在碰撞的时候有更加自然的表现。

Physsics Simulation Blending

虽然使用物理模拟融合之后碰撞效果也没有很自然,但至少比使用物理模拟融合前的碰撞效果好了很多。

总体来说,《看门狗2》最终的载具物理同步效果并不好,虽然主要是受限于P2P的网络模型,但也从某种程度上说明载具的物理同步确实很难,否则也不需要打这么多补丁才能得到一个勉强能看的效果。

里面提到的很多优化策略大部分都没有多少参考价值,都是为了弥补P2P的缺陷所打的补丁,唯一比较值得参考的点是通过内插值和外插值混合的方式,确保模拟端载具以比较准确的轨迹运动的同时减少和主控端的延迟。


4. 总结

物理同步一直是多人网络游戏中比较不好处理的部分,如何处理拥有复杂物理模拟逻辑的载具更是难上加难。

目前并没有针对载具物理同步的通用解决方案,基本都需要根据项目的具体需求和限制来决定具体的同步策略。就像《火箭联盟》的方案可以获得一个很棒的同步效果,但其回溯以及高物理帧率所带来的巨大CPU开销使其很难在手机游戏上落地。


参考文章

  1. 车辆动力学及在Unity、UE4中的实现
  2. UE4的物理同步
  3. 浅谈物理引擎的网络同步方案
  4. GDC 2018, It IS Rocket Science! The Physics of Rocket League Detailed
  5. Fast-Paced Multiplayer (Part IV): Lag Compensation
  6. 复制混乱——看门狗2的载具同步(翻译)
  7. 手游中的载具物理同步的实现方案
  8. Extrapolated physics interpolation mode
  9. 细谈网络同步在游戏历史中的发展变化(下)

载具的物理同步方案
https://asancai.github.io/posts/f93cc4a5/
作者
RainbowCyan
发布于
2024年2月28日
许可协议