Skip to content

网络联机

信息同步

  • 网络同步 = 实时的多端数据同步+实时的多端表现

协议

  • 实时游戏(FPS、MOBA):倾向于使用 UDP,因为低延迟和高性能是关键要求。开发者通常在 UDP 之上实现自定义的可靠性和数据顺序机制,以优化特定游戏的网络通信。
  • 非实时游戏:可能优先选择TCP,因为数据的完整性和顺序比延迟更重要。
  • 混合使用TCP和UDP:一些游戏会同时使用TCP和UDP来处理不同的通信需求,例如,使用TCP处理登录、聊天和交易,而使用UDP处理实时游戏状态的更新

状态同步

  • 通过开发服务端程序,把用户的操作作为输入实时上传到服务端,服务端通过计算返回结果给各个客户端,这样的过程就是状态同步。

问题及解决

  • 延迟过大、客户端性能浪费、服务端压力大
  • 带宽的浪费

帧同步

  • 仅传递一些操作、事件信息,关于游戏的具体状况以及渲染交给客户端自己完成,客户端处理渲染画面外还要负责游戏逻辑的计算
  • 帧同步的战斗逻辑在客户端,服务端只转发操作,不做任何逻辑处理。
  • 当客户端收到指令后执行本地代码,如果输入的指令一致,计算的过程一致,那么计算的结果肯定是一致的,这样就能保证所有客户端的同步,这就是帧同步。
  • img

问题及解决

  • 帧同步战斗逻辑都在客户端,服务器没有验证,带来的问题就是外挂的产生(加速、透视、自动瞄准、数据修改等)
  • 网络条件较差的客户端会影响其他玩家的游戏体验。(优化方案:乐观帧锁定、渲染与逻辑帧分离、客户端预执行、指令流水线化、操作回滚等)
  • 不同机器浮点数精度问题、容器排序不确定性、RPC时序、随机数值计算不统一(容易造成游戏状态不统一)
  • 乐观锁:每次Interval时钟发生时固定将操作广播给所有用户,不依赖具体每个玩家是否有操作更新
  • 传统的帧同步方案通常采用"锁步"机制。在这种机制下,每个客户端必须在进入下一帧之前等待所有玩家的操作被确认。这种方法简单直接,可以确保所有玩家的游戏状态完全同步,但主要缺点是对网络要求较高,任何玩家的网络延迟都会导致所有玩家的游戏体验受到影响
  • 乐观的方法在设计和实现上更为复杂,需要能够处理预测错误导致的状态不一致问题;而传统方案在逻辑上更为简单直接,但以牺牲一定的流畅性为代价。

对比

属性 帧同步(LockStep) 状态同步
确定性 严格确定 允许小误差,定时纠正误差数据
表现与响应速度 传统严格帧锁定要等其他客户端消息全部到达,响应比较慢;乐观帧锁定可以做到本地立刻响应,但是需要回滚的时候,体验就没那么好了 一般会做预测,可以做到立刻响应。不做预测的话,响应时间是一个往返时间(RTT)
带宽与流量 带宽随人数增加而增加,不适合MMO 需要发送各种状态数据,带宽占用比较高。可以通过压缩、裁剪、增量等方式优化。人数较少时候不如帧同步省流量
网络延迟适应性 要求较低的延迟。如果延迟较高,所有玩家体验都不好。即使采用乐观帧锁定优化,高延迟下也容易产生卡顿 适应性较高,方便做各种插值优化。当然高延迟下,也容易产生位置突变
开发难度 初期开发减法,框架容易实现,但是后期解决bug和完善系统很困难。比如浮点数、随机数、执行顺序导致计算结果不一致,问题很难排查 框架比较复杂,客户端服务端一套代码,每个功能都需要客户端服务端联调。问题定位比较容易。也会出现时序问题
玩家数量 适合少量的玩家,比如ACT、MOBA 可多可少
跨平台 不适合跨平台,会有浮点数问题,可以用定点数来将误差控制在一个可接受范围,同时可以定时纠正结果 适合。有权威服务器
反外挂 P2P架构不适合反外挂,如果引入战斗服务器来校验各个客户端结果,可以解决常见外挂,但是透视和全图视野防不了 与服务器加入校验机制,可以起到比较好的反外挂效果。但是一样防不了透视外挂
中途加入和断线重连 比较复杂。可以在断线的时候,通过快捷播放服务器同步的帧数据来快速跟上游戏 容易。由于实时记录了各个对象的状态信息,所以重连的时候,直接创建这些对象,并同步信息即可
性能(客户端) 客户端要跑完整逻辑,还要执行渲染逻辑,开销比较大 可以灵活优化,客户端跑较少逻辑
回放(离线) 本身收集了所有玩家的输入信息进行逻辑推进,天然支持回放,且回放文件比较小 可以支持回放,但是逻辑比较复杂,需要不断记录状态信息,同时回放时候需要读取合适的时间。回放文件大
回放(实时) 比较复杂,客户端需要本地对全场状态进行序列化,才能回到目标时间。播完回放后还需要加速追上实时游戏状态 相对容易,可以方便的记录快照信息,并按照录制内容随时播放
#### 状态同步与帧同步的本质区别
- 考虑不同玩家的延迟有所区别
- 帧同步依赖于所有玩家的输入在同一帧中处理和计算。因此,如果任何玩家经历了显著的网络延迟,它将影响所有玩家的游戏体验
- 相应的这也保证了公平性,延迟较大的玩家仍然能正常、公平操作(因此经济游戏如 moba 类型经常使用)
- 保证了较高的同步精度
- 状态同步主要通过服务器来维护和同步游戏状态,服务器定期向所有客户端发送最新的游戏状态。这种方式对个别玩家的网络延迟不太敏感:
- 主导,一个玩家的网络问题对其他人的影响有限
- 同步的精度较低,存在公平性的问题,延迟小的玩家的操作总是更快的得到响应
## 网络同步优化技术

表现优化

  • 插值技术
  • 在状态同步中,由于客户端每次收到的是其他角色的位置信息,为了避免位置突变,客户端会采用插值技术,让表现更平滑,而不是跳帧。
  • 内插值是一种在两个已知数据点之间估算中间值的方法。在游戏中,它主要用于平滑玩家的运动和动画。
  • 外插值是一种在已知数据范围之外估算未知值的方法。在网络游戏中,它被用来预测未来的游戏状态,特别是当网络延迟或抖动时,客户端暂时无法从服务器接收到最新的状态更新。
  • 客户端预测+回滚
  • 预测的目的是让玩家输入后,本地立刻收到反馈,提高游戏体验
  • 回滚是为了保证服务器的权威性
  • 把玩家本地预执行的指令都记录好时间戳并存放到一个Move_Buffer列表里(类似滑动窗口)。在添加了时间戳条件下,收到了一条过时的服务器位置数据。
    • 如果玩家本地预测结果与服务器几乎一致,服务器回复一个ACKMOVE。客户端把Move_Buffer列表中对应数据清除
    • 如果预测结果与服务器不一致:需要本地回滚到服务器指定位置,把错误时刻后面的Move_Buffer列表指令执行一遍