帧同步之从零开始

一直想写一个多人在线游戏,也一直在研究相关的技术。从目前了解到的信息来看,网络游戏的同步方案大部分状况下是:帧同步或状态同步。下面就介绍一下,我对帧同步的一些了解。git

基本概念


什么是帧同步?简化的流程以下图。 github

帧同步

红色箭头:客户端向服务端发送玩家的操做指令。(A-A: 玩家A按下A键)服务器

蓝色箭头:服务器每隔一段时间T,向全部客户端发送当前收集到的客户端指令。网络

帧同步原理就是这么简单:同步玩家的全部操做而非状态(HP、攻击力、位置)。当客户端收到服务端的消息时,进行游戏状态更新,即图中蓝色箭头位置。因此理想状态下,全部客户端的更新都是同步的。由于绘制时间点是统一的,指令也是一致的,那么就是完美的同步了。socket

网络延迟


那么问题来了,若是出现网络延迟怎么办?性能

帧同步

实际渲染时,玩家A将比玩家B更早收到消息,意味着玩家A的设备里角色已经开始动了而玩家B的设备里游戏角色仍是没有反应,即不一样步。若是不做处理,随着网络波动,将会致使游戏进行到必定程度后,玩家A和玩家B是两个不一样的游戏画面。优化

优化方案


其实,影响不一样步的因素有不少,网络延时多是最直观的。下面我列举一下,别人和我本身实践中用到的优化方案。ui

  1. 避免浮点数运算(不一样设备下会出现精度不一致的状况,效应叠加就会“差之毫厘谬以千里”)
  2. 减少每次发包的数据量(网络游戏是频繁通讯的:10-20次/s)
  3. 逻辑帧与渲染帧(不一样设备性能不一,不能将全部游戏的状态更新都放在渲染循环里)
  4. 不一样步的插值优化(网络问题的致使的不一样步,须要优化处理,手段不一)

实践


为了研究帧同步,写了一个TANK.IO。项目后续会更新,如今这个实现并不完美。socket.io

主要的优化操做:spa

  • 避免浮点数运算

    对小数进行有效位数限定。

    export function toFixed(i, precision=3) {
      return +i.toFixed(precision)
    }
    复制代码
  • 利用msgpack压缩数据,socket.io有对应插件

    const
      parser = require('socket.io-msgpack-parser'),
      io = require('socket.io')(3000, {parser})
    复制代码

PS: 不一样步的优化感受不是很好,就不发出来了。能够本地运行一下代码,在局域网下运行,游戏总体还过得去。

参考资料


从《王者荣耀》来聊聊游戏的帧同步

相关文章
相关标签/搜索