3.快节奏的多人游戏 (第三部分):实体插值

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_25327609/article/details/88897249

英文原文地址 Fast-Paced Multiplayer (Part III): Entity Interpolation

能力有限,如有错误,请谅解,并欢迎指正!

介绍


      在本系列的第一篇文章中,我们介绍了权威服务器的概念及其防止客户开挂的用处。然而,天真地使用这种技术可能会导致关于可玩性和响应性的潜在问题。在第二篇文章中,我们提出了客户端预测作为克服这些限制的方法。

      这两篇文章的最终结果是一组概念和技术,允许玩家以一种感觉完全像单人游戏的方式控制游戏中角色,即使通过互联网连接连接到权威服务器也是如此。传输延迟。

      在本文中,我们将探讨将其他玩家控制的角色连接到同一服务器的后果。

服务器时间步长


      在上一篇文章中,我们描述的服务器的行为非常简单 - 它读取客户端输入,更新游戏状态,并将其发送回客户端。但是,当连接多个客户端时,主服务器循环会有所不同。

      在这种情况下,几个客户端可能同时发送输入,并且速度很快(玩家可以发出命令的速度,按箭头键,移动鼠标或单击屏幕)。每次从每个客户端接收输入然后广播游戏状态时更新游戏世界将消耗太多的CPU和带宽。

      更好的方法是在接收客户端输入时对其进行排队,而无需任何处理。相反,游戏世界以低频周期性地更新,例如每秒10次。每次更新之间的延迟(在这种情况下为100ms)称为时间步长。在每个更新循环迭代中,应用所有未处理的客户端输入(可能以比时间步长更小的时间增量,以使物理更可预测),并且将新的游戏状态广播给客户端。

      总之,游戏世界以可预测的速率独立于客户输入的存在和数量而更新。

处理低频更新


      从客户端的角度来看,这种方法与以前一样顺利 - 客户端预测的工作与更新延迟无关,因此它显然也可以在可预测的(如果相对不频繁的)状态更新下工作。然而,由于游戏状态以低频率广播(继续该示例,每100ms),客户端具有关于可能在全世界中移动的其他实体的非常稀疏的信息。

      第一个实现将在收到状态更新时更新其他角色的位置; 这会导致非常不稳定的运动,即每100毫秒离散跳跃而不是平滑运动。
客户端2看到的客户端1
      根据您正在开发的游戏类型,有很多方法可以解决这个问题; 一般来说,你的游戏实体越可预测,就越容易做到正确。

航位推测法


假设你正在制作赛车游戏。一辆真正快速行驶的汽车是非常可预测的 - 例如,如果它以每秒100米的速度运行,一秒钟后它将比它开始前大约100米。

为什么“粗略”?在那一秒钟内,汽车可能会加速或减速一点,或者转向右侧或左侧一点 - 这里的关键词是“有点”。汽车的可操作性使得在高速时它在任何时间点的位置高度依赖于其先前的位置,速度和方向,而不管玩家实际上做什么。换句话说,赛车不能立即转180º。

这个原理如何使用在每100毫秒发送更新的服务器上呢?客户端接收每个竞争车辆的准确的的速度和航向,对于接下来的100毫秒,它将不会收到任何新信息,但它仍然需要显示它们正在运行。最简单的方法是假设汽车的航向和加速度在100毫秒内保持不变,并使用该参数在本地运行汽车物理。然后,100毫秒后,当服务器更新到达时,汽车的位置得到纠正。

根据许多因素,校正可能很大或相对较小。如果玩家确实将汽车保持在直线上并且不改变汽车速度,则预测位置将与校正位置完全相同。另一方面,如果玩家遇到某些事情,预测的位置将是非常错误的。

请注意,航位推算可以应用于低速情况 - 例如战列舰。事实上,**“航位推测”**一词起源于海上航行。

实体插值


      在某些情况下,根本无法应用航位推测 - 特别是在所有情况下,玩家的方向和速度可以立即改变。例如,在3D射击游戏中,玩家通常以非常高的速度跑动,停止和转弯,这使得航位推测基本上无用,因为以前的数据无法再预测位置和速度。

      当服务器发送权威数据时,您不能只更新玩家位置; 你会得到每100毫秒内短距离移动的玩家,这使得比赛无法进行。

      你所拥有的是每100毫秒的权威位置数据,诀窍是如何向玩家展示中间发生的事情。解决方案的关键是向用户的玩家展示过去的其他玩家。

      假设您在 t = 1000时收到位置数据。您已经在 t = 900时收到了数据,因此您知道玩家在 t = 900t = 1000时的位置。因此,从t = 1000t = 1100,您可以显示其他玩家从t = 900t = 1000所做的事情。通过这种方式,您始终会显示用户的实际移动数据,除非您“延迟”显示100毫秒。
客户端2呈现“过去的”客户端1,插入最后已知位置
      用于从t = 900t = 1000进行插值的位置数据取决于游戏。插值通常效果很好。如果没有,您可以让服务器在每次更新时发送更详细的移动数据 - 例如,播放器后面的一系列直线段,或每10 ms采样的位置,插值时看起来更好(您不需要发送10倍以上的数据 - 由于您正在为小动作发送增量,因此可以针对此特定情况对线路上的格式进行大量优化。

      请注意,使用这种技术,每个玩家都会看到游戏世界的略有不同的渲染,因为每个玩家在现在看到自己但看到过去的其他实体。然而,即使对于快节奏的游戏,看到具有100毫秒的其他实体通常也不明显。

      有一些例外 - 当你需要很多空间和时间精度时,例如当玩家向其他玩家射击时。由于过去看过其他玩家,你的目标是延迟100毫秒 - 也就是说,你的射击目标是100毫秒前!我们将在下一篇文章中讨论这个问题。

总结


      在具有权威服务器的客户端 - 服务器环境中,不经常更新和网络延迟,您仍然必须给予玩家连续性和平稳移动的假象。在 本系列的第2部分中, 我们探索了一种使用客户端预测和服务器协调来实时显示用户控制的玩家的移动的方法; 这可确保用户输入对本地播放器产生直接影响,消除导致游戏无法进行的延迟。

      但是,其他实体仍然是个问题。在本文中,我们探讨了两种处理它们的方法。

      第一个,航位推算,适用于某些类型的模拟,其中实体位置可以从先前的实体数据(例如位置,速度和加速度)可接受地估计。当不满足这些条件时,此方法失败。

      第二个实体插值根本不预测未来位置 - 它仅使用服务器提供的真实实体数据,从而显示其他实体在时间上稍微延迟。

      实际效果是用户的玩家在当前看到,其他实体在过去看到。这通常会带来难以置信的无缝体验。

      但是,如果没有其他任何操作,当事件需要高空间和时间精度时,例如在移动目标上进行射击时,幻觉就会崩溃:客户端2呈现的位置客户端1与服务器或客户端1的位置不匹配所以爆头变得不可能!由于在没有爆头的情况下没有游戏完成,我们将在下一篇文章中处理这个问题。

猜你喜欢

转载自blog.csdn.net/qq_25327609/article/details/88897249
今日推荐