帧同步简介
帧同步是让玩家保持一致性,可以进行对战联机的功能,王者荣耀要采用了该技术。简单点来说,就是每当玩家进行操作,都会上传对应的操作给服务器,服务器定时将收到的操作发放给游戏客户端,每个游戏客户端收到的数据都是一样的,运行的结果自然也是一样的。
帧同步跟状态同步相比,优点有:高一致性,低流量消耗,简化服务器逻辑,容易反作弊。
sdk特点
本次开发的sdk使用了udp技术,支持微信小程序,qq小程序,web和app端等多平台。
如何兼容多平台
- 对外接口保持一致
- 复用平台能力
- 数据结构,类型声明保持一致
udp实现
这里开发的帧同步使用了udp的技术,udp有下面的特点:无连接,延迟低,多播,弱网表现更好。然而无连接也带来了数据传输不可靠的问题,如何避免呢?
首先是上传的时候使用三倍冗余,帧的数据结构带上帧id,定时对收到的帧进行id的校验,如果id不连续,跟服务器进行补帧的请求。
udp这么好,赶紧用起来,微信小程序的帧同步是支持udp的,我只需要封装一下平台的能力就好了,保证数据结构,api等跟别的平台一致就好了(然而还是踩了很多很大的坑),遗憾的是web端暂时不支持udp,也只能降级到使用tcp方案,qq小程序原生支持udp,但是要付费,同样降级~
现在就还剩app端了,经过和客户端大佬的讨论,决定使用app跟后台进行udp通讯,然后app在跟web端进行websocket通讯的方法来曲线实现帧同步。
有人想问了,为什么web跟客户端不用jsbridge那套?那样不是更方便吗?
答案是,jsbridge是使用字符串来传输,效率比不上websocket,由于帧同步的传输量大,对实时性要求高,引起我们采用了现在的方案
反作弊
- 多人是采用多数人方法
- pk时采用定时校验关键环节方法避免作弊
- 还可以将数据转发给能跑游戏逻辑的服务器来运算校验
开发时踩过的坑
难以排查问题
帧同步的初始化是一个很繁琐的过程,需要判断当前是否已经存在帧同步,是否重新链接,判断token是否正确,能否链接后台,连接后还要进行登录等等,每一步都可能卡住,卡住之后固然上报数据,但也很难排查发生了什么事情。
解决方法:,每进行一步都输出对应的日志,并对日志进行编号,出错的时候上传编号列表,然后根据编号列表反向查询日志来判断进行到哪一步,出错原因可能是什么。
对错误的处理
原本只是单纯的抛出错误,等候游戏处理,后来发现错误类型太多,错误可能来自服务器,可能来自游戏的错误调用,可能来自sdk本身的逻辑有问题,游戏收到错误也不知道该怎么处理,因此,主动对错误进行了分类分级。
将错误分为了会导致游戏结束的致命错误,需要注意的错误,无关紧要的错误三个级别,并告知给游戏。
完善事件机制
原本只有玩家发送的广播事件会告知给游戏方。而如果帧同步本身断开链接,只是会默默的自动重连,不告知游戏方。
然而现实很骨感,有时就是重连不上,重连要很久,因此补上了断开链接和重新连接的事件,以及游戏开始,游戏结束事件等,让游戏方更了解帧同步sdk运行的状态。
教训:一些事情可能自认为不会影响到用户,可以解决,但还是会出现无法解决,解决耗时太久的问题,需要主动告知用户。同时也要主动跟用户沟通,补充用户感兴趣的通知事件。
容易掉线
定时发送心跳,同时计算ping
不同玩家展示不一样
- 避免本地计算浮点数
- 定时同步状态
- 帧数据驱动展示