最近毕设准备做一个关注游戏同步方案的 demo,准备选用帧同步。正巧所在组火影手游绝大部分的玩法都是使用帧锁定同步来做的,所以在这记录一下。

概述

帧同步,或者更详细的说是帧锁定同步,是将前端的表现划分为每秒n次的逻辑关键帧,客户端的表现根据关键帧完成展示。客户端将指令经由或者不经由服务器广播到所有相关的客户端上,相邻的指令将会被封装为帧并被客户端理解执行。所有元素在某一时刻的状态,都是由各个客户端独立计算出来的。

帧同步方案

这里我们讨论cs架构下的帧同步方案。
下图反应了火影手游pvp玩法中的同步逻辑。
clipboard.png

可以看到,服务器端每 66ms 会将接收到的所有客户端指令封装成帧并下发到各客户端中。如果某个帧在传输中丢失了,将会随下一帧重传。同时,使用 seq 和 ack 对每个帧进行确认。如果 99ms 内客户端还没有收到包含自己已发出指令的帧,就要将丢失的指令重传。

无论是客户端发送的 action,还是服务器端的 frame,都要有确认重传机制。frame 的确认就是通过客户端附带的 ack 字段来确认。

乐观锁

标准的帧同步,是要求客户端定时发送指令,服务器必须等待收集到所有客户端的包之后再下发,这个等待帧信息的过程称为帧锁定。如果一个客户端网络卡顿,那么所有客户端都要等待这个客户端的帧同步信息。

乐观锁就是无论是否收集到客户端的信息,都将目前为止收集到的指令封装为帧并下发,客户端发现自己的指令丢失之后应该将指令重传。这样所有客户端不会因为某个客户端的卡顿而卡顿。

不同步,反作弊以及Gamecore

每个客户端都要保证有相同的初始状态,一旦存在不同步,就要快速定位不同步和恢复。
当玩家数多于2个的时候,可以取大多数作为正确的状态,在检测到不同步后恢复。如果是只有两人参与的游戏,如果出现不同步,比较好的解决方法是设计合理的 gamecore。

gamecore 是同时运行在客户端和服务器端的游戏核心逻辑,所有状态结算都由 gamecore 完成,我们可以更倾向于相信 gamecore 的计算结果。一旦出现不同步,只要 gamecore 和其中部分客户端的计算结果一致,就可以将 gamecore 的状态下发到客户端中。如果 gamecore 与所有玩家的状态都不一致,那么就要考虑 gamecore 的健壮性和正确性了,应该通过 log 及时发现并排除这样的状况。

如上的 gamecore 设计,也是一个反作弊的好解决方案。

gamecore 和状态同步?

帧同步主要是为了解决大量单位都需要同步的情况,比较少量的网络传输能够保证高度同步。gamecore 只是为了辅助客户端的状态计算,这样保证了同步的高效性。

finally

以上说的都是一些浅薄的个人之见,有什么不对的希望业界前辈不吝赐教!


mist14
45 声望8 粉丝

想养喵