zoukankan      html  css  js  c++  java
  • 多人在线游戏,客户端服务器间同步低延迟方案(译)

    原文:https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking

    输入预测

    假设玩家的网络延迟为150毫秒,并开始向前移动。按键命令发送到服务器。用户命令被处理,并且玩家的角色在游戏世界中向前移动。这个状态更改将通过下一次快照更新传输到所有客户端。所以玩家在开始走路之后,会在150毫秒的延迟时间后看到自己的动作变化。这种延迟存在于所有玩家的行动,如运动,射击武器等,并且随着更高的延迟而变得更糟。玩家输入和相应的视觉反馈之间的延迟会产生奇怪的,不自然的感觉,并且使得难以精确地移动或瞄准。

    客户端输入预测(cl_predict 1)是一种消除这种延迟的方法,让玩家的动作感觉更加即时。而不是等待服务器更新自己的位置,本地客户端只是预测自己的用户命令的结果。因此,客户端运行与服务器完全相同的代码和规则,便于服务器验证用户命令。预测完成后,本地玩家将立即移动到新位置,而服务器仍然在旧位置看到他。

    150毫秒后,客户端将根据他之前预测的用户命令接收包含更改的服务器快照。然后,客户端将服务器位置与他的预测位置进行比较。如果它们不同,则发生预测错误。这表示客户端在处理用户命令时没有获得其他实体和环境的正确信息。然后,客户端必须纠正自己的位置,因为服务器具有决定客户端预测是否准确的最终权限。如果cl_showerror 1打开,客户可以看到预测错误发生。预测误差校正可能非常显著,可能导致客户端的视图不规律地跳动。通过在短时间内逐渐纠正这个错误(cl_smoothtime),可以顺利地纠正错误。cl_smooth 0

    只有当他们受到影响的本地玩家和实体才能进行预测,因为可以通过使用客户的按键来做出玩家最终的“最好的猜测”。无法预测其他的玩家。

    滞后补偿

    源代码SDK中提供了用于滞后补偿和视图插值的所有源代码。查看实施细节的滞后补偿

    假设玩家在客户端10.5射击目标。发射信息被打包成用户命令并发送到服务器。当数据包正在通过网络时,服务器继续模拟世界,目标可能已经移动到不同的位置。用户命令到达服务器时间10.6,并且服务器将会检测到未命中,即使玩家完全瞄准目标。该错误需要服务器端滞后补偿进行纠正。

    滞后补偿制度保存了所有近期一秒钟内玩家的历史位置。如果执行了用户命令,则服务器估计创建命令的时间如下:

    命令执行时间 = 当前服务器时间 - 数据包延迟 - 客户端视图插值

    然后,服务器将所有相关玩家 - 移动到他们在命令执行时间的地方。执行用户命令并正确检测命中。用户命令处理完毕后,玩家将恢复到最新的位置。

    注意:由于实体内插值含在方程式中,因此不启用该选项可能会导致不正常的结果。
    举个例子:

    该屏幕截图是net_fakelag在服务器确认命中之后,在具有200毫秒延迟(使用的监听服务器上拍摄的。红色的hitbox在客户端显示100ms + interp之前的目标位置。此后,当用户命令发往服务器时,目标继续向左移动。用户命令到达后,服务器根据估计的命令执行时间恢复目标位置(蓝色命中框)。服务器确认命中(客户端看到血液效应)。

    思考:

    由于时间测量中的精确度误差小,客户端和服务器的命中框不完全匹配。即使是几毫秒的小差也可能导致快速移动物体几英寸的误差。多人攻击检测不是像素完美的,并且基于运动对象的滴答率和速度已知精度限制。

    问题出在了,为什么命中检测在服务器上这么复杂?在点击检测时,对玩家位置执行后跟踪和精度处理错误,可以通过客户端方式更轻松,并更精确。客户端只是告诉服务器一个“命中”消息什么玩家被击中和哪里。但是我们不能容忍,因为游戏服务器不能信任客户端这样重要的决定。即使客户端“干净”并受到Valve Anti-Cheat的保护,也可以在第三台机器上修改数据包,同时路由到游戏服务器。这些“欺骗代理”可能会在VAC(“中间人”攻击)中察觉到“打”消息到网络包中。

    网络延迟和滞后补偿可能产生与现实世界似乎不合逻辑的矛盾。例如,你可以被一个甚至不能再看到的攻击者击中,因为你已经被盖了。发生了什么事情是,服务器将您的播放器命中的时间推迟回来,您仍然暴露在您的攻击者身上。由于数据包速度相对较慢,这种不一致性问题一般无法解决。在现实世界中,你不会注意到这个问题,因为光(包)行进得如此之快,你和你周围的人都看到与现在相同的世界。

    附:一种计算客户端服务器间网络延迟的方法

    客户端想服务器发送一个请求,同时客户端记录下当前时间:sendTime
    这个请求服务器收到以后不做任何处理,直接返回给客户端。客户端收到以后再次记录当前时间:receiveTime
    网络延时就是: (receiveTimer - sendTime)/ 2 

    服务器方的计算方法同理。

    服务器端的工作简介:针对客户端的命令,验证当前位置是否合法,目标位置是否可达并修正(碰撞检测),玩家操作延时补偿,

  • 相关阅读:
    Easy | LeetCode 108. 将有序数组转换为二叉搜索树
    Medium | LeetCode 105 | 剑指 Offer 07. 从前序与中序遍历序列构造二叉树
    Easy | LeetCode 543. 二叉树的直径
    Easy | LeetCode 235 | 剑指 Offer 68
    Easy | LeetCode 236 | 剑指 Offer 68
    Medium | LeetCode 114. 二叉树展开为链表 | 先序遍历 | 递归 | 迭代
    Medium | LeetCode 538,1038. 把二叉搜索树转换为累加树
    Medium | LeetCode 230. 二叉搜索树中第K小的元素
    Easy | 剑指 Offer 54. 二叉搜索树的第k大节点
    stl(5)vector容器
  • 原文地址:https://www.cnblogs.com/zendu/p/6655456.html
Copyright © 2011-2022 走看看