游戏战斗同步机制

简介

基本上大部分游戏都有战斗

战斗的同步机制无非两种    状态同步和帧同步

帧同步当中笔者还了解过一个分支(帧校验)

状态同步

原理:玩家发送指令到服务端 服务端进行战斗逻辑运算 将计算结果(比如玩家的位置 血量等等)发送给客户端 战斗逻辑在服务端   

通俗的讲 客户端a和客户端b同一时间看到的画面可能是不一样的 但最终玩家的状态(位置 血量等)不管在哪个客户端那里看 数据都是一样的

客户端收包时机:玩家状态发生变换时会收到服务器发来的数据   

好处:防作弊 以服务器的计算结果为准

缺点:宽带消耗大 服务器压力大

适用场景:回合制游戏  射击游戏(射击游戏还有客户端预测加回滚做优化)

回合制游戏

回合制游戏是最经典用状态同步的了

比如rpg和一些slg

对于回合制rpg来说

服务器处于选招状态 玩家选招
-->服务器计算结果
-->服务器处于播报状态 客户端播报
-->通知服务器播报完成
-->服务器切换成选招状态

也就是说当服务器处于选招状态时 玩家不管谁先完成选招都没有影响 

这对于帧同步来说就不一样了 帧同步的是先完成选招的玩家会先出手

对于一些slg游戏来说 就没有玩家选招的状态  英雄的出招是自动的 服务器直接计算完战斗结果返回给客户端

客户端常识

一般来说客户端的代码会分为表现层和逻辑层

为了保证结果准确 服务也需要跑相同的代码 这个代码指的就是客户端的逻辑层代码

fps常见问题

射击游戏可以说是用了状态同步加帧同步的结合

对于fps游戏来说 为了降低延时感 会让客户端先做表现 或者说叫客户端预测 等到服务端运算完发回包后 进行校验是否做回滚

也就是说玩家的血量要以服务器的为准 

客户端发来数据时 服务器做转发 同时服务器也在进行运算

服务器做转发的数据 客户端用来在表现层做处理  服务器运算的数据做在逻辑层

笔者的认知当中认为   客户端发指令后 服务器进行转发 每个客户端都按照指令作为输入进行战斗表现  比如播放动画 特效啥的 同时服务器也在跑战斗代码 但当服务器发来了状态信息 比如(玩家的血量 位置) 客户端在刷新这些数据

同时fps笔者认为也用到了之前的aoi九宫格的广播 比如吃鸡游戏 一张大地图这么多玩家 玩家只需要获得当前所在地图的格子和周围8个格子的玩家数据 然后进行跑战斗代码 

fps游戏还有个说法是 未来的自己打过去的玩家

也就是跑帧的时候 玩家攻击了 这个时候会取前几帧其他玩家的状态来攻击 判断是否打中或者扣血

一般来说fps用udp协议 

帧同步

原理:玩家发送指令到服务端 服务端只做数据转发 将指令转发给其他客户端 其他客户端收到后在本地作为输入进行战斗计算

通俗的讲 一般来说很多游戏都是60帧 或者有些是30帧 或者240帧等等 

以60帧为例 每一帧就是1/60    0.16秒的间隔 每0.16秒的时间服务器都会等待客户端发来指令 如果没有指令也要发空包 然后服务器打包起来转发给每个客户端      每个客户端收到后在本地进行战斗计算  客户端每0.16秒也就是一帧看到的画面都是一样的

客户端收包时机:每一帧都要收到服务器发来的数据

好处:服务器压力小 对实时要求高的游戏体验好

缺点:容易作弊 且不适合同个画面多单位的场景

适用场景:moba游戏 fps游戏

常见问题

数据一致性:每个客户端接收同样的指令跑一样的代码  按理说得到的结果是一样的 但帧同步开发过程中最头疼的就是客户端之间数据不一致的问题 因为每个客户端跑的机器可能不一样 一些随机函数 一些底层的设计不一样

常见的就是随机数和浮点数

随机数一般都是服务器一开始做个随机种子发给客户端 然后开发者自己做一个随机函数 参数为随机种子  函数通过随机种子作为参数 输出另一个随机数 另一个随机数又作为下一次的参数

这样即可以得到一个随机数 但是每个客户端得到的随机数都是一样的 叫做假随机

还有个浮点数问题 每个机器的小数后保留的位数可能不一样 

解决方法就是传输数据时不传小数 传分子和分母 然后客户端计算完后保留固定的位数

或者直接将数据放大1000倍 保留整数 再传数据

一般标准库中的hash也是不能用的 因为当你遍历hash结构时 顺序是不能保证的 一般要自己封装一套

还有一种假如某个客户端掉线了一直不发包怎么办

这种时候有两种 

1服务端默认客户端发空包 不管

2服务端一直等待这个客户端 其他客户端全部卡帧等待 等到一段时间后判断该客户端下线

作弊

帧同步因为是客户端做战斗逻辑 代码在客户端 懂点技术的玩家是可以修改代码 

解决方式

1每次客户端发包的时候 把当前玩家的一些关键信息做个摘要 然后通过hash算法得到一个值

客户端发数据到服务器后 服务器把每个客户端发的值都对比 不相同的直接抛弃

2客户端发的数据 服务器同时也做一份保存 当战斗结束后服务器再跑一次逻辑 然后把结果和客户端进行对比 类似帧校验

当然这些只是防止了部分作弊 还有一些不是关键信息的作弊 比如王者荣耀的开全图 或者百里守约的自动秒准 就没办法了

开全图也有个解决办法 那就是在地图中某个地方 这个地方(正常情况下是一直看不到的)如果被看到就当作弊

协议

一般来说为了实时性 传输层的协议都是用udp 市面上比较成熟的可以用kcp

帧校验

和帧同步防作弊的思路一样的 就是客户端跑一段时间后 把多个帧的数据打包发给服务器

服务器跑相同的代码 然后验证结果  有点像帧同步和状态同步的结合 就是最终结果以服务器为主

但客户端可以先行跑逻辑

相似点

笔者认为状态同步和帧同步 除了计算战斗的逻辑分别在服务器和客户端外

笔者认为有个相似点就是 

帧同步是每一帧都要求数据一致

状态同步是要求同步状态时数据一致 两次同步状态的间隔之间数据可以不一致  

其实帧同步和状态同步对数据一致的要求是一样的 都是同步的时候数据要一致 只不过同步的时间间隔不一样   帧同步可能是0.16秒 状态同步可能是几秒

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值