最近毕设准备做一个关注游戏同步方案的 demo,准备选用帧同步。正巧所在组火影手游绝大部分的玩法都是使用帧锁定同步来做的,所以在这记录一下。
概述
帧同步,或者更详细的说是帧锁定同步
,是将前端的表现划分为每秒n次的逻辑关键帧,客户端的表现根据关键帧完成展示。客户端将指令经由或者不经由服务器广播到所有相关的客户端上,相邻的指令将会被封装为帧并被客户端理解执行。所有元素在某一时刻的状态,都是由各个客户端独立计算出来的。
帧同步方案
这里我们讨论cs架构下的帧同步方案。
下图反应了火影手游pvp玩法中的同步逻辑。
可以看到,服务器端每 66ms 会将接收到的所有客户端指令封装成帧并下发到各客户端中。如果某个帧在传输中丢失了,将会随下一帧重传。同时,使用 seq 和 ack 对每个帧进行确认。如果 99ms 内客户端还没有收到包含自己已发出指令的帧,就要将丢失的指令重传。
无论是客户端发送的 action,还是服务器端的 frame,都要有确认重传机制。frame 的确认就是通过客户端附带的 ack 字段来确认。
乐观锁
标准的帧同步,是要求客户端定时发送指令,服务器必须等待收集到所有客户端的包之后再下发,这个等待帧信息的过程称为帧锁定。如果一个客户端网络卡顿,那么所有客户端都要等待这个客户端的帧同步信息。
乐观锁就是无论是否收集到客户端的信息,都将目前为止收集到的指令封装为帧并下发,客户端发现自己的指令丢失之后应该将指令重传。这样所有客户端不会因为某个客户端的卡顿而卡顿。
不同步,反作弊以及Gamecore
每个客户端都要保证有相同的初始状态,一旦存在不同步,就要快速定位不同步和恢复。
当玩家数多于2个的时候,可以取大多数作为正确的状态,在检测到不同步后恢复。如果是只有两人参与的游戏,如果出现不同步,比较好的解决方法是设计合理的 gamecore。
gamecore 是同时运行在客户端和服务器端的游戏核心逻辑,所有状态结算都由 gamecore 完成,我们可以更倾向于相信 gamecore 的计算结果。一旦出现不同步,只要 gamecore 和其中部分客户端的计算结果一致,就可以将 gamecore 的状态下发到客户端中。如果 gamecore 与所有玩家的状态都不一致,那么就要考虑 gamecore 的健壮性和正确性了,应该通过 log 及时发现并排除这样的状况。
如上的 gamecore 设计,也是一个反作弊的好解决方案。
gamecore 和状态同步?
帧同步主要是为了解决大量单位都需要同步的情况,比较少量的网络传输能够保证高度同步。gamecore 只是为了辅助客户端的状态计算,这样保证了同步的高效性。
finally
以上说的都是一些浅薄的个人之见,有什么不对的希望业界前辈不吝赐教!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。