多人联机游戏怎么做_HTML5引擎网络通信基础实现【教程】

19次阅读

websocket 连接失败时 onerror 不触发且 onopen 不执行,主因是服务端未启动或跨域拦截;需手动添加超时判断,并注意开发用 ws://、上线必用 wss://。

多人联机游戏怎么做_HTML5 引擎网络通信基础实现【教程】

WebSocket 连接失败:onerror 不触发,但 onopen 也不执行

这是最常被当成“代码没写错”却卡住的点——实际是服务端没启动或跨域拦截了。HTML5 游戏联机本质靠客户端主动连服务器,不是浏览器自动帮你配好通信链路。

  • WebSocket 实例创建后,状态是 0CONNECTING),但若服务端无响应,它会卡在这儿,既不升到 1OPEN),也不会立刻进 onerror
  • 必须手动加超时判断:
    const ws = new WebSocket('ws://localhost:8080'); let timeout = setTimeout(() => {   if (ws.readyState === WebSocket.CONNECTING) {console.error('WebSocket connection timed out');   } }, 5000);
  • 开发时用 ws:// 协议;上线必须换 wss://,否则 Chrome 会直接拒绝连接(混合内容限制)

消息收发用 JSON.stringify() 还是 ArrayBuffer?

取决于你传的是游戏状态快照,还是高频输入指令。前者可读、易调试;后者省带宽、少解析开销,但写起来容易出错。

  • 玩家移动、射击等操作建议用轻量 JSON:
    ws.send(JSON.stringify({ type: 'input', player: 'p1', action: 'jump'}));
  • 每秒同步 30 帧的位置数据(x/y/rot)时,用 ArrayBuffer + DataView 更稳:
    const buf = new ArrayBuffer(12); const view = new DataView(buf); view.setFloat32(0, x, true); view.setFloat32(4, y, true); view.setFloat32(8, rot, true); ws.send(buf);
  • 别在 onmessage 里直接 JSON.parse(event.data) ——如果服务端发来的是 ArrayBufferevent.data 就不是字符串,会报 Unexpected token

怎么让多个玩家画面同步不卡顿?

不是把所有帧都广播出去就完事。网络延迟、丢包、不同设备渲染帧率不一致,会导致“你看到的我总比实际慢半拍”。

  • 服务端不做权威帧同步(即不每帧校验并重发)的话,客户端得自己做插值:lerp(currentPos, targetPos, 0.1),而不是硬跳到最新位置
  • 客户端预测要开启:收到输入指令后立刻本地执行,再等服务端确认;若确认结果和预测不一致(比如撞墙了),再回滚 + 补偿
  • 别用 setInterval 发送状态——用 requestAnimationFrame 驱动发送逻辑,和渲染节奏对齐,避免“发得太密塞死 WebSocket 缓冲区”

本地测试能连,部署后连不上:CORS 和代理配置漏了哪步?

浏览器不会报 CORS 错误给 WebSocket,它只在 HTTP 握手阶段被拦截,表现就是连接直接关闭,readyState 变成 CLOSED3)。

立即学习 前端免费学习笔记(深入)”;

  • 确保 Nginx 或 Cloudflare 没把 UpgradeConnection 头过滤掉:
    proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
  • 服务端(如 Node.js 的 ws 库)要显式允许来源:new WebSocket.Server({noServer: true}) 配合自定义 upgrade 处理,否则默认只认 *,而现代浏览器要求精确匹配
  • 静态资源走 https://game.example.com,但 WebSocket 写成 ws://game.example.com:8080 ——端口不同就算跨源,必须用 wss:// 且后端同域名反代

真正难的不是连上,是连上之后怎么让两个设备上的小人看起来“同时起跳”。时间戳对齐、RTT 估算、输入延迟补偿……这些没法靠改一两行代码解决,得在每次 onmessage 回调里悄悄做点手脚。

text=ZqhQzanResources