Skip to content

Latest commit

 

History

History
69 lines (45 loc) · 4.49 KB

实现多人网络对战游戏的技术和算法(第四节).md

File metadata and controls

69 lines (45 loc) · 4.49 KB

实现多人网络对战游戏的技术和算法(第四节)

Lag Compensation

译自 Fast-Paced Multiplayer

介绍

前面三篇文章阐述的客户端-服务器游戏架构可以总结如下:

  • 服务器接收来自所有客户端带有时间戳的输入请求
  • 服务器处理请求并更新游戏世界状态
  • 服务器定期将游戏世界状态广播给所有客户端
  • 客户端向服务器发送操作请求并在本地模拟玩家效果
  • 客户端接收游戏状态和
    • 同步本地预测状态和服务器状态
    • 为其它游戏实体插入历史状态

从玩家的角度看,这会产生两个重要的结果:

  • 玩家看到自己的角色是实时状态
  • 玩家看到的其它游戏实体是历史状态

这种方案通常都能适用,但是在对时空精度要求比较高的场景中则容易出问题,比如:将你的敌人爆头。

延迟补偿

所以当你用的提狙击步枪很完美地瞄准了敌人的头。你开枪 - 这是注定会打中的一枪。

但是你没打中。

这怎么可能?

因为我们已经在前面的客户端-服务器架构中阐述过了,你瞄准的敌人的头的位置是他100ms前所在的位置。

换个说话,就好像你在一个光速很慢很慢的宇宙里玩射击,你当前瞄准的是敌人过去所有的位置,当你开枪的时候,敌人早已经走远了。

幸运的是,针对这个问题有一个相对简单的解决方案,在大多数的时候都能满足大部分的玩家(有一个例外情形在下面会讨论)。

下面阐述它是如何工作的:

  • 当你射击时,客户端将此次射击事件的完整数据发送给服务器,即:你射击时的精确时间戳和你武器的精确瞄准数据。
  • 这是决定性的一步,因为服务器收到的所有输入请求都带有时间戳,它可以重构游戏历史的任一时刻,尤其是,它可以向所有客户端重构时间轴上任一时刻的游戏状态。
  • 这意味着服务器知道你开枪的时候你的武器的瞄准镜里是什么,那是你的敌人的头部的历史所在位置,服务器知道在当时你看到的就是敌人的头部位置
  • 服务器在时间轴上的那个时刻认定为击中事件,并更新所有客户端状态

于是所有人都很开心!

服务器开心因为他是服务器,它一直都很开心。

你开心是因为你瞄准了敌人的头,开枪,得到一次成功的爆头奖励。

那个敌人或许是唯一不是很开心的人,如果他被击中的时候是站立不动的,是他的错,对吧?如果他正在移动,我草,你真是牛逼的狙击手。

但是如果他从一个开阔的位置,跑到了一堵墙后面,当他以为他安全的时候,但是转眼之间却被击倒了?

好吧,这种事情也可能会发生。这个时候就需要你来权衡了,因为你击中的是对方历史的位置,但他在找到掩护后的若干毫秒后仍然被击倒了。

这某种意义上是不公平的,但是对于所有参与的人来说,这已经是最能令人满意的解决方案了,未击中和误击中是更差的结果。

结论

这是我探讨《实现多人网络对战游戏的技术和算法》的尾声,要把这类问题处理好是挺棘手,不过只要对具体发生了什么有一个清晰的概念理解,也就不再显得那么困难了。

虽然这几篇文章面向的读者是游戏开发者,但是也发现了另一个有趣的读者群体:玩家!从一个玩家的角度来看,理解游戏中某些事情为什么会发生也是一件有趣的事情。

更多阅读

尽管这些技术很精妙,但是我也不能为它们做任何保证。这些文章只是我针对我从其它资源(包括一些文章、源代码和一些实验)学习到的一些概念整理出来的一个易于理解的向导性介绍。