原文链接: Fast-Paced Multiplayer (Part II): Client-Side Prediction and Server Reconciliation

介绍

在第一篇文章中,我们介绍了一种权威服务器的C-S模型,在这种模型中,客户端只将输入发送到服务器中,当收到来自服务器的游戏状态更新的时候再将结果渲染出来。

单纯地依赖这种模型会导致玩家输入命令和画面更新之间的延迟感,比如,当玩家按下向右的按钮,然后玩家等了半秒钟才开始移动,因为首先客户端需要把输入传给服务器,然后服务器处理了出入之后计算出新的游戏状态,然后再将新的游戏状态传回给客户端。

网络延迟的效果

在实际的网络环境中,延迟可能会达到零点几秒,这时游戏就有点感觉延迟了,最坏的情况是直接没法玩了。在这篇文章中,我们将找到减小这种延迟感的方法,甚至能够消除这种延迟。

客户端预测

虽然存在着作弊的玩家,但是大部分时候服务器是处理有效访问的(来自非作弊玩家的),这也意味着服务器收到大部分的输入都是有效的,而且游戏状态的更新也是按照预期的,也即是说:如果你的角色在(10,10),然后方向键右被按下了,那么你的角色就会移动到(11,10)。

我们可以利用这一点,如果游戏世界的确定性足够(给定一个游戏状态和一些列的输入,得到的结果是完全可预测的)。

现在假设有100ms的延迟,角色移动一格需要花费100ms,使用之前说的实现方式,那么整个动作完成需要花费200ms:

网络延迟和动画

因为游戏世界是确定的,我们假设传送到服务器的输入都能够成功执行。在这种假设下,客户端能够预测游戏世界在接受输入后的状态,并且绝大部分情况下,结果是正确的。

与之前说的将客户端的输入发送到客户端然后等待服务器的响应再在客户端做出反应,我们可以将两者同时进行,即当在发送输入信息的时候,就当作它们已经正确执行,通常服务器返回的结果和客户端的执行的结果是一致的:

在服务器确认行为的同时执行动画

现在玩家输入和运行结果之间就没有任何延迟存在了,同时服务器还是权威服务器。(如果有作弊的客户端发送无用的消息,他可以把角色放在他想要的任何地方,但这并不会影响到服务器,也就是其他玩家也不会受到他的影响)。

同步的问题

在上面的例子里,我选用了一些比较特例的数字来让所有事情看起都很完美,现在假设另一种情况,假设现在服务器延时250ms,移动一格花费100ms,现在玩家按了两下方向键右,想要往右移动两格。

使用之前我们说的技术,情况如下图所示

客户端预测和服务器返回的状态不匹配

当 t = 250ms的时候,也就是收到服务器第一个包的时候,有趣的事发生了,客户端预测的状态是x=12,但是服务器说新的游戏状态是x=11,因为服务器是权威的,客户端必须把玩家拖回到x=11的位置,然后再t=350的时候,又来了一个新包,说角色应该在x=12,角色又移动了一次 。

从玩家的角度看,它按下了两次按键,角色向右移动了两次,然后过了50ms之后,又向左跳了一格,站了100ms之后,又向右跳了一格,这当然是没法接受的。

服务器调和

解决上面说的问题的办法就是你得意识到,客户端所看到的世界是当前的,但是但是因为延迟,客户端得到的游戏状态都是过去的,当服务器在发送更新的时候,它并没有把客户端发来的所有的命令都处理掉。

这就很麻烦了,首先,客户端在发送请求包的时候,给每个包打上帧序,在上面的例子里,第一个按键请求的编号是#1,第二个按键请求时#2,然后当服务器回复的时候,包的包含着请求的序列号。

客户端预测+服务器调和

当t = 250的时候,服务器说“基于#1的输入请求,你的位置是11”.因为服务器是权威的,所以角色的位置是x=11, 现在假设客户端保存了一份发送到服务器的请求,基于新的游戏状态,它知道服务器已经处理了请求 #1,所以他将这个备份丢弃掉,但是客户端知道服务器还需要将#2请求的回复发过来,所以再一次进行客户端预测,客户端可以基于上次服务器发来的状态和#2输入来计算当前的状态。

所以当t=250ms的时候,客户端得到“经过#1的输入之后,x=11”,它将#1输入的拷贝丢弃掉,但是还有一份并没有得到服务器返回的#2的拷贝,客户端将内部游戏状态更新为服务器所发来的游戏状态,也就是x=11,然后将所有未收到回复但已经发送给服务器的输入用于预测,在上面的例子,输入就是向右移动,最终状态就是x=12,这是正确的。当t=350的时候,一个新的游戏状态从服务器获得;这种情况它说“基于#2输入,x=12”。在这是,客户端将#2请求之前的请求都丢弃,然后将游戏状态更新为x=12,没有需要预测的输入,所以不需要预测,现在得到的结果都是正确的。

一些其他的问题

上面讨论的例子里只讨论了移动,但是这个方法在其他方面也可以使用。比如,在一个回合制的游戏里,当玩家攻击其他玩家的时候,你可以播放飙血的特效和伤害值,但是你不应该在收到服务器回复之前直接更新玩家的血量。

因为游戏状态的复杂性,它并不能保证是绝对可逆的,你也许希望只有再收到服务器确认的时候才将一个玩家杀死,即使这个玩家的血量降到负的了。(但假象一种情况,一个玩家实际上已经死了,但是在没有收到服务器确认之前他使用了药包,这个时候你该怎么处理?)

这又带来了一个有趣的问题,即使世界是绝对的确定的,并且没有玩家在作弊,还是有客户端的预测和服务器不吻合的情况。上面说的情况在单人游戏中不会出现,但是在多人接入同一个服务器的时候就会发生,这个问题会在下面的文章中进行讨论。

总结

当使用权威服务器的时候,你需要给玩家即时的响应,即使是当在等待服务器处理出入。为了达到这样的目的,客户端模拟出输入的结果,当收到服务器的回复时,客户端的游戏状态需要通过服务器的回复和还未处理的输入进行重新计算。

介绍

在第一篇文章中,我们介绍了一种权威服务器的C-S模型,在这种模型中,客户端只将输入发送到服务器中,当收到来自服务器的游戏状态更新的时候再将结果渲染出来。

单纯地依赖这种模型会导致玩家输入命令和画面更新之间的延迟感,比如,当玩家按下向右的按钮,然后玩家等了半秒钟才开始移动,因为首先客户端需要把输入传给服务器,然后服务器处理了出入之后计算出新的游戏状态,然后再将新的游戏状态传回给客户端。

网络延迟的效果

在实际的网络环境中,延迟可能会达到零点几秒,这时游戏就有点感觉延迟了,最坏的情况是直接没法玩了。在这篇文章中,我们将找到减小这种延迟感的方法,甚至能够消除这种延迟。

客户端预测

虽然存在着作弊的玩家,但是大部分时候服务器是处理有效访问的(来自非作弊玩家的),这也意味着服务器收到大部分的输入都是有效的,而且游戏状态的更新也是按照预期的,也即是说:如果你的角色在(10,10),然后方向键右被按下了,那么你的角色就会移动到(11,10)。

我们可以利用这一点,如果游戏世界的确定性足够(给定一个游戏状态和一些列的输入,得到的结果是完全可预测的)。

现在假设有100ms的延迟,角色移动一格需要花费100ms,使用之前说的实现方式,那么整个动作完成需要花费200ms:

网络延迟和动画

因为游戏世界是确定的,我们假设传送到服务器的输入都能够成功执行。在这种假设下,客户端能够预测游戏世界在接受输入后的状态,并且绝大部分情况下,结果是正确的。

与之前说的将客户端的输入发送到客户端然后等待服务器的响应再在客户端做出反应,我们可以将两者同时进行,即当在发送输入信息的时候,就当作它们已经正确执行,通常服务器返回的结果和客户端的执行的结果是一致的:

在服务器确认行为的同时执行动画

现在玩家输入和运行结果之间就没有任何延迟存在了,同时服务器还是权威服务器。(如果有作弊的客户端发送无用的消息,他可以把角色放在他想要的任何地方,但这并不会影响到服务器,也就是其他玩家也不会受到他的影响)。

同步的问题

在上面的例子里,我选用了一些比较特例的数字来让所有事情看起都很完美,但是

快速多人游戏(2) - 客户端预测和服务器校验相关推荐

  1. 快节奏多人在线游戏网络入门系列教程(2):客户端预测与服务器协调

    简介 在上一篇文章中,我们简单介绍了权威服务器的体系.客户端发送交互信息给服务器,服务器周期性的更新游戏状态,然后返回游戏状态给客户端. 这个简单体系会导致用户发送命令时和屏幕渲染响应之间的延迟.产生 ...

  2. 多人网络游戏服务器开发基础学习笔记 II: 帧同步 | 游戏客户端预测原理分析 | FPS 游戏状态同步

    这篇是对书本 网络多人游戏架构与编程 的学习第二篇(第一篇:多人网络游戏服务器开发基础学习笔记 I:基本知识 | 游戏设计模式 | 网游服务器层次结构 | 游戏对象序列化 | 游戏 RPC 框架 | ...

  3. 快速向服务器传文件格式,客户端如何向服务器传文件格式

    客户端如何向服务器传文件格式 内容精选 换一换 语音通话平台通过此接口向客户推送语音通话业务用户呼叫时的状态信息,如呼入.呼出.振铃.应答.挂机等状态的信息.语音通话平台(客户端) → 客户服务器(服 ...

  4. 抓包之服务器校验客户端证书

    挂上vpn,打开charles抓包可以看到没网络,但是可以抓到包,怀疑是服务器校验客户端证书了 这里推荐一下肉老师的文章 https://www.anquanke.com/post/id/197657 ...

  5. 服务器校验客户端证书分析及代码

    当前app安全越来越受到重视,很多app采取了HTTPS的协议,但是一般app都不会对证书进行校验,一些app只是客户端对服务端证书进行了强校验,也就是通常呢,抓包的时候app提示无网络连接或者网络连 ...

  6. 快速多人游戏(4) - 爆头!(AKA延迟补偿)

    原文链接:Fast-Paced Multiplayer (Part IV): Headshot! (AKA Lag Compensation) 介绍 从上一篇文章到现在已经过了很久很久了(整整两年!哦 ...

  7. qt客户端连接服务器不响应,qt判断tcp客户端是否连接服务器

    qt判断tcp客户端是否连接服务器 内容精选 换一换 本章节指导您使用MongoDB客户端,通过弹性云服务器内网方式连接GaussDB(for Mongo)集群实例.操作系统使用场景:弹性云服务器的操 ...

  8. 快速多人游戏(1) - 介绍

    原文地址:Fast-Paced Multiplayer (Part I): Introduction 简介 这是一系列的关于快速多人游戏的技术和算法的文章的第一篇,如果你对于多人游戏背后的技术非常熟悉 ...

  9. python 服务端渲染_客户端渲染和服务器渲染的区别

    我们都知道,网页上的很多内容之所以能那么丰富,是因为大量的css.js去渲染出这个页面.那么他们是如何渲染的呢?那么就要说到我们本文的两种渲染方式了,即客户端渲染和服务端渲染. 正文 本文将分别讲述两 ...

最新文章

  1. 2021-10-28 python爬虫学习
  2. html5 跳转参数不显示_HTML5、CSS3、ES6新特性总结
  3. php中文九九乘法表,PHP输出九九乘法表代码实例
  4. 进销存excel_EXCEL也能连接扫码枪?商品扫码入库,免费进销存自由修改功能
  5. 红外图像高低温校正【待补充】
  6. 【腾讯地图】纯手写微信定位考勤小程序,内附完整源码!
  7. ESP8266获取B站粉丝数
  8. 使用vue3+vite+cesium,在地图上显示图标,并且点击实体弹出消息框
  9. 深兰科技出席“2022世界设计之都大会”,论剑工业设计高峰论坛
  10. 分享15个英文SEO长尾关键词挖掘分析工具
  11. table标签中tr和td的英文单词
  12. iMX RT FlexSPI 时序及驱动程序参数设置解析 (一)
  13. google海底光缆图_Google领头建造横跨太平洋海底光缆PLCN:连接香港,120Tbps
  14. 设计模式相关内容介绍
  15. java从入门到放弃(二)
  16. matlab绘制一组椭圆,在MATLAB中绘制椭圆和椭圆体
  17. 电话号码正则表达式 代码 javascript+html,JS正则表达式判断11位手机号码
  18. 施乐维修服务器,富士施乐故障维修代码
  19. win10(1903)JVM虚拟机启动无法进入桌面解决办法汇总
  20. Vue中的 key 的作用是什么?

热门文章

  1. 蒸汽机器人布里茨天赋_lol机器人S6天赋加点图|2016赛季英雄联盟蒸汽机器人布里茨S6天赋、出装、符文加点最新全攻略_好特教程...
  2. 【AI视野·今日CV 计算机视觉论文速览 第199期】Mon, 17 May 2021
  3. 大咖面对面 | 曹寅:做加密艺术世界的伯乐
  4. java.sql.Types,数据库字段类型,java数据类型的对应关系
  5. 移植 RT-Thread 到MB9BF218S
  6. Pandas去重函数:drop_duplicates()
  7. Systemverilog 打印格式
  8. Java学习之计算圆面积
  9. Excel成绩表中自动将等级转换为分数
  10. 讽刺c语言,鲁迅先生评价《儒林外史》“婉而多讽”,达到我国古典小说讽刺艺术的高峰。请从小贴士中选择一项,结合作品具体内,赏析《儒林外史》的讽刺艺术:...