手游中载具物理同步的实现方案

Ned 腾讯互娱工程师

▌一.载具同步的难点

 

 

FPS游戏里的载具,基本上是随着“吃鸡”玩法一起涌现的,基本上每一个大地图的玩法都少不了载具系统。可能在很多人的印象里,人物移动的网络同步不是一件很复杂的事情,按照UE3状态机+走路点的方式来实现,基本上最终结果就是可以接受的。但是载具的网络同步却要复杂的多,见下表:

 

 

---

 

▌二. 网络同步的本质

 

我个人觉得对于客户端来说,网络同步可以类比为一个信号重建的过程,从remote端接受到原始信号的一系列离散的“采样数据”,然后试图在本地还原出原始信号,可以从信号采样的角度描述成sampling->reconstruction filtering->resampling的过程。对于人和载具的移动同步来说,“原始信号"就是连续的运动轨迹。好的同步,就等同于好的信号重建结果。

 

对于移动同步来说,而它的特殊之处在于:

 

(1)网络延时和传输速度的不稳定,也就是说得到的采样数据(网络同步包)不是等时间间隔的;

 

(2)手游对网络传输量有所限制,所以网络同步包的频率不可能太大,也就是说sampling rate比较低(注意到resampling rate其实是游戏帧率),undersampling在所难免;

 

(3)原始信号会有“突变”的情况,例如载具高速撞到墙上马上停止下来;

 

(4)有实时性要求,本地做信号重建的时候只能拿到历史的有延迟的数据,而对于重建结果来说普通情况下只能允许与原始信号存在几百毫秒的延迟,特殊情况下要求几乎零毫秒的延迟。

 

---

 

▌三.同步系统概要

 

-名词说明

 

 

(1)载具的权威端称之为master或者1P,它代表着“原始信号”,它的运动状态就是“正确的”那个状态。它的host可以是服务器,也可以是操控着这个载具的那个客户端。

 

(2)模拟端称之为replica或者3P,它就是需要在某个客户端上通过信号重建出来的载具对象。

 

 

(3)将用于同步的网络包所包含的数据称为snapshot,其中包含了物理状态信息,例如状态记录时刻、位置、朝向、速度、加速度、角速度等。如上图中的红色圆形所示。

 

(4)同步算法中的Interpolation和Extrapolation

 

Interpolation:基于收到的一组snapshot,插值求出过去某个时刻master的位置。如果采取此策略,replica的状态一定是跟master过去的某个状态接近。

 

Extrapolation:基于最后一个snapshot,预测出当前/未来某时刻master的位置。因为是预测,所以肯定就会有错的时候,但是如果master在发出最后一个snapshot之后,一直在做加速度恒定的运动的话,那么推算出来的状态就会跟master在目标时刻的状态一致。

 

可以看到2个策略各有好处,interpolation与过去状态高度相似,但是有延迟。expolation无延迟,但是可能会出现预测错误。

 

注:Unity的rigidbody就有一个类似的选项,其实表达的是同一个意思。

 

(5)Dead Reckoning[2]

 

中文名叫导航推测算法,它利用现在/过去物体位置及速度推定未来位置方向的航海技术。在移动同步的上下文里,这个技术就是根据历史的snapshot去猜测一段时间之后(例如50ms)master的位置。猜完之后还需要基于replica当前的运动状态,设计一条“真实的”移动轨迹使得一段时间之后能够与推测出来的master的移动状态一致。

 

其实Unreal的rigidbody同步机制里面,也是包含了dead reckoning思想的,我记得对应的函数名叫做applyRBState()。

 

(6)Physics Simulation Blending表示将物理计算的结果和同步算法得到的结果进行混合,混合的权重是变化的。从实现的角度来说是在不断修改物理引擎计算出来的结果。

 

-系统概要

 

* master向replica所在客户端以较低频率(例如50ms)发送snapshot,包含当时的时刻和运动状态,这个就是原始信号的采样数据;

 

* master在生成snapshot的时候,会对一些数据求历史均值,例如加速度,角速度等。这个其实是在做reconstruction filter,把一些高频分量给去掉;

 

* 如果当前1P和3P没有发生碰撞的可能,则:模拟端客户端试图重建出replica在过去某时刻的运动状态,也就是基于snapshot进行interpolation;

 

* 如果当前1P和3P有发生碰撞的可能,则:客户端基于dead reckoning技术确定replica在当前时刻的运动状态,也就是基于snapshot进行extrapolation,同时确保replica开启了物理模拟,如果1P和3P发生碰撞,则触发physic simulation blending,碰撞的瞬间混合权重为1,控制权完全交给物理系统,随着时间的推移,混合权重逐渐降低为0,最终完全受同步算法控制。

 

---

 

四. 核心技术详细说明

 

(1)网络同步状态下载具之间真实物理碰撞的实现

 

为了实现1P和3P载具的“正确的”碰撞表现,需要解决这3个问题:在碰撞发生之前replica的精确同步、碰撞时候的物理模拟、对物理模拟导致的replica和master的运动状态不一致性的恢复。

 

设想下面这个case,载具A和B面对面地高速行驶,最终发生碰撞。如果在A的宿主客户端,B作为replica与它的master的位置差别较大的话,那么很可能出现一个情况:在A的宿主客户端已经发生了A和B的碰撞,而此时在B的宿主客户端2者却还相离几米远。这种不一致性,一般被称作conflict。要较好的解决conflict,首先当然要保证replica和master不一致的状态不能差的太多,那么首先就要确保在A和B的宿主客户端上发生碰撞的时间和位置是非常接近的。只要replica的同步在时间和空间上都足够精确,那么这一点就能保证。我们通过基于Dead Reckoning技术的extrapolation同步策略来实现较精确同步。第二点,则是在碰撞发生时候让本地的物理引擎去模拟出一个真实的碰撞效果。这一点只要保证碰撞发生前物理模拟是开启状态就可以实现。如果3P不是始终开启物理模拟的话,则需要预测碰撞的发生,在可能即将发生碰撞之前,启用物理模拟。因为snapshot的网络延时和extrapolation的预测本质,几乎可以肯定,本地物理模拟之后,replica和其master的位置是不一致的,因此必定需要第三点,也就是conflict resolve。这个则是通过Physics Simulation Blending技术,来保证碰撞发生后的一小段时间内,replica的运动状态逐渐趋于与其master一致,最终消除不一致性。

 

(2)Projective Velocity Blending

 

这是Dead Reckoning技术的一种,它是以物体在某个时间段内进行的是均加速直线运动为前提,来进行预测和本地轨迹的计算。算法保证得到的结果会是一条平滑的曲线。参见下面的2张图(听起来很复杂,其实用的是初中物理知识)。

 

 

在本文所述的同步框架里,Projective Velocity Blending用来实现expolation同步。

 

(3)Physics Simulation Blending

 

这个技术理解起来其实很简单。想象replica载具存在两条不同的运动轨迹:一个是基于snapshot用同步算法计算出来的轨迹,另一个是本地物理模拟出来的轨迹。Physics Simulation Blending就是将这两条轨迹(包含位置和速度)进行混合,其中混合系数随时间变化。在碰撞发生的一瞬间,系数为1,replica的运动完全受物理模拟控制,从而表现出真实的碰撞效果。随着时间的推移,系数逐渐降低为0,replica的运动完全受到同步算法控制。

 

(4)Intepolation同步策略存在的意义

 

前面说过,实现真实碰撞表现,必须使用extrapolation的同步策略,那么interpolation同步策略存在的意义是什么呢?extrapolation在实际运用中,最大的问题是,因为始终只使用表征master的“最新”状态的snapshot去做预测,所以抗网络抖动能力,非常的差。网络一不稳定,可能就几百ms都收不到snapshot了,这种情况下还继续做预测基本上就会误差越来越大,导致网络恢复正常之后的conflic resolve没法做得很好。而从另外一个角度来说,如果1P和3P不会发生碰撞,那么我们是完全可以接受replica的本地同步状态具有延迟性的。那么使用intepolation策略,配合一个snapshot buffer,就可以更好的适应网络抖动的情况。具体来说就是假如我们的目标是同步replica在150ms之前的状态,正常情况下的网络延时是50ms,snapshot的发送频率是50ms。在这种情况下,我们始终是使用倒数第2个和倒数第3个snapshot来做interpolation。如果网络发生抖动导致最新的snapshot包没按时接收到,我们可以使用倒数第2个和倒数第1个snapshot来做intepolation。如果更长的时间还收不到snapshot,我们还可以把同步策略切换成extrapolation。

 

---

 

▌五. 小结

 

同步框架非原创,参考了Watch Dogs 2 团队在GDC2017上的一篇分享[1]。

 

在实际应用中,这套同步框架还可以被应用到了其他类型的载具上,包括了四轮车、两轮车、直升机、船、无人机。

 

最后,非常感谢相关同学与我在一些实现技术细节上毫无保留的探讨,谢谢。

 

*引用:

 

[1] Replicating Chaos: Vehicle Replication in 'Watch Dogs 2'  :
https://www.gdcvault.com/play/1024597/Replicating-Chaos-Vehicle-Replication-in

[2] Defeating Lag With Cubic Splines:
http://archive.gamedev.net/archive/reference/articles/article914.html

阅读与本文标签相同的文章