同步,其实就是让所有客户端看到的内容是一致的,举个例子:王者荣耀,5V5时,当玩家A释放了一个技能,10个玩家(包括A)的手机屏幕上都应该可以同步看到玩家A释放的技能。所以同步一说,一般都是指在网络游戏中,玩家在各自的设备上看到相同的东西。而单机游戏,自己玩自己的,基本不需要同步。 而主流的同步方式一般就是状态同步和帧同步两种。
一.实现原理:
状态同步:
客户端发送操作指令给服务器,服务器接到指令后进行逻辑处理,把最终的处理结果返回给客户端。然后客户端根据服务器返回的结果,在本地播放对应的效果就可以了。
如:A点击了技能按钮(释放一个技能攻击B),那么客户端会发送使用技能的消息给服务器,服务器会处理这个消息,是否够”蓝“放技能,技能对B造成多少伤害,B是否死亡,等等的一些逻辑运算,最终会把结果返回给所有的玩家,然后所有玩家的设备上(客户端)就会播放技能释放特效,B的受击动画,然后B的扣血飘字等等的效果。
帧同步:
客户端发送指令给服务器,服务器不做任何处理把指令转发到所有客户端,然后所有客户端收到指令后再在客户端本地执行逻辑处理,然后播放效果即可。
二.优缺点对比:
1.服务器压力
状态同步:因为逻辑运算在服务器,相对来说压力会比较大。
帧同步:无服务器压力。
2.逻辑一致性
状态同步:统一在服务器运算,绝对一致。
帧同步:需花较大的功夫以确保一致性。如:战斗开始时接受服务器发送的随机因子,以确保所有客户端随机结果一致。 尽量避免小数点运算,以确保不同设备上运算结果会有误差等等。
3.断线重连:
状态同步:比较好实现,因为重连时,当前回合实时的数据都在服务器,服务器只需要把当前服务器的数据给客户端,就可以直接呈现当前的战斗界面状态。
帧同步:因为服务器只有客户端所有的操作步骤,重连时,可能需要从第一步开始执行,直到执行到当前游戏进度的这一步,才能还原整个战斗界面状态。
4.战斗回放:
状态同步:需要记录保存所有发送给客户端的状态信息,保存的数量量比较大。
帧同步:只需要保存转发给客户端的操作记录即可,回放实现比较方便。
5.数据量:
状态同步:比较多,因为服务器要把处理逻辑后的所有玩家状态,处理结果都发给客户端。
帧同步:比较少,只需转发操作指令。
6.网络延迟:
状态同步:可以通过预表现的方式,让玩家看起来相对没那么卡,流畅一点。
帧同步:会整个游戏卡顿,效果比较差。
7.防作弊:
状态同步:比较简答,因为核心计算逻辑在服务器,即使玩家修改了客户端,也只能改他本地的显示效果。
帧同步:比较困难,因为逻辑处理都在客户端本地执行。但也可以通过一些手段加以验证结果,如:验证所有玩家结果的一致性,如果一个玩家作弊,调高了自己的攻击了,那么这个玩家的客户端会显示一刀杀死了对方,而其他客户端上则显示对方只是正常扣血并没有死亡,由此也可以验证这个玩家的客户端异常。 但也存在一些作弊行为难以有效制止,如:显示全地图,全玩家位置等
8.开发效率:
状态同步:需要客户端服务器对清楚需求,合作制作,联调等(就是多了沟通成本)。 但由于很多游戏的战斗都有PVE部分,所以其实可以有客户端统一开发战斗系统,单机战斗和联网战斗使用同一套战斗代码,这样就可以省掉沟通成本,不过也需要格外增加一些客户端或者服务器相关特殊处理的代码。
帧同步:服务器只负责转发,所有代码均有客户端开发(无沟通成本),但也要重点注意”防破解“,”代码执行结果唯一性“,”逻辑与表现分离“等相关内容。
9.适用场景
状态同步:几乎适用于所有的游戏。
帧同步:不适用与玩家数量过多的游戏(占很高带宽);不适用于超大地图的MMO游戏,因为在超大地图的游戏中,客户端只有当前手机显示的这一部分区域的数据,而地图的其他数据都存在于服务器中,客户端没全部数据也没办法去做逻辑处理。
PS:绝大部分游戏均可使用两种同步方式,具体哪种更适合,需要综合考虑游戏类型、战斗模式、网络带宽、延迟响应、防作弊、开发周期等等因素来选择不同的方案,甚至二者混合使用,没有最好的技术,只有最合适的技术。 所以用哪种方式只能看项目的具体需求。
--------------------------------------------小知识-------------------------------------------
1.早期的帧同步,服务器会等待接受齐所有玩家的关键帧消息后,才会转发给所有玩家,导致一个玩家卡顿,所有玩家都卡顿,都停下来的极差游戏体验感。 现在的帧同步采用”乐观帧“,服务器在固定时间间隔把收到的客户端发过来的消息转发给其他客户端,不等待卡的那位了。这样就只会让卡的那个玩家那边卡着,其他网络正常的玩家正常进行游戏,体验感好很多。