网络同步 #
网络同步 = 数据同步 + 表现同步 网络同步一般分为帧同步和状态同步
帧同步 #
基本原理 #
计算逻辑在客户端,按照一定的帧速率(逻辑帧而非渲染帧),服务端只转发
帧同步缺陷 #
- 计算逻辑不在服务端,容易出现外挂
- 严格帧锁定同步网络差的客户端会影响其他玩家体验(乐观帧锁定同步)
- 不同客户端浮点数精度问题、随机值不统一
乐观帧锁定 #
传统严格帧锁定算法会出现慢网影响其他人的情况,此时可以采用定时不等待的方式,服务端以固定帧率同步数据,不依赖每个玩家是否有操作
状态同步 #
基本原理 #
计算逻辑在服务端,客户端只表现。状态同步一般都应用RPC调用和增量同步技术
状态同步缺陷 #
- 延迟过大、服务端压力大
- 状态同步做回放系统较麻烦
网络协议 #
一些基础 #
- TCP是流式传输没有固定内容边界,会出现拆包和沾包问题,UDP基于报文有消息边界,不存在拆包沾包问题
- TCP默认情况下使用Nagle算法,可以优化传输减少网络里的小包数量,传输时协议栈会累积数据直到满足以下条件之一
- 积累的数量达到最大MSS
- 收到一个ACK
- TCp默认情况下使用延迟累积ACK发送机制,传输时协议栈会合并多个ACK发送,提高网络性能,直到满足一下条件之一
- 累积多个ACK或有数据传输时
- ACK超时(40ms)
- TCP可以使用TCP_NODELAY来关闭Nagle算法
网络协议方案 #
可以默认使用TCP,然后再打开使用KCP 在网络状态较好时可以使用KCP,当出现大量丢包时切换使用TCP
同步优化方案 #
表现优化 #
表现优化主要是想弱化玩家对于延迟的感受,主要分为以下一些优化技术
1.插值优化 #
https://zhuanlan.zhihu.com/p/631954987?utm_id=0 状态同步中,由于客户端每次收到都是其他角色的位置信息,为了避免位置突变,客户端会使用插值技术而不是跳帧
- 内插值目的是解决客户端离散信息更新导致的突变问题,通过线性插值Lerp插入过渡数据
- 收到数据包时不能直接应用,必须等到下一个数据包到来才能开始插值,延迟增加
- 运动状态发生剧烈变化时,会丢失部份运动状态
- 外插值目的是解决网络延迟过大或抖动导致间隙性收不到数据的卡顿问题,通过额外同步线速度、角速度、加速度和网络延迟等数据,在收到包时直接推测下一个数据包的状态
- 如何判断外插值预测结果的正确性?
- 如何从错误的预测结果平滑过渡到正确的运动状态
2.预表现和回滚 #
预测的目的是让玩家输入后立刻得到反馈,提高游戏体验,回滚是保证服务器的权威性 玩家本地执行的记录通过move_buffer存储,在收到服务器的数据时
- 如果本地和服务器一致,则客户端清理move_buffer
- 如果本地和服务器不一致,则需要本地回滚到服务器指定位置,把错误时刻后面的move_buffer数据再执行一遍
延迟对抗 #
用于弱化玩家对延迟的感受,主要有以下一些技术
1.延迟补偿 #
用于弥补客户端到服务端同步的技术,核心是服务器在指定时刻对玩家角色进行位置回滚和计算 实现方式:服务器会定时记录所有玩家的位置,假设客户端到服务端的延迟为xms服务端收到客户端的操作后,服务器使用记录的xms前所有玩机的位置来计算是否命中,从而抵消延迟带来的问题
缺陷:不适合ACT网游
带宽优化 #
1.对象裁剪 #
- AOI算法
2.增量状态快照 #
资料参考 #
https://zhuanlan.zhihu.com/p/105040792 https://www.skywind.me/blog/archives/1343 https://zhuanlan.zhihu.com/p/357973435