帧同步和状态同步是游戏客户端和服务器通信的两种方式:
适合帧同步的情况:
1,网络波动较大,比如移动端网络。
2,追求即是反馈,例如FPS、MOBA,SPT(这是啥游戏?)
3,控制大量单位,RTS(星际魔兽)
简易模型
1,状态同步
发操作、收状态。
客户端上传指令->服务端下发状态->客户端播放状态
2,帧同步
发操作、收操作
操作发送给服务器、服务器转发给客户端、客户端表现。
(把所有玩家的操作发给所有玩家,包括发送者自己)
控制100个单位移动需要多少数据量?
状态同步是定时的发送给客户端状态,服务器的运算压力较大
帧同步的计算量主要在客户端上。
帧同步和状态同步的区别
1,如果游戏中有随机数的情况,帧同步需要保证所有玩家的数据是相同的,如果玩家A的随机数是10,那么玩家B的随机数也必须是10,。因此随机数和字典不能用。
2,中途加入游戏:帧同步可能需要等一会,需要从游戏开始的状态计算,一直计算到游戏当前的状态。状态同步直接下发状态数据,不需要等待。
3,帧同步不容易反外挂,状态同步安全性较高。
4,离线战斗:帧同步可以实现不连接服务器也能战斗。
帧同步和状态同步的游戏案例:
MOBA:英雄联盟,Dota2,虽然实时性要求较高,但是是状态同步的,因为他们是PC端游戏,网络相对稳定。而王者荣耀采用的是帧同步。
RTS:星际争霸、魔兽争霸,操作单位过多
MMO:大多以状态同步
其他:刀塔**、FGO
帧同步的原理
1,服务器发初始帧Update0给客户端,客户端收到以后,就以每5帧(假设每5帧)同步一次的频率给服务器发送消息。首先发第0帧的操作,由于有网络延迟的关系,客户端A和客户端B发送的消息发送到服务器的时间不一样,B先到,A后到,此时服务器会等待A的数据报到达之后再向所有玩家广播A和B的操作。
2,服务器同时向A和B广播A和B的操作,而由于网络因素,B先收到,此时B先进行操作然后发送给服务器,然后服务器等待A的包到达之后,再向A和B广播消息。
看到这里不难发现一个问题,就是卡顿。假如有一个玩家网络不行,就会把所有玩家都卡住。
(学到这里我不禁想起了当年在浩方VS玩Dota1的时光)
一套完整的帧同步游戏框架
1,可靠UDP
2,确定性的数学和物理运算库
3,断线重连
4,比赛回放
5,反作弊
6,避免等待
1,可靠UDP
粘包:50ms以内的数据包,如果数据量很小,就把这些包合并在一起。比如我有一封信要寄到美国去,飞机会等待很多有相同需求的人的信,然后一起送过去。
2,确定性的数学和物理引擎
(1)首先十进制浮点数无法精确转换为二进制
(2)浮点数运算对位 console.log(0.1+0.2)=0.30000000000000000004
(3)非确定性物理引擎
右侧游戏是断线重连的,用浮点数学就会产生不精确性。
解决方案:
(1)取整计算
(2)容许小概率误差
(3)逻辑表现分离(表现层可以使用浮点数) 图形变换、模型、动画