状态同步位置和技能(适用于fps和mmorpg类游戏)
客户端A的同步阀值(减少同步量)
客户端A本地会存储一份对其他客户端看到的A的预测状态,当本地真实状态和预测状态偏差超过阀值时,则发起同步,同时更新客户端A本地的预测状态
玩家运动的关键点也会同步,例如起跳坐标点,起跳最高坐标点,落地坐标点,开始跑步的速度方向,停止跑步时的坐标点
插值算法的选择
客户端插值 和 航位推测的选择
航位推测只用于预测位移
客户端插值(线性插值,3次样条插值,曲线的寻路(寻路这个可能会在同步频率低的游戏中使用))
使用航位推测:不做服务端的延迟补偿时,可以对客户端A上的第三方代理对象做航位预测
客户端A上看到的玩家B的移动
客户端A看到的第三方玩家B一直向着A接收到的服务端发来的B的数据包的最新状态插值,当客户端B走到最新状态,还是没有再次接收到服务器的数据包时,会按上一个移动操作包进行运动,直到再次收到B的数据包,则去检测是否有错误
客户端A上玩家B的移动预测错误时的纠正
A接收到服务端的数据包时检测到B在客户端A上的模拟有错误时,有以下处理方法
1.距离远则瞬移表现层,适用于快节奏的游戏
2.距离近则插值,可以用3次样条插值,适用于快节奏的游戏
3.如果是突然加速这种,可以加二阶参数(例如加速度)去处理,例如插值时增大加速度,接近航位推测近似值时降低加速度
使用插值:做了服务端延迟补偿时,服务端需要精确的计算出被射击的玩家的位置,需要通过帧数和插值进度去计算,所以此时不能用航位预测
一般类似fps需要优化射击方体验的游戏中需要延迟补偿,此时远程玩家使用客户端插值,而不是用航位推测
在客户端A看到的第三方对象B,例如B此时从第3帧的状态插值到第6帧(帧状态是服务端下发的,且客户端更新频率和服务端更新频率保持一致,一般是1秒30帧)
A开枪射击B时,发起射击请求,请求包内会有A在XX坐标,以XX角度,B从第3帧,插值到第5帧,当前插值进度XX
服务端收到包后,根据缓存的前几帧的状态和插值的帧以及插值进度去计算A开枪时看到的B所在的位置,再做命中检测
客户端A接受到A的状态数据包时的处理(移动)
客户端发起移动包,同时客户端记录下这个操作(客户端utc时间和操作),客户端本地立刻开始移动(此时是客户端的移动预测)
RTT时间后接收到服务端发来的数据包,将这个数据包内的时间戳和整个数据包状态存储起来
因为接收到的数据包里的状态会比当前服务器状态慢大概半个RTT,所以需要本地模拟预测半个RTT的移动
根据数据包里的服务端发起的utc时间 + 服务端和客户端的时间差,得到客户端对应的服务端发起这个数据包的时间点
然后客户端从记录下来的自己的移动操作列表中得到这个时间点之后所有服务端未加入计算的移动操作
通过数据包(指定时间在哪个坐标)+服务端计算出这个数据包时未计算的操作(也就是客户端这个时间点后的其他操作)
计算出在当前时间应该在的状态C(位置,方向,旋转等),然后向C状态进行插值
(如果移动的中途没有被其他玩家影响的话就是精确的,即使有误差也会很小(例如被技能打中晕眩之类的)),被其他玩家操作影响后也会发同步消息到客户端,客户端再纠正
玩家B施法,客户端A看到玩家B是怎么施法的
会有延迟,也就是玩家B在客户端B按下施法,客户端A看到的玩家B至少也是RTT时间后才会播放施法动画
玩家A施法,客户端A看到玩家A是怎么施法的
按下施法按钮,先播放前摇,前摇时间至少是RTT,接收到返回的数据包时,如果不能施法则停止施法动画,如果能施法则继续动画,以及播放后续施法效果(例如射出飞弹)
服务端延迟补偿
服务端会记录之前的n帧的世界状态
服务端接收到玩家A的施法包时,从包中取出客户端发起的utc时间戳t1,加上服务端和客户端的时钟差后得到玩家A在发起操作时服务端的时间t2
那么用t2去取之前记录下来的世界状态
掩盖不同步的技巧以及优化
优化命中表现:添加攻击边缘模糊的特效,数据层上会击中的攻击,因为表现层还在插值,所以如果没有特效,看起来是不会击中的,但因为有范围模拟的特效,所以表现上就跟击中了一样
优化预测:前摇时间的调整
为了预测效果更好,某些情况下可以信任客户端
降低延迟
选择更近的服务器节点(需要负载均很)
让服务器和客户端tick的速度更高(需要衡量性能压力)
尽量减少服务端和客户端接收到输入时的缓存buffering处理
客户端平滑插值(平滑处理位移的做法会在整个同步过程中的方方面都用到)
接收到消息包(包含时间戳以及正确的位置P1)后,和本地记录的该时间戳的位置对比,如果相同则不处理。
如果不同则,数据层从P1位置开始按已经记录下来的这个时间戳之后的操作包进行移动,然后得到客户端预测的数据层位置。
和当前表现层的位置进行比较,距离远就瞬移,距离近就插值(如果是直接拉回,不进行P1+预测包的预测处理的话,表现上看起来会莫名其妙的拉回到以前的一个位置,网络差时基本就不会移动了)
体验上分为:对人战斗的体验和单击打怪的体验
优化了延迟后仍然会有的问题
fps中看A玩家看到自己已经躲到了掩体后,仍然被命中。原因如下:
1是A的操作还没发到服务端,虽然看着是进了掩体,但在服务端看来是没有躲在掩体后的
2是fps如果做了服务端的延迟补偿,则B开枪射A,B看到的A是滞后服务端半个RTT的且正在插值的对象,此时如果B的网络很差,则A躲进掩体后,B还是能看到A且命中A
不停移动的玩家会更难射中,因为即便做了以上的优化后,仍然会有误差
整体流程来看:
按下鼠标到网络packet发出--客户端帧数越高越好
网络延时(ping)--延时最大头
服务器上面buf
【笔记】状态同步笔记
最新推荐文章于 2025-03-08 15:30:00 发布