多人实时对战网络同步方式研究

2023-11-19

写在开头:已经研究生毕业快一年半了,一直在一家游戏公司做客户端研发。至于这篇文章讲的却是服务端的东西,主要是因为以前一直没想写博客,学到的东西也一直记在本子上就得了。本人喜欢有剧情的东西,像RPG游戏(仙剑爱好者),有剧情的电视、电影,还有竞技类型的游戏,像dota/2、王者荣耀等。最近在做的项目和玩的王者荣耀都涉及到游戏的同步问题,王者荣耀做的不错,但也有自己的问题,就准备研究下这方面。本文的内容是从这两个网站https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networkinghttp://www.gabrielgambetta.com/fast_paced_multiplayer.html学习总结出来,并实现了一个demo,效果也确实不错。

好了,下面说点具体的内容,所有的内容以moba类游戏为例。

所有moba类游戏或者一些对同步要求比较高的游戏都面对一些具体的问题。一、如何让玩家体验到非常流畅的体验,而不是一顿一顿一卡一卡的表现等。二、如何防止玩家作弊。

针对玩家作弊,我进入游戏界最先听到的一句话就是“永远不要相信玩家”,一切操作都在服务端实现。但是呢由于手游的崛起以及流量的费用,一些手游还是会部分的相信玩家。

扯远了,一句话就是“在服务端进行验证”。那么最简单的实现就是玩家的任何操作都先向服务端发送请求,然后等待服务端的响应做出相应的反馈。如图一所示。客户端想向右移动一个单位,先向服务端通知,服务端反馈给客户端结果。客户端在100ms的延迟之后执行向右移动一个单位的操作。


图一

很明显上面的结果是,玩家点了向右移动的按钮,过一会才会向右移动(体验很差)。

 

优化一下 :既然上面体验不好就优化一下呗,可以发现如果我点击向右移动按钮,就直接向右移动,而不是等服务端的响应就会比较好。可是这就引发了问题二,玩家作弊怎么办?大家可能已经想到了,我先向右走然后等服务端的响应,等服务端发送过来响应的时候再检查一下,当前客户端的状态是不是对的,如果对的就好了,不对的可能就是客户端作弊了,比如说跑的快了。如图二所示。


图二


问题:但是上面又有一个问题,如果服务端响应的较慢,在服务端响应回来之前玩家已经又进行了一次操作怎么办呢?如图三所示。


图三

一个可行的方案是:客户端没法送一个操作给服务端的时候,加上一个序号。客户端继续按照上面介绍的方式去运行,不用等待服务端的反馈。当服务端的反馈到来的时候,客户端不再是去检测当前客户端的状态和服务端反馈的状态是否一致,而是要检测客户端当前的状态与服务端反馈的状态+还未执行的客户端状态是否一致。如图四,当服务端反馈#1时,客户端的位置为12而服务端的反馈的位置是11, 但是服务端反馈的位置11+#2的操作的结果是位置12所以验证时合法的。同理在服务端反馈#2的时候,验证的结果也是合法的。可见使用这样的方法,可以保证合法的玩家的用户体验很不错,同时能检测到作弊的玩家,对于作弊的玩家怎么处理可以根据项目的具体需求具体操作。


图四


上面解决了客户端内只有自己的玩家的问题,当有其他玩家的时候,如何同步其表现呢?

我们还是从最简单的开始考虑。如图五所示,那就是服务端直接同步客户端1的操作结果给客户端2,客户端2直接设置玩家1在客户端2的位置,你会发现在客户端2上客户端1的玩家的位置一跳一跳的。

一个可行的简单的优化是:既然你一跳一跳的表现不好,那我们就让它平滑一点呗(游戏中常用的方式)。让它在一段时间内以一个恒定的速度从当前位置移动到服务端反馈的位置。这样表现会稍微好点,但是当我们设定了一个恒定的时间或者恒定的速度,都会出现玩家很快移动到目的地停下来等待下次操作或者还没移动到目的地就要向下一次目的地移动,一直跟踪不上节奏。聪明的读者可能想到,出现这个的问题是因为我们无法预测玩家下一次到到达的位置,无法动态的平滑的调玩家的移动速度、移动时间来刚好达到目的地。一个巧妙的方式是“我们不要追踪当前即时的目标点,而是追踪一个我们已知的目标点”。如图六所示,我们来介绍这句话的理解。由于服务端会同步别的客户端的玩家的位置给你。在当前时刻了客户端2已知知道了客户端1经过第二次操作跑了位置12和上一次操作玩家在位置11.在当前时刻,根据一个延时,算出客户端1的玩家在一个延时之前的位置,把它表现出来,这样客户端1的表现就会很流畅。比如设置延时时间为0.1s,对人眼而言也没有什么大的误差。对于像cs:Go这样的游戏,还可以通过在服务端上做延时回放可以得到精确的位置,这里就不介绍了。想看的话可以去提供的链接1valve上去看。


图五


图六


说了这么多具体怎么实现呢?

由于涉及到客户端和服务端,要是都讲的话,只服务端都得介绍很久。这里我只讲下实现的具体思路,特别想知道具体的实现或者自己实现有问题的,可以联系我一起讨论下。

 

客户端:

一个全局的操作序号:  seq

有一个记录上传服务端的操作序列,记为self_op

一个记录其他玩家的操作反馈,记为other_op

 

玩家操作时:

记录到self_op中

同时seq++

在客户端直接操作

 

定时器:

定时上传self_op到服务端上去

 

服务端回调结果:

如果是自己的:

         根据反馈的操作序列+剩余的操作序列self_op与当前客户端玩家状态进行验证

         合法 ok  不合法:惩罚

如果是其他玩家的:

         记录到other_op中

 

logic循环:

       根据other_op和设定的延时时间计算并设置其他玩家的状态

 

服务端:

根据收到玩家的op,计算玩家的状态,存储到status中

 

logic循环:

同步当前所有的玩家状态给同一个team的所有玩家

 

(注:这是原理的实现,具体项目实现肯定还要进行一些针对性的优化)

 

 

好了,第一次写博客。 谢谢大家!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

多人实时对战网络同步方式研究 的相关文章

随机推荐

  • 计算机数据的存储-编码(补码,移码)

    在计算机系统中 补码是最重要的编码 数值一律用补码来表示 存储 主要原因 使用补码 可以将符号位和其它位统一处理 同时 减法也可按加法来处理 另外 两个用补 码表示的数相加时 如果最高位 符号位 有进位 则进位被舍弃 2 补码与原码的转换过
  • Hive order by,sort by,distribute by,cluster by 区别

    假设有一个表a 结构如下 par id c 3 c 7 b 8 b 6 a 1 a 4 a 5 c 9 a 10 b 2 order by 全排序 只会启动一个reduce执行任务 select from a order by id 在hd
  • 【C++】怎么接受未知数量的参数?

    2023年9月8日 周五下午 目录 第一种方式 可变参数函数 Variadic Function 头文件 使用方法 详解va start宏 详解va arg宏 示例程序 第一种方式 可变参数函数 Variadic Function 可变参数
  • 第2讲 Hi3861的WiFi实验-Station模式

    引言 在本文中 带大家编写一个程序 测试Hi3861的WiFi Station模式 进一步熟悉相关API的使用 请先按照本专栏第一讲中的第四部分准备好实验环境 一 编写程序 首先 打开 DevEco Device Tool 在鸿蒙项目 hi
  • Mysql JDBC Driver参数配置

    1 建立连接配置 1 user 连接的用户 默认值 无 2 Password 连接时使用的密码 默认值 无 3 socketFactory 驱动程序用于创建与服务器套接字连接的类的名称 该类必须实现了接口 com mysql jdbc So
  • 问题解决:io.lettuce.core.RedisCommandTimeoutException: Command timed out after

    环境 spring boot starter 2 x 和 sprig data starter data redis 2 x 在使用 connection bRPop timeout rawKey 方法时 如果这里的timeout大于spr
  • 飞桨AI Studio(星河社区)推出文心大模型的SDK功能

    随着大模型的涌现 我们喜悦于其远远超越小模型的性能 但又不得不面临大模型开发难的困境 训练难 微调难 部署难 开发者难以将其投入实际生产 不仅面临资源的限制 更面临高精数据难寻 时间成本过高等问题 为了让平台更多开发者可以进行大模型开发 体
  • 有序顺序表的插入

    下面看问题场景 如图是一个有序表 有序表是用数组承载的 然后我想把 元素 8插入到有序表 怎么实现呢 下面开始用人脑模拟 要把 8 插入到有序表 先从有序表的第一个元素和8进行比较 依次看到了7 下一个元素9大于8 停止遍历 我们就把 8
  • ABAP动态编程-动态生成报表、动态屏幕

    目录 前言 一 动态生成报表并调用 二 动态生成屏幕并调用 总结 前言 本文主要讲述ABAP编程中根据逻辑自动生成报表及屏幕 依托语句GENERATE DYNPRO 的实现示例及简单说明 一 动态生成报表并调用 代码示例 Create re
  • Map对象以及作用域

    首先我们要明白什么键值对 键值对 key value 顾名思义 每一个键会对应一个值 例 a 身份证号和你本人是绑定的关系 每一个身份证 键 会对应一个人 值 b 登录微信和游戏 需要输入手机号验证身份 手机号码 键 对应接收用户 值 每个
  • core_cm3.h文件报错问题

    D Software Keil5 ARM PACK Keil STM32F1xx DFP 2 1 0 Device Include stm32f10x h 483 error 5 cannot open source input file
  • mysql批量插入数据

    比较两种批量插入数据的方法 差距不是一般的大 方法一 最笨重的方法 一条一条的插入 sql语句如下
  • 假定CSomething是一个类,执行下面这些语句之后,内存里创建了____个CSomething对象。...

    CSomething a CSomething b 2 CSomething c 3 CSomething ra b CSomething d b CSomething pA c CSomething p new CSomething 4
  • Python自动化测试之异常处理机制知识讲解

    一 前言 今天笔者还是想要讲python中的基础 主要讲解Python中异常介绍 捕获 处理相关知识点内容 只有学好了这些才能为后续自动化测试框架搭建及日常维护做铺垫 废话不多说我们直接进入主题吧 二 异常处理合集 2 1 异常处理讲解 在
  • 四川百幕晟科技有限公司:抖音名称最多多少字?

    在抖音上 用户可以为其帐户选择昵称 该昵称显示在用户的个人资料中 不过 很多人好奇 一个抖音昵称到底能有多少个字 本文将深入探讨抖音昵称长度限制以及一些最吸引人的昵称示例 1 抖音昵称长度限制 抖音昵称的长度限制是一个相对灵活的规定 具体而
  • android判断一个Activity是否处于栈顶

    实际开发中我们需要很多情况需要判断某个activity是否位于栈顶 也许会给新的小伙伴带来困扰 那么直接上代码吧 也没几行 判断某activity是否处于栈顶 return true在栈顶 false不在栈顶 private boolean
  • Charles连接手机移动端的基本使用及教程

    一 Charles基本使用 1 打开 Help Local IP Address 查看本机的IP地址 2 设置手机 手机需要连接到和电脑在同一网络的 WIFI 依次打开 设置 无线局域网 点击已选wifi最右边的感叹号 填好以后 返回 打开
  • MySQL 8 group by 报错 this is incompatible with sql_mode=only_full_group_by

    文章目录 sql mode配置 ONLY FULL GROUP BY STRICT TRANS TABLES NO ZERO IN DATE NO ZERO DATE ERROR FOR DIVISION BY ZERO NO AUTO C
  • linux的设计模式属于,linux下GUI设计模式的有效性

    考虑到你在评论中如何解释你的应用程序 同时完全支持Qt 我也建议你考虑一下将你的应用程序变成一个web应用程序可能带来的许多好处 在 既然你说它是一个客户端服务器应用程序 它至少需要 至少 本地网络连接 所以通常针对web应用程序提出的第一
  • 多人实时对战网络同步方式研究

    写在开头 已经研究生毕业快一年半了 一直在一家游戏公司做客户端研发 至于这篇文章讲的却是服务端的东西 主要是因为以前一直没想写博客 学到的东西也一直记在本子上就得了 本人喜欢有剧情的东西 像RPG游戏 仙剑爱好者 有剧情的电视 电影 还有竞