文档章节

【转】帧锁定同步算法

diguo2046
 diguo2046
发布于 2017/05/25 16:47
字数 1870
阅读 47
收藏 1
点赞 0
评论 0

早期 RTS,XBOX360 LIVE游戏常用同步策略是什么?格斗游戏多人联机如何保证流畅性和一致性?如何才能像单机游戏一样编写网游?敬请观看《帧锁定同步算法》

《帧锁定同步算法》转载请注明出处:http://www.skywind.me/blog/archives/131

 

 

算法概念

该算法普遍要求网速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. 服务端每秒钟20-50次向所有客户端发送更新消息(包含所有客户端的操作和递增的帧号):

update=(FrameID,player_keyboards)

3. 客户端就像播放游戏录像一样不停的播放这些包含每帧所有玩家操作的 update消息。

4. 客户端如果没有update数据了,就必须等待,直到有新的数据到来。

5. 客户端如果一下子收到很多连续的update,则快进播放。

6. 客户端只有按键按下或者放开,就会发送消息给服务端(而不是到每帧开始才采集键盘),消息只包含一个整数。服务端收到以后,改写player_keyboards

————-

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

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

 

指令缓存

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

————–

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

 

(完)

本文转载自:http://www.skywind.me/blog/archives/131

共有 人打赏支持
diguo2046
粉丝 1
博文 10
码字总数 463
作品 0
衡阳
程序员
【面试必读(编程基础)】网络游戏同步方式(帧同步和状态同步)

在做网络游戏的时候首先要做的是选择一种同步方式来使用,网上的文章都是说帧同步与状态同步的选择,但是又经常讲的模糊不清,我大概整理了一下,并且有一种我们现在项目用的网络同步方式 状...

chrisfxs ⋅ 2017/06/23 ⋅ 0

java.util.concurrent包(1)——synchronized和lock

一、对synchronized的改进 JDK5后引入了线程并发库java.util.concurrent。JSR 166小组花了这么多时间来开发java.util.concurrent.lock框架呢?答案很简单——synchronized同步是不错,但它并...

woshixuye111 ⋅ 2014/06/02 ⋅ 0

【计算机视觉】结构光——格雷码模式捕获教程2(经典论文)

基于结构光投影的运动物体高速实时三维测量方法研究 _刘永久 1 系统概述 采用了一种基于高速视觉的投影和同步图像获取方法,将格雷码结构光编码方法应用于运动物体三维测量中,利用缩短帧间投...

kyjl888 ⋅ 2017/07/03 ⋅ 0

目标检测(Object Detection)和目标跟踪(Object Tracking)的区别

在计算机视觉中,目标检测是在图像和视频(一系列的图像)中扫描和搜寻目标,概括来说就是在一个场景中对目标进行定位和识别,如下图中展示的,我们要检测图像中的车辆,这就是典型的目标检测...

忆臻 ⋅ 01/11 ⋅ 0

帧同步~平滑处理

平滑分类 轨迹相同平滑 轨迹近似平滑 轨迹相同平滑 这类平滑方法同步对象和被同步对象在同一个帧时刻位置状态完全相同(进度会有先后)。 比如 「帧缓冲」 人为让已接收到的帧推迟处理,积累...

IvwsIgeMq ⋅ 2016/05/18 ⋅ 0

COBSforToN一种用于串行通讯的高效编码算法

一般用串口进行数据通讯时,我们会在发送端(master)把传输的数据流按照一定的规则划分成数据帧进行传输,接收端(client)根据约定好的规则将接收的数据流分帧解析执行。传统的方式主要有两...

ShuyangZ ⋅ 2016/09/22 ⋅ 0

原子变量, 无锁定且无等待算法

Java 理论与实践: 流行的原子 新原子类是 java.util.concurrent 的隐藏精华 public class SynchronizedCounter { } public class SynchronizedMutex { } public class SimulatedCAS { } publ......

刘小兵2014 ⋅ 2010/12/07 ⋅ 0

Java静态static工具类线程安全问题研究

针对静态方法有以下一些前提: 静态方法和实例方法的区别是静态方法只能引用静态变量,静态方法通过类名来调用,实例方法通过对象实例来调用 每个线程都有自己的线程栈,栈与线程同时创建,每...

easonjim ⋅ 01/17 ⋅ 0

JVM(5)-线程安全与锁优化

1.线程安全 如果一个对象能安全地被多个线程同时使用,那么它就是线程安全的。 当多个线程访问同一个对象时,如果不需要考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步...

Jdqm ⋅ 05/17 ⋅ 0

帧同步扫盲帖

帧同步: 目的: 实际: 理解: 各客户端每deltatime周期上传操作指令集(eg:左摇杆xy值,右摇杆xy值,按下哪个按钮,抬起哪个按钮); 服务端保存这些操作指令集,并在下一帧将其广播给所有客户...

tj134679258 ⋅ 2017/09/07 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

NFS介绍 NFS服务端安装配置 NFS配置选项

NFS介绍 NFS是Network File System的缩写;这个文件系统是基于网路层面,通过网络层面实现数据同步 NFS最早由Sun公司开发,分2,3,4三个版本,2和3由Sun起草开发,4.0开始Netapp公司参与并主导...

lyy549745 ⋅ 25分钟前 ⋅ 0

Spring AOP 源码分析 - 筛选合适的通知器

1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析。本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出合适的通知器(Advisor...

java高级架构牛人 ⋅ 47分钟前 ⋅ 0

HTML-标签手册

标签 描述 <!--...--> 定义注释。 <!DOCTYPE> 定义文档类型。 <a> 定义锚。超链接 <abbr> 定义缩写。 <acronym> 定义只取首字母的缩写。 <address> 定义文档作者或拥有者的联系信息。 <apple......

ZHAO_JH ⋅ 49分钟前 ⋅ 0

SylixOS在t_main中使用硬浮点方法

问题描述 在某些使用场景中,应用程序不使用动态加载的方式执行,而是跟随BSP在 t_main 线程中启动,此时应用代码是跟随 BSP 进行编译的。由于 BSP 默认使用软浮点,所以会导致应用代码中的浮...

zhywxyy ⋅ 56分钟前 ⋅ 0

JsBridge原理分析

看了这个Github代码 https://github.com/lzyzsd/JsBridge,想起N年前比较火的Hybrid方案,想看看现在跨平台调用实现有什么新的实现方式。代码看下来之后发现确实有点独特之处,这里先把核心的...

Kingguary ⋅ 今天 ⋅ 0

Intellij IDEA神器常用技巧五-真正常用快捷键(收藏级)

如果你觉得前面几篇博文太啰嗦,下面是博主多年使用Intellij IDEA真正常用快捷键,建议收藏!!! sout,System.out.println()快捷键 fori,for循环快捷键 psvm,main方法快捷键 Alt+Home,导...

Mkeeper ⋅ 今天 ⋅ 0

Java 静态代码分析工具简要分析与使用

本文首先介绍了静态代码分析的基本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代码分析工具 (Checkstyle,FindBugs,PMD,Jtest),最后从功能、特性等方面对它们进行分析和比较,...

Oo若离oO ⋅ 今天 ⋅ 0

SpringBoot自动配置小记

spring-boot项目的特色就在于它的自动配置,自动配置就是开箱即用的本源。 不过支持一个子项目的自动配置,往往比较复杂,无论是sping自己的项目,还是第三方的,都是如此。刚接触会有点乱乱...

大_于 ⋅ 今天 ⋅ 0

React jsx 中写更优雅、直观的条件运算符

在这篇文字中我学到了很多知识,同时结合工作中的一些经验也在思考一些东西。比如条件运算符 Conditional Operator condition ? expr_if_true : expr_if_false 在jsx中书写条件语句我们经常都...

开源中国最帅没有之一 ⋅ 今天 ⋅ 0

vim编辑模式与命令模式

5.5 进入编辑模式 从编辑模式返回一般模式“Esc” 5.6 vim命令模式 命令 :“nohl”=no high light 无高亮,取消内容中高亮标记 "x":保存退出,和wq的区别是,当进入一个文件未进行编辑时,使...

弓正 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部