3

这里有几个问题。

想象一下,我有客户端 A 将向服务器发送以下消息:“开始移动”。

服务器不会立即收到此消息,因为延迟会导致延迟。

问题 1:ping(或更好:往返时间​​)是客户端向服务器发送消息并收到响应所需的时间。如果您可以忽略服务器注意到它已收到消息并开始发送响应所需的时间(这应该很短),这是否意味着以下情况?

  1. 客户端向服务器发送某些信息所需的时间 = 往返时间 / 2
  2. 服务器向客户端发送内容所需的时间 = 往返时间 / 2

因此,当客户端 A 发送该消息时,服务器应该会在客户端发送消息后的往返时间/2 毫秒内收到该消息。这引出了下一个问题。

问题 2:客户端是否应该先发送包,然后等待往返时间/2 毫秒,然后才能在客户端实际执行该命令(在这种情况下:向前移动)以补偿延迟/滞后?

现在,服务器将向附近的所有玩家发送以下消息:“客户端 A 正在向前移动”。然后,这些客户将确保客户 a 的角色开始移动,这将引导我进入下一个问题。

问题3:接收其他客户端移动的消息的客户端是否应该考虑到该消息是由服务器往返时间/ 2毫秒前发送的?因此,用于移动计算时间戳的当前时间应该减少往返时间/2?

在我看来,所有这些方法都会确保客户端之间的同步得到改善,因为考虑到了延迟。这是正确的做事方式吗?大多数其他优秀的多人游戏都这样做吗?您想给出任何评论、建议、替代方案或随机但相关的呼喊?提前致谢。

4

4 回答 4

10

我认为在大多数 mmo 中,除非出现严重滞后,否则您的客户端主要在不与服务器交互的情况下移动。服务器在客户端发送给服务器的消息的帮助下再现运动。因此,例如,如果服务器滞后,客户端将停止接收来自服务器的反馈并恢复到服务器确定您所在的位置。这就是为什么你在糟糕的延迟期间跳回几帧的原因。这样,服务器也可以控制您的速度,这样您就不会进行快速黑客攻击。如果您的客户端以超过服务器确定的速度的特定速率移动,您只需跳回额外的帧。

其他客户端根本不会让您在一定时间内没有服务器的响应而移动。这是您将经历“冻结滞后”的时间。

当然也有服务端简单地拿客户端发来的位置,盲目信任的情况。这些是通常容易受到传送黑客攻击的游戏。

其他玩家的位置确实有延迟,如果你拿两台电脑,连接到哇之类的游戏,同时移动两个角色就可以看到。您会看到,在您真正开始移动他之后,非本地角色将在两台计算机上开始移动。

客户通常有某种滞后补偿。因此,如果另一个玩家在某个方向移动然后停止,您的客户端仍会模拟该玩家的移动,直到您从服务器收到他改变方向或停止移动的消息。这就是为什么其他玩家可以在 ping 高时来回跳跃。这也是为什么当你击中延迟尖峰时玩家似乎只是滑行/逃跑/走开,然后当你的客户从服务器收到位置时返回他们的真实位置。

当然,这会因引擎而异,但这是一种相当通用的方法。

编辑:忘了补充一点,服务器也使用延迟补偿是很常见的。如果您在您的范围内的 mmo 中击中某人,则该人可能不在服务器视图的范围内。因此,如果您真的在彼此的范围内,服务器会为您的两个客户端承担延迟并尝试匹配。

于 2009-09-19T19:30:06.370 回答
4

这是一个老问题,但我最近编写了类似的代码,所以也许这会对某人有所帮助。

是的,延迟在计算中总是有用的。但它比 RTT 稍微复杂一些。往返时间总是在变化......您的网络代码可以保持平均值,但与该平均值的差异很大。

本地客户端、远程客户端和服务器都使用算法预测当前位置。以下数据接近典型值:

  • 时间:吨
  • 放置:位置 (x,y,z) 和方向 (x,y,z,w)
  • 运动:直线运动矢量以长度为速度(x,y,z),旋转运动矢量以长度为轴(x,y,z)

您需要从 [T,P,M] 集合推断为 simtime 的算法。我不会在这里提供这些。

当客户端在 [T,P,M] 处注册船舶驱动器的更改时,直到 T+deltaT 才会到达服务器。但如果 deltaT 在典型网络延迟的容差范围内,服务器可以说“是的,它发生在 T,我接受”。否则它可能想要纠正客户端说“不,这超出了容忍度,它发生在我的时间 T'”在这种情况下,客户端将不得不重播所有随后驱动的 [T,P,M] 从服务器更正的更改(这意味着您需要保留一个队列或它们的列表)。

下一个客户将在 T+deltaT+differentdeltaT 获得它。它不可能改变它已经模拟的东西,所以如果它没有延迟它的模拟,它会跳过远程船,你会看到一个混蛋帧。这就是为什么远程驱动的船舶应该将其模拟延迟始终大于 2*typicaldeltaT 的时间。它应该是一个持续的延迟,或者是一个逐渐变化的延迟,在严重滞后的时候,你仍然会看到 jerk 帧

你可以用额外的平滑代码来平滑所有的混蛋,但在你的代码完美无瑕之前不要这样做,因为它只会让人无法看到问题出在哪里。

您必须有一个良好的同步时间参考。那里的许多代码做得相当草率(例如,RakNet 没有(或没有)做得很好)。这里有一个很好的提示:短期内你可以假设每个人的时钟都在以相同的速率运行,你只需要弄清楚偏移量是多少,所以保持一个最大和最小偏移量的窗口,并在你学习时关闭它;从长远来看,您需要补偿时钟运行速度快或慢的客户,因此如果您确定必须打开窗口,请允许它打开。您必须使用单调递增的本地时间源,并且不会影响处理器速度(现在是可变的)。

不,不要在本地“化身”移动时延迟本地模拟。这似乎太没有反应了。您可以稍微延迟它(最多可能 50 毫秒)以帮助改善同步,但是一直延迟到 RTT 会使您的游戏看起来令人沮丧地没有响应。设置本地延迟选项并使用它,因为可以接受小的一致延迟并改善同步。但这不是必需的,并且会导致很多问题,因此我建议最后执行该代码。(如果您正在尝试制作 FPS 近战游戏,则需要执行此操作以及您可以获得的所有其他帮助)。

至于作弊预防与模拟平滑度:首先,当官方位置发生变化时,客户不应仅从最后已知位置推断。它应该注册一个调整向量并缓慢地从旧路径移动到新路径以获得平滑度(但就像我上面所说的那样,最后执行此代码,否则它将掩盖其他错误)。其次,服务器应该容忍大范围的延迟......即使在同一以太网上的机器上,数据包延迟通常运行 5ms 到 100ms 左右......这是一个相当大的范围。当然,你需要打断它并说“如果你说你在 T 时间搬家,但我在 T + some_large_number 收到了数据包,那么我认为你是在试图调整过去并对我撒谎。” some_large_number 不应该比平均 RTT 大很多,以保持人们诚实。

模拟永远不会紧密同步。它们应该在 Internet 上保持在 400 毫秒左右,但在延迟时间肯定会超出这个范围……到 30 秒或更长时间,你需要容忍这种情况,因为它们并不罕见。鉴于 Internet 受到铜缆中光速的限制,您始终可以预期,对于您的远方客户端,单向延迟通常在至少 100 毫秒的范围内,通常为 500 毫秒或更长。

所以我强烈建议你不要尝试在互联网上制作近战FPS游戏(一些大公司尝试但总是会遇到麻烦)。如果您使用射弹(通过在一个模拟中快速运行它们而在另一个模拟中慢速运行),您可以做一些技巧,这样即使时间关闭,它也会继续显示。此外,FPS游戏使用的规则是命中检测是基于攻击者的模拟......当攻击者知道他已经死在目标上并没有击中时,感觉更错误,然后当防守者知道他不在路上并被击中时感觉更错误无论如何。你必须选择一个或另一个,从心理上来说就是这样。近战需要一定程度的同步,坦率地说这是不可能的,大多数游戏公司不会接触 MMORPG FPS 近战,而是使用自动瞄准(尝试玩 Mortal Online,

祝你好运。

于 2010-10-18T07:03:15.983 回答
1

对于 Q1:这对我来说是正确的。

Q2:我过去这样做的方式是:如果你想让事情感觉反应灵敏,就立即在客户端的模拟上开始执行动作,然后服务器在玩家发起动作时在游戏时间向前模拟。即客户端知道它在游戏模拟时间的几毫秒开始,所以服务器也可以在那个时间启动它(注意:这总是从服务器的当前时间倒退,所以你必须及时保存状态去做这个)。

Q3:客户端只需要知道他们在时间 X 进行模拟,服务器说事件集 {A,B,C} 发生在时间 {X,Y,Z}。然后客户端和服务器可以使用相同的信息模拟转发,并且通常保持同步(同时发生冲突时除外)。在这些情况下,您需要让服务器重新同步事物,因此您通常会在非常小的误差范围内结束,并且体验非常流畅。

如果您的目标是改善对延迟的感知,您也可以尝试信任客户端。

于 2009-09-28T20:45:57.553 回答
0

有几种网络模型可以解决这些问题;

在网络游戏中,你需要同步两件事,一是时间,二是空间。

  1. 一种称为锁步的网络游戏模型;

你应该看看帝国2游戏工作室时代写的文章,其中描述了锁步模型的细节。

在这个模型中,Client和Server逐帧运行游戏逻辑,例如RTS以100ms为一帧,Server和Client会同步frame Id,也就是同步时间。

客户端在第 50 帧,发送命令 MoveForward,但不立即运行,客户端将告诉服务器在第 51 帧运行移动命令;然后当第 51 帧到来时,服务器和客户端将同时运行命令。所以客户端和服务器逻辑将是相同的。

在这样的模型中,在第 50 帧,客户端和服务器可能会运行在第 49 帧发出的命令,因此客户端输入反馈总是有 100 毫秒或更长时间的延迟。

客户端和服务器之间的延迟不仅包含网络RTT,还包含逻辑帧延迟,即100ms;

在此模型中,要同步空间,您需要使您的客户端代码和服务器代码具有确定性,因此它们只能同步命令和 frameId,不需要同步实体状态。

在这个模型中,输入反馈很大,所以你需要播放动画或声音来帮助玩家忽略延迟。

  1. 其他模型使用状态同步

在这个模型中,我们还需要同步时间,所以客户端会猜测服务器中的当前时间。

当玩家输入时,客户端立即移动,然后以客户端估计的当前服务器时间戳向服务器发送移动命令或客户端目标位置。

当服务器接收到客户端命令时,它知道客户端何时在服务器时间发出命令,它将尝试通过外推运行该命令。

所有其他客户端将收到该命令,其服务器时间,所有其他客户端将尝试推断该命令。

这些技术包括客户端预测、服务器延迟补偿、服务器实体插值。

在这个模型中,客户端的输入反馈很短,但是对于一些冲动的命令,比如使用技能,我们仍然需要使用锁步法,用动画、声音和粒子效果来弥补输入反馈时间。

在网络游戏中,至少有两种命令,第一种是运动,命令会运行一定的时间,像源源不断的流,具有连续性的属性。

另一种喜欢冷时使用技能,指挥效果会带冲动,要区别对待。

于 2017-11-17T23:12:41.070 回答