作者:韦易笑
链接:https://www.zhihu.com/question/30204598/answer/47173171
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 帧间同步模式: 帧锁定同步算法 (2007):
  • 玩法规避模式:网络游戏同步法则 (2005) 最好给您们策划看这篇,玩法规避
  • 预测插值模式:影子跟随算法 (2007) FPS, 赛车
  • 提高传输速度: 快速可靠传输协议 (2012)基于UDP的快速可靠协议。

正文:

早期 RTS,XBOX360 LIVE游戏常用同步策略是什么?格斗游戏多人联机如何保证流畅性和一致性?如何才能像单机游戏一样编写网游?

算法概念

该算法普遍要求网速RTT要在100ms以内,一般人数不超过8人,在这样的情况下,可以像单机游戏一样编写网络游戏。所有客户端任意时刻逻辑都是统一的,缺点是一个人卡机,所有人等待。

1.客户端定时(比如每五帧)上传控制信息。

2.服务器收到所有控制信息后广播给所有客户。

3.客户端用服务器发来的更新消息中的控制信息进行游戏。

4.如果客户端进行到下一个关键帧(5帧后)时没有收到服务器的更新消息则等待。

5.如果客户端进行到下一个关键帧时已经接收到了服务器的更新消息,则将上面的数据用于游戏,并采集当前鼠标键盘输入发送给服务器,同时继续进行下去。

6.服务端采集到所有数据后再次发送下一个关键帧更新消息。

这个等待关键帧更新数据的过程称为“帧锁定”

应用案例:大部分RTS游戏,街霸II(xbox360),Callus模拟器。

算法流程

客户端逻辑:

  1. 判断当前帧F是否关键帧K1:如果不是跳转(7)。
  2. 如果是关键帧,则察看有没有K1的UPDATE数据,如果没有的话重复2等待。
  3. 采集当前K1的输入作为CTRL数据与K1编号一起发送给服务器
  4. 从UPDATE K1中得到下一个关键帧的号码K2以及到下一个关键帧之间的输入数据I。
  5. 从这个关键帧到下 一个关键帧K2之间的虚拟输入都用I。
  6. 令K1 = K2。
  7. 执行该帧逻辑
  8. 跳转(1)

服务端逻辑:

  1. 收集所有客户端本关键帧K1的CTRL数据(Ctrl-K)等待知道收集完成所有的CTRL-K。
  2. 根据所有CTRL-K,计算下一个关键帧K2的Update,计算再下一个关键帧的编号K3。
  3. 将Update发送给所有客户端
  4. 令K1=K2
  5. 跳转(1)

服务器根据所有客户端的最大RTT,平滑计算下一个关键帧的编号,让延迟根据网络情况自动调整。

算法演示

我根据该算法将街机模拟器修改出了一个可用于多人对战的版本,早期有一个叫做kaillera的东西,可以帮助模拟器实现多人联机,但是并没有作帧锁定,只是简单将键盘消息进行收集广播而已,后来Capcom在PSP和360上都出过街霸的联网版本,但是联网效果不理想。这个算法其实局域网有细就经常使用了,只是近年来公网速度提高,很容易找到RTT<50ms的服务器,因此根据上述算法,在平均RTT=100ms(操作灵敏度1/10秒),情况下,保证自动计算关键帧适应各种网络条件后,就能够像编写单机游戏一样开发网游,而不需状态上作复杂的位置/状态同步。

从上图的演示中可以看到,两个模拟器进程都在运行1941这个游戏,两边客户端使用了该算法,将逻辑统一在一个整体中。

最后这张图是运行KOF99的效果图,两边完美同步,上图是我开发的街机对战效果,在公网环境下,只要不是小型宽带用户,一般电信或者联通用户都能有一个比较好的体验。

乐观帧锁定

针对传统帧锁定算法网速慢会卡到网速快的问题,实践中线上动作游戏通常用“定时不等待”的方式再每次Interval时钟发生时固定将操作广播给所有用户,不依赖具体每个玩家是否有操作更新:

  1. 单个用户当前键盘上下左右攻击跳跃是否按下用一个32位整数描述,服务端描述一局游戏中最多8玩家的键盘操作为:int player_keyboards[8];
  2. 服务端每秒钟50次向所有客户端发送更新消息(包含所有客户端的操作和递增的帧号): update=(FrameID,player_keyboards)
  3. 客户端就像播放游戏录像一样不停的播放这些包含每帧所有玩家操作的update消息。
  4. 客户端如果没有update数据了,就必须等待,直到有数据到来。
  5. 客户端如果一下子收到很多连续的update,则快进播放。
  6. 客户端只有按键按下或者放开,就会发送消息给服务端(而不是到每帧开始才采集键盘),消息只包含一个整数。服务端收到以后,改写player_keyboards

-------------

虽然网速慢的玩家网络一卡,可能就被网速快的玩家给秒了(其他游戏也差不多)。但是网速慢的玩家不会卡到快的玩家,只会感觉自己操作延迟而已。另一个侧面来说,土豪的网宿一般比较快,我们要照顾。

指令缓存

针对高级别的抽象指令(非前后可以覆盖的键盘操作),比如即时战略游戏中,各种高级操作指令,在“乐观帧锁定”中,客户端任何操作都是可靠消息发送到服务端,服务端缓存在对应玩家的指令队列里面,然后定时向所有人广播所有队列里面的历史操作,广播完成后清空队列,等待新的指令上传。客户端收到后按顺序执行这些指令,为了保证公平性,客户端可以先执轮询行每个用户的第一条指令,执行完以后弹出队列,再进入下一轮,直到没有任何指令。这样在即时战略游戏中,选择 250ms一个同步帧,每秒四次,已经足够了。如果做的好还可以象 AOE一样根据网速调整,比如网速快的时候,进化为每秒10帧,网速慢时退化成每秒4帧,2帧之类的。

————–

随机数需要服务端提前将种子发给各个客户端,各个客户端算逻辑时用该种子生成随机数,另外该例子以键盘操作为例,实际可以以更高级的操作为例,比如“正走向A点”,“正在攻击”等。帧锁定系列方法目前也成功的被应用到了若干线上实时动作游戏中。

PS:可以把整段战斗过程的操作和随机数种子记录下来,不但可以当录像播放,还可以交给另外一台服务端延迟验算,还可以交给其他空闲的客户端验算,将验算结果的 hash值进行比较,如果相同则认可,如果不通则记录或者处理,服务端如果根据游戏当前进程加入一些临时事件(比如天上掉下一个宝箱),可以在广播的时候附带。

----------------

关于帧锁定系列的方法有很多类似实现(包括后面提到的帧间无等待改进,包括 Lock Step等),但是他们的核心都是一个:保证所有客户端每帧的输入都一样。这样的方式被格斗游戏,RTS和足球(FIFA类)、篮球(NBA)等体育和动作游戏大量使用,比如我们熟悉的各大战网平台游戏(Xbox Live等),还有很多基于模拟器的街机对战平台。以及不少大型多人横版动作游戏。以开发便利,同步逻辑直观而受到大家欢迎。

帧锁定算法多用在 C/S模型中(或者一人做主多人做从的P2P里),它和 LockStep(多用于P2P)共同存在的问题就是 “网速慢的玩家会卡到网速快的玩家”,老式游戏经常一个角色断网,所有人就在那里等待。为此出现了帧锁定的改良版本 “乐观帧锁定”(具体描述见帧锁定文章的下半部分)经过了不少游戏的实践检验。先前还有几款上线的横版格斗页游用 Flash 的 TCP without NODELAY 来跑该算法(由于近两年国内网速提高,Flash的 Tcp without NODELAY也能做很多事情了),效果还不错。

具体实施时用不着按照文所述每一个步奏都相同,可以有很多变通。比如不一定是有变化的时候才通知服务端,有线上某横版格斗页游就是也可以每秒 20次向服务端直接发送数据(flash时钟不准需要自己独立计时),服务端再每秒 40次更新回所有客户端,看具体情况而定。

也有使用 UDP的端游,客户端每秒钟上传50次键盘信息到服务端,丢了就丢了,后面持续发送过来的键盘数据会覆盖前面的数据,所以丢了没关系,更快捷。当然,UDP也不是必须的,近两年网速提高很快,省内都能做到10ms的 RTT 了,跨省也就 50ms的rtt,不少页游上用该方法上裸的 TCP 照样跑的很顺畅。

而近两年动作游戏领域也涌现出一些新的改良方法,比如 Time Warp,以客户端先行+逻辑不一致时回滚的方式,带来了更好的同步效果,俗称时间回退法。不果国内暂时没看到有游戏这么尝试,更多的是国外近两年的双人动作游戏比较多,要求游戏每帧状态都可以保存,逻辑上开发会复杂一些。国内大部分是超过两人出去副本的,在3-4人出去 PK的情况下,引入状态回退,会让整个效果大打折扣。不果2人的效果确实有所改进,有兴趣的同学可以搜索 Time Warp相关的论文。

----------------

2009年,云游戏(游戏远程渲染)技术得到广泛应用,客户端上传操作,服务端远程渲染,并以低延迟视频编码流的方式传回给客户端,用的就是这样类似的技术。客户端不需要高额的硬件,也不存在盗版问题,其中 Gaikai和 OnLive两家公司做的比较好。

2012年,Sony推出 Playstation Now技术,可以在 PSV和 PS3/PS4上玩云游戏,玩家不需要购买游戏就可以免费体验一定时间。使得 PSV/PS3等低端硬件也可以流畅的跑 PS4游戏。

更多阅读:《

再谈网络游戏同步

----

手机格斗网游该如何避免延迟相关推荐

  1. 手机格斗网游该如何避免延迟?

    早期 RTS,XBOX360 LIVE游戏常用同步策略是什么?格斗游戏多人联机如何保证流畅性和一致性?如何才能像单机游戏一样编写网游? 算法概念 该算法普遍要求网速RTT要在100ms以内,一般人数不 ...

  2. 开发一款手机格斗网游需要注意些什么

    本文转自 http://www.sfw.cn/xinwen/431742.html 先针对问题本身解释一下.目前纯正的格斗手机网游还不存在,我也没做过,更不知道该怎么做.在PC上格斗网游也只有流星蝴蝶 ...

  3. 网游中针对网络延迟的优化

    在网络游戏中,由于延迟或者网络状况的抖动,可能会将客户端效果产生一定的扭曲和卡顿.影响玩家体验以及进一步的操作.要降低因为延迟带来的体验问题,有两种策略,一种为客户端预测,一种为延迟补偿. 1.客户端 ...

  4. 艾尔之光服务器维修,艾尔之光-ELSWORD-官方网站-二次元动漫格斗网游

    <艾尔之光>开启师徒系统,同一服务器中,只要满足条件的玩家,即可1:1结成师徒关系,共同开始愉快的二次元冒险之旅噢! 师徒关系条件 师傅:角色等级99级以上,完成二转,完成艾里奥斯师傅的资 ...

  5. 网游同步技术:实时动作游戏同步方式和传输协议选择

    http://www.gameres.com/478430.html 6 天前 上传 下载附件 (88.33 KB) GameRes游资网授权发布 文 /  韦易笑 实时动作游戏在近年来得到迅猛的发展 ...

  6. 从回合霸王到网游巨头 网易游戏十年史

    网易办公环境 网易互动娱乐有限公司隶属于网易公司,前身为网易在线游戏事业部,2002年正式挂牌成为独立公司.2004年,网易推出自主研发的2D回合制网游<梦幻西游>,时至今日,游戏依然保持 ...

  7. 页游arpg服务端java_ARPG手机网游java服务端主程初哥遇到的一些坑总结

    游戏类型:ARPG横板格斗过关手机网游,类似王者之剑,DNF. 客户端unity,碰撞判定在客户端,AI和伤害运算在服务端.峰值单服在线2800. netty,protobuf,mysql. 指令设计 ...

  8. 情怀java手机网游_经典端游移植手游 “情怀”赋予老IP全新活力

    原标题:经典端游移植手游 "情怀"赋予老IP全新活力 腾讯旗下<天涯明月刀>手游在近日开始了封测,这款经典的国产网游也正式加入了手游的大家庭中,事实上很多知名的网络游戏 ...

  9. 自己架设手机网游_起来,不愿做网游的奴隶!

    起来~~不愿做网游的奴隶 ! 复学一月有余, 老师是否在为孩子的"迷离"状态而焦虑? 戒不掉的手机,离不开的网游: 上课精神不济,作息日夜颠倒: 学习低效,心浮气躁: -- 一.5 ...

最新文章

  1. 第 4 章 Hypertable
  2. python笔记基础-python学习笔记(一)python简介和基础
  3. ABAP 如何实现屏幕字段不可输入
  4. Adobe产品安装错误问题:Exit Code: 7
  5. 【数字逻辑设计】基本逻辑门
  6. python html转word文档_Python实现将HTML转换成doc格式文件的方法示例
  7. Hadoop 系列之 Hive
  8. HTML行内元素、块状元素和行内块状元素的区分
  9. 大数据可视化类型有哪些
  10. 实例6 函数的返回值
  11. HDU2837 Calculation(指数循环节)题解
  12. 【vulhub】conference
  13. 一篇了解TrustZone
  14. 联想成为梦工厂动画的首选工作站创新合作伙伴
  15. Android-环境搭建
  16. mysql支付成功订单数超过10_1.超时未支付订单处理
  17. 大数据就业前景如何?马云曾经说过大数据是未来顶峰时代应验了
  18. 我在校园自动打卡autojs脚本
  19. 计算机的存储规则【小白进】
  20. java界面化_JAVA 界面美化

热门文章

  1. php rewrite重写,yaf 自定义重写路由rewrite
  2. 如何编写一个抢购bot_如何编写一个SkyWalking插件
  3. 输出华氏-摄氏温度转换表(15分)
  4. vue 使用this.reload方法刷新页面配置
  5. 老生常谈之CSS的垂直居中
  6. 三维视觉基础之世界坐标系、相机坐标系、图像坐标系和像素坐标系之间的转换关系
  7. c语言教程文库,C语言经典教程
  8. mysql配置文件my.cnf_MariaDB/MySQL配置文件my.cnf详解
  9. 门店定位怎么在地图上显示_怎么在百度地图上面显示自己店面的地址,
  10. ROS 5.12 上自动更新3322.org动态域名