60Hz Lockstep Tick
固定步长服务端 tick,位置 / 血量 / 技能以 state-diff 增量下发;客户端只负责提交输入与呈现结果。
AsterNova 是一款自建专用服务器 (dedicated game server) 的 2D 多人实时竞技游戏。所有战斗逻辑与状态判定均在 Go 后端运行,前端只负责渲染与输入采集。从协议设计、状态同步算法到 DevOps 部署,整套技术栈独立完成。
针对多人实时同步场景,选用 Go 协程与 WebSocket 二进制协议,把输入、服务端状态和客户端呈现拆成清晰链路。Server-Authoritative 模式让客户端无权篡改命中判定。

03 · LOCKSTEP / WORLD STATE
ONE TICK.
ONE REALITY.
当所有客户端在同一节拍内推进,战场不再只是画面,而是一套可验证、可回放、可扩展的世界状态。
固定步长服务端 tick,位置 / 血量 / 技能以 state-diff 增量下发;客户端只负责提交输入与呈现结果。
客户端零信任。伤害、冷却、命中判定一律服务端裁定 —— 这是 2D 联机最干净的反作弊形态。
entity-component-system 架于 Go channel + select 之上,单机承载 1 个房间、24 在线、零锁。
protobuf 变长编码 + CRC16 校验,帧结构明确,便于调试、重连和异常丢弃。
阿里云 + 腾讯云双区,跨区 WebRTC + TURN 备援;同区 8-15 ms、跨区 80-120 ms。
房间不停服热更新:游戏版本 / 地图 / 技能表在线滚动加载,玩家零感知。
从玩家输入到状态广播的多段管线;每一段都对应明确的状态边界和可观察问题。
同区中位数端到端延迟;方差几乎全部来自 wire 段。
channel 多路 I/O,per-tick 循环零互斥锁。
同种子 + 同输入 → 完全一致的世界状态;回放与作弊取证精确而非近似。
WebSocket 二进制帧载 24-96 字节 payload。下表展示完整 9 段字段布局。
| FIELD | BYTES | NOTE |
|---|---|---|
| magic | 1 B | 帧魔数 0xA7 · 用于同步与乱序检测 |
| version | 1 B | 协议版本 · 双端 mismatch 立即断连 |
| type | 1 B | 帧类型:0x01 input / 0x02 snapshot / 0x03 heartbeat / 0x10 ack |
| flags | 1 B | 位标志:compressed · delta · encrypted |
| seq | 4 B | 32-bit 包序号 · 客户端单调递增 |
| tick | 4 B | 服务端 tick 号 · 0=input 帧,>0=snapshot |
| payload | var | varint 编码 · 长度由 next varint 给出 |
| len | var | payload 长度的 varint 前缀 |
| crc16 | 2 B | CRC-16/CCITT-FALSE · 整个帧除自身外 |
a7 01 01 00 3f 12 00 00 00 00 12 0a 03 1c ff 02 c1 9e
magic=0xA7 · v1 · type=input · seq=0x123f · tick=0 · payload: 上 / 右 / 攻击 · CRC=0x9ec1
a7 01 02 01 40 12 00 00 2a 02 3b a0 0c 18 06 91 ... fc 02 9c 7d
type=snapshot · flags=compressed · seq=0x1240 · tick=42 · zstd delta · CRC 校验通过
a7 01 03 00 00 00 00 00
纯 keepalive · 无 payload · 30 s 周期 · 双向 · 用于 RTT 测量
a7 01 10 00 41 12 00 00 00 00 ff 0d
客户端对服务端 snapshot 的确认 · seq 收到最高序号 · 携带抖动缓冲水位
客户端无权裁定任何关键状态。五条硬规则,下表罗列客户端可做 / 服务端裁定之边界。
用可重复的输入、房间状态和故障演练观察资源曲线、连接质量与 tick 稳定性;页面不把模拟数据包装成线上实时指标。
观察资源曲线是否出现持续爬升、突发尖峰或回收抖动。
关注切换、丢包和重连场景下的连接质量变化。
关注固定步长是否连续,以及客户端是否能平滑追上最新快照。
Five top stack frames from the on-host pprof capture during the 60-minute run. Tick dispatch dominates; jemalloc eliminates GC pauses; snapshot diff keeps per-frame delta small.
TickLoop.dispatch 38.4%World.diffSnapshot 21.7%WSConn.flushBatch 14.2%Room.broadcast 9.8%Arena.resolveHits 6.5%
Go + WebSocket + Godot 4 客户端;CI/CD 流水线搭建
核心 tick 与状态同步完成,围绕输入、判定和呈现验证链路
game.asterforge.top 进入公测,对外开放真实联机体验
完成云端部署迁移与跨区灾备整理,收敛连接和同步边界
接入 pprof 与 Prometheus,为运行状态和异常定位留下记录
cn-hangzhou 主区 / ap-shanghai 热备,无感切换
占点 / 组队模式 + 排位赛 + Steam / WeGame 接入规划
游戏现已在 game.asterforge.top 公测。邀请码 77 体验游客对战。或联系作者定制专属技术方案。