快节奏多人在线游戏网络入门系列教程(4):爆头!滞后补偿

简介

距离我上次发表上一篇文章已经过去了很长很长时间(2年。。。),出乎我的意料,我收到了很多邮件来询问我“下一篇文章”。好吧,这就是我的下一篇文章——延时的时间一致性,或者简单的说,爆头:)

回顾

前面3篇文章解释了客户端-服务器架构的内容可概述为:

  • 服务器收到客户端的输入,包含时间戳;
  • 服务器处理输入并且更新游戏状态;
  • 服务器发送游戏状态给所有客户端;
  • 客户端发送输入并在本地进行模拟运算;
  • 客户端收到服务器发回的世界状态并且:
    • 把本地的世界状态同步为权威世界状态;
    • 利用已知的状态对实体进行插值;

玩家视角中的2个重要因素:

  • 玩家看到的自己处于现在时;
  • 玩家看到的其他实体处于过去时;

这种情况通常是没问题的,但是在时空敏感的时间上变得极其糟糕——比如爆头其他玩家的情况!

延迟补偿

现在你用你的狙击枪完美瞄准了你的敌人的头部,你开枪了,这理应是一枪完美的爆头!然而你miss了。
为什么?
因为在本文所描述的网络架构中,你瞄准的是100ms之前的敌人的头部。在你扣下扳机的瞬间,敌人已经跑远了。
辛运的是,我们有一个相对简单的解决方案来解决绝大部分此类问题(除了一个例外,后文会讨论)
解决方法如下:

  • 当你射击的时候,客户端发送射击事件给服务器,同时包含了射击事件准确的时间戳,以及武器准确的瞄准位置。
  • 这是最重要的一步。由于服务器具有所有输入的时间戳,因此可以精确重建游戏世界中任何时间点的状态。特别的,可以重建在任何客户端视角下的任何时间点的状态。
  • 这意味着服务器精确的知道你的武器开火瞬间的世界状态。在服务器的视角,是敌人在“过去”时候的头部的位置,但是同时也是你“现在”瞄准的位置。
  • 服务器在你开火的时间点上处理射击事件,并通知客户端。

于是皆大欢喜了!
服务器开心是因为他是服务器,服务器总是开心的。
你也开心了,因为你瞄准了敌人的头部并射击了,然后成功爆头了!
或许被爆头的敌人是唯一不开心的了。如果他站在原地不动,则被爆头;如果他移动了…那你真是一个优秀的狙击手。
但是,如果你开枪的瞬间之后(几分之一秒),他躲到了墙后面,还觉得他安全了呢?
恩,这是有可能发生的,这就是这种解决方案所付出的代价。因为你射击的是他几分之一秒前的位置,因此他仍然会被爆头。
看上去不太公平。然而对所有人而言,这是最可被接受的解决方案了。这总比你瞄准了开火确被服务器告知miss好得多吧!

结论

这是本系列文章的结尾。这类问题总是很难得到完美结果的。但是只要理解了背后的原理,总能得到合理的解决方案。
虽然本文的读者是游戏开发者,但是另外一类读者——玩家也能获得收益!站在玩家的角度上理解各种游戏现象背后的问题也是非常有趣的。

扩展阅读

下面给出一些文章和参考资料,甚至一些源代码和实验结果。
与本文最接近的文章有:
《 What Every Programmer Needs to Know About Game Networking》
《 Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization》
下面给出一个JS写的DEMO,有兴趣的读者可以去调试各种参数看看结果:
http://www.gabrielgambetta.com/fpm_live.html

================================================
原文链接:
http://www.gabrielgambetta.com/fpm4.html

阅读更多

没有更多推荐了,返回首页