写点什么

13kB JavaScript 实现的 MOBA 游戏网络同步技术

作者:qife
  • 2025-08-07
    福建
  • 本文字数:981 字

    阅读完需:约 3 分钟

13kB JavaScript 实现的 MOBA 游戏网络同步技术

作者 Nicholas Carlini


2020-11-21


连续第三年参加 JS13k 竞赛,目标是用不超过 13kB 的 JavaScript 代码制作游戏。今年的挑战是开发具有复杂网络功能的多人游戏——一个精简版 MOBA(多人在线战术竞技游戏)。


点击此处播放游戏 | 源代码

核心目标

选择 MOBA 类型因其具备:


  • 实时交互需求(支持多玩家与非玩家角色协同)

  • 对网络延迟的容忍度(相比 FPS 游戏更宽松)

  • 适中的对象数量(约 100 个活动单位)

网络同步方案

基础方案的问题

初始采用每 100ms 同步全量状态的方式,在 5FPS 更新频率和 200ms 延迟下会出现明显卡顿:


// 服务端基础逻辑class MovingBlock {    constructor() { this.position = ZERO; }    update(dt) { this.position = this.position.add(NewVector(dt,0,0)); }}
复制代码

优化方案:运动预测

改为传输运动函数而非离散坐标:


function linear_move_withtime(start_pos, end_pos, rate, start_time) {    return cur_time =>         start_pos.lerp(end_pos,            clamp((cur_time - start_time)/duration, 0, 1))}
复制代码


优势:


  1. 带宽降低 90%(仅方向变化时通信)

  2. 客户端可 60FPS 平滑插值

  3. 规避 TCP 顺序传输导致的卡顿

技术实现细节

增量状态同步

服务端通过差异检测仅发送变更属性:


var delta = Object.keys(state).reduce((diff, key) => {    if (JSON.stringify(state[key]) === JSON.stringify(last_state[key])) return diff    return {...diff, [key]: state[key]}}, {})
复制代码

函数序列化

通过特殊标记实现函数网络传输:


{    _function: "linear_move_withtime",    args: [[0,0,0], [5,0,0], 3, 0]}
复制代码

客户端预测

本地立即响应移动指令,再同步服务端确认:


// 客户端直接执行移动player.move(target);// 异步通知其他客户端socket.emit('move', target);
复制代码

典型问题与解决方案

  1. 时间不同步

  2. 通过服务端定期 ping-pong 校准各客户端时钟

  3. 循环引用

  4. 对象引用改为 UID 关联:


   A={id:"A", target: {id:"B"}}
复制代码


  1. ID 冲突

  2. 改用服务端单调递增 ID 生成器

性能数据

  • 网络负载:平均 10kB/s(百个对象+多玩家场景)

  • 服务端频率:5FPS 基础更新

  • 客户端表现:60FPS 流畅渲染

游戏元素实现

在剩余 6kB 空间内实现:


  • 太空主题地图(复用星云粒子系统)

  • 单位 AI 行为树(移动/攻击决策)

  • 塔防机制(固定位置高伤害单位)


体验完整游戏 | 研究源代码更多精彩内容 请关注我的个人公众号 公众号(办公 AI 智能小助手)公众号二维码


办公AI智能小助手


用户头像

qife

关注

还未添加个人签名 2021-05-19 加入

还未添加个人简介

评论

发布
暂无评论
13kB JavaScript实现的MOBA游戏网络同步技术_JavaScript_qife_InfoQ写作社区