游戏客户端预测和协调服务器
2022-07-12 14:45:01 【

在网络环境中,如互联网,延迟可能在十分之一秒左右,一个游戏在最好的情况下可能没感觉出延迟,但是在在最坏的情况下,是无法玩的。在本文中,我们将找到最小化甚至消除该问题的方法。

客户端预测

即使有一些作弊玩家,大多数时候游戏服务器都在处理有效的请求(来自非作弊客户端和在特定时间不作弊的客户端)。这意味着接收到的大部分输入都是有效的,并将按预期更新游戏状态;也就是说,如果您的角色位于(10,10)并且按下了右箭头键,则它将结束于(11,10)。

我们可以利用这个优势。如果游戏世界具有足够的确定性(即,给定一个游戏状态和一组输入,结果完全可以预测)。

假设我们有100毫秒的延迟,角色从一个正方形移动到下一个正方形的动画需要100毫秒。使用简单的实现,整个操作需要200毫秒:


由于世界是确定性的,所以我们可以假设发送到服务器的输入将成功执行。在这个假设下,客户端可以在处理输入之后预测游戏世界的状态,并且大多数情况下这是正确的。

与发送输入并等待新的游戏状态开始呈现不同,我们可以发送输入并开始展示输入的结果,就好像它们已经成功一样,而我们则等待服务器发送“真实”的游戏状态,这通常会与本地计算的状态相匹配:


现在玩家的行为和屏幕上的结果之间完全没有延迟,而服务器仍然是权威的(如果被黑客攻击的客户端发送无效的输入,它可以在它自己的屏幕上展示任何它想要的内容,但不会影响服务器的状态,也不会影响到其他玩家看到的)。

同步问题

在上面的例子中,我仔细地选择了这些数字,以使所有的工作都正常。但是,考虑一个稍微修改过的场景:假设我们与服务器之间有250毫秒的延迟,从一个方块移动到下一个方块需要100毫秒。假设玩家连续按了2次右键,试图将2个方块移动到右侧。

使用到目前为止的技术,这就是将要发生的事情:


当新游戏状态到来时,我们在t=250毫秒时遇到了一个有趣的问题。客户端的预测状态是x=12,但是服务器说新的游戏状态是x=11。因为服务器是权威的,所以客户机必须将字符移回x=11。但是,一个新的服务器状态到达t=350,表示x=12,所以字符再次跳,这次向前。

从玩家的角度来看,他按了两次右箭头键;角色向右移动了两个方块,站在那里50毫秒,向左跳了一个方块,站在那里100毫秒,向右跳了一个方块。当然,这是不可接受的。

协调服务器

解决这个问题的关键是要认识到客户端在当前时间看到了游戏世界,但是由于延迟,从服务器获取的更新实际上是过去的游戏状态。到服务器发送更新的游戏状态时,它还没有处理客户端发送的所有命令。

不过,这并不难解决。首先,客户端向每个请求添加一个序列号;在我们的示例中,第一个按键是请求1,第二个按键是请求2。然后,当服务器回复时,它包括它处理的最后一个输入的序列号:


现在,在t=250时,服务器会说“根据我对您请求的了解,您的位置是x=11”。因为服务器是权威的,所以它将字符位置设置为x=11。现在让我们假设客户端保留它发送到服务器的请求的操作。根据新的游戏状态,它知道服务器已经处理了请求1,因此它可以丢弃该操作。但是它也知道服务器仍然需要发送处理请求2的结果。因此,再次应用客户端预测,客户端可以根据服务器发送的最后一个授权状态,加上服务器尚未处理的输入,计算出游戏的“当前”状态。

因此,当t=250的时候,客户机得到“x=11,最后处理的请求1”。它丢弃发送的输入的操作#1–但它保留了#2的操作,服务器尚未确认该操作。它用服务器发送的x=11更新它的内部游戏状态,然后应用服务器仍然看不到的所有输入——在现在这种情况下,就是输入2,“向右移动”。客户端最终结果是x=12,这是正确的。

继续我们的示例,在t=350时,服务器将进入一个新的游戏状态;这次它将显示“x=12,上次处理的请求#2”。此时,客户端将丢弃所有输入到#2,并用x=12更新状态。现在没有未处理的输出的请求要去执行,因此处理将以正确的结果结束。

零碎提示

上面讨论的例子只提到了运动,但同样的原理几乎可以应用于其他任何事情。例如,在基于回合的战斗游戏中,当玩家攻击另一个角色时,您可以显示血液和表示所造成伤害的数字,但在服务器这样说之前,您不应该更新角色的健康状况。

由于游戏状态的复杂性,这并不总是容易逆转的,你可能想避免杀死一个角色,直到服务器这样说,即使它的血量在客户端的游戏状态下降到零以下(如果另一个角色在收到致命攻击之前使用了急救包,但服务器还没有告诉你怎么办?)

这给我们带来了一个有趣的观点——即使世界是完全确定的,并且没有客户机作弊,客户机预测的状态和服务器发送的状态在协调后仍然可能不匹配。上面这种情况当只有一个玩家的时候是不可能遇到的,但当几个玩家同时连接到服务器很容易遇到。这将是下一篇文章的主题。

总结

当使用权威服务器时,您需要在等待服务器实际处理您的输入时给执行一个响应的假象。为此,客户端模拟输入的结果。当更新的服务器状态到达时,预测的客户端状态将从更新的状态和客户端发送但服务器尚未确认的输入重新计算。


】【打印关闭】 【返回顶部
上一篇没有了 下一篇怎么选择游戏服务器服务商?