首先,500ms延迟的情况下,同时保证游戏流畅度和公平性,是不可能的
我们假设A是高延迟玩家,B是低延迟玩家
插值
当A行走的时候,对A的移动进行插值,在0时刻A向右行走,服务端开始插值到500时刻,这时如果A并没有改变操作 那么A的行走就是准确的。
当然这种方法大多数是路径控制
B会看到A的移动十分的生硬,如果延迟保持500ms,可以观察到A以500ms为单位进行直线移动
补偿
当A释放了技能,服务端会对A的技能进行补偿,例如吧游戏时间回退一定时间并加入A的技能对结果进行判断,吧结果反应到当前结果
CSGO一定程度上是这种情况
B会看到A存在小范围的瞬移,抖动。可能会莫名其妙受到A的攻击,很大程度上存在着不同程度的不公平,但可以保证玩家流畅体验。
同步
网络的游戏基本不能考虑基于坐标同步,因为这样会造成大量对低延迟玩家的惩罚
在同步之前,游戏中的时间其实有两个,游戏时刻和真实时刻
对于A和B来说,游戏时刻等于真实时刻,他们会基于当前的游戏内容判断
而对于服务器来说,游戏时刻总是晚于真实时刻的
t是真实时间,t'是游戏内时间
我们假设服务器是10Hz的 (每100ms一帧
在 t' = t = 450 的时候, A 执行动作 a
B在 t' = 500 时候死亡, 但 B 在 t' = t = 750 的时候移动了自己的位置
这个数据包在 t = 500 发送给服务器
服务器在 t = 1000时刻 收到 t = 500 时发送的 描述 t' = 450 的动作 a
那么这个时候有几种做法
吧动作a插入到 t' = 450 中去,重新计算结果
这时 B 死亡,B会在 t' = 500 死亡,t = 1100 的时候看到自己死亡
吧动作a插入到最新的一帧中去,重新计算结果
这时 B 存活,相当于A在 t' = 900 的时候释放了这个技能
由于 B 在 t' = 750 的时候移动了位置,A并没有击中B
吧动作a插入到 n 帧之前, 重新计算结果,如果这时n = 2
相当于A在 t' = 700 的时候攻击,B在 t' = 750 的时候移动了位置
B 会在 t' = 750 的时候死亡, t = 1100 的时候看到自己死亡
但是这些动作都没有经过“同步”
A和B只是吧自己的动作和时间通知服务器,交由服务器判断
而这时,加入同步机制
A 在 t' = t = 500 的时候计算出B已经死亡,
并把结果通知服务器
同样 B 在 t' = t = 750 的时候移动,
并把坐标通知服务器
在 t = 1100 的时候,服务器 t = 1000 的数据包 内包含了 a 的通知
将其加入自己游戏时间线中,判断自己死亡
很明显,这是不公平的,但是在PVE中,可以使用这种做法,因为这种不公平更倾向于对敌方单位的不公平,玩家的游戏体验可以一定程度上提升
经过这些的结合,我们可以吧一些关键的信息,比如死亡进行同步,而大量的动作,同步只会导致某一个特定玩家损失惨重(战争框架大体上是类似的做法,延迟高的玩家A体验流畅,而且保留有一定的伤害能力,但诸如开门、道具使用等等地方就会有相当大的延迟