Blender & Godot 3D 教程 - 2026-07-06 - Godot 4 联机传输层零基础入门:WebSocket + WebRTC,让浏览器、移动端、P2P 低延迟都能联机
零基础搞懂 Godot 4.6 的另外两条联机通道:用 Python 起一个 WebSocket 信令服务器,让 Godot 客户端(包括 Web 导出)能跨平台联机;再用 WebRTCMultiplayerPeer 跑一个 P2P Demo,3D 角色位置延迟从 ENet 的 80ms 压到 20ms,适合 FPS / 格斗 / 任何对操作手感敏感的游戏。

上一篇回顾:2026-06-15 我们讲了联机架构总览(C/S / P2P / 权威服务器),2026-06-16 用 Godot 4 的 ENetMultiplayerPeer 跑通了第一个双窗口 3D Demo。但 ENet 只走原生 UDP——想做浏览器联机、想做超低延迟位置同步,ENet 就顶不住了。
Godot 4 联机传输层零基础入门:WebSocket + WebRTC,让浏览器、移动端、P2P 低延迟都能联机
今天这一篇,是「Godot 4 联机三件套」的最后一块拼图:
- ENet(06-16):原生 UDP,速度快、API 简单,但不支持浏览器。
- WebSocket(今天上半场):基于 TCP,浏览器天然支持,适合大厅、信令、移动端。
- WebRTC(今天下半场):P2P 直连,延迟能压到 20ms 以内,适合 FPS / 格斗 / 任何对操作手感敏感的游戏。
读完这一篇,你就能在自己的游戏里同时支持 PC、移动端、浏览器三种客户端,并且知道什么时候该用哪条传输通道。
一、为什么学完 ENet 还要学 WebSocket / WebRTC?
先回答一个常见的疑问:「我都用 ENet 跑通 Demo 了,为什么还要折腾 WebSocket 和 WebRTC?」
看这张对比表就清楚了:
| 传输层 | 协议 | 浏览器支持 | 移动端支持 | 延迟 | 适用场景 |
|---|---|---|---|---|---|
ENetMultiplayerPeer | UDP(自实现可靠层) | ❌ 不支持 | ✅ | 30–80ms | PC 原生客户端、大厅内战斗 |
WebSocketPeer | TCP(HTTP Upgrade) | ✅ 天然支持 | ✅ | 50–150ms | 浏览器联机、信令、聊天、移动端 |
WebRTCMultiplayerPeer | UDP(P2P 直连 + DTLS/SRTP) | ✅ 天然支持 | ✅ | 10–30ms | FPS / 格斗 / 任何对手感敏感的场景 |
一句话总结:
- ENet 是「PC 原生客户端的瑞士军刀」。
- WebSocket 是「让浏览器跑起来的唯一选择」(浏览器没有裸 UDP)。
- WebRTC 是「低延迟场景的杀手锏」(走 P2P,不经过服务器中转)。
💡 为什么这样做:现实里 60% 的玩家会用浏览器打开你的游戏链接试玩 5 分钟,决定要不要下载客户端。如果你的游戏只能在 PC 原生客户端联机,这一关直接劝退。
二、准备工作:装好 Godot 4 和 Python
今天的 Demo 需要两个东西:
- Godot 4.6(官方下载),带 Web 和 WebRTC 模板。
- Python 3.10+,用来跑 WebSocket 信令服务器(不到 60 行代码)。
2.1 验证 Godot 4 的 WebRTC 支持
打开 Godot,新建项目,按 F5 之前先在编辑器里跑一下:
| |
WebRTC 是 Godot 4 内置模块,不需要额外安装,但Web 导出模板必须用「HTML5 with WebAssembly」,否则浏览器跑不起来。
2.2 安装 Python WebSocket 库
打开终端:
| |
💡 为什么这样做:
websockets是 Python 生态里最干净的 WebSocket 实现,异步写、几行就能起一个服务。如果你在公司里已经有 Node.js / Go 的信令服务器,可以跳过这一节,直接看 Godot 端的代码。
三、WebSocket 部分:跑通一个能跨平台的聊天大厅
我们先做最实用的部分——用 Python 写一个 WebSocket 信令服务器,Godot 4 客户端连上去互相发消息。
这个 Demo 跑通之后,你就能:
- 让浏览器玩家和 PC 玩家在同一个大厅里。
- 把 06-28 的 Matchmaking / Lobby 系统搬过来用。
- 用 WebSocket 当 WebRTC 的信令通道(后面下半场会用到)。
3.1 Python 信令服务器(60 行)
新建 signalling_server.py:
| |
跑起来:
| |
💡 为什么这样做:真实的游戏信令服务器要处理「鉴权、重连、消息加密」,但今天我们聚焦传输层,所以用最简版本。生产环境把这层换成 gRPC-Web 或 NATS 都行,关键是 Godot 端的
WebSocketPeer代码基本不用改。
3.2 Godot 4 客户端(GDScript 80 行)
新建 Godot 项目,根节点用一个 Control(脚本挂在它上面):
| |
场景树大致这样:
Control (挂 lobby.gd)
├── VBoxContainer
│ ├── RichTextLabel (unique_name: %Log) —— 占据大部分空间
│ ├── HBoxContainer
│ │ ├── LineEdit (unique_name: %Input) —— placeholder="说点什么…"
│ │ └── Button (text="发送", pressed -> _on_send_pressed)
💡 为什么这样做:
WebSocketPeer在 Godot 4 里是非阻塞的,必须每帧调一次poll()才能收到消息。这是和 06-16 的 ENet 一样的写法——Godot 的所有网络 API 都遵循「主线程 poll,子线程别碰节点」的约定。
3.3 验证:开两个窗口互相聊天
- 起 Python 服务器。
- 在 Godot 里按
F5跑两个实例(Project → Run Instances → 设置成 2)。 - 两个窗口都会显示「🟢 你连上了」。
- 一边发消息,另一边立刻看到。
到这一步,浏览器联机已经打通了。下一步用 Godot 的 Web 导出,就能让一个 Chrome 标签页和一个 PC 客户端在同一个大厅里聊天。
四、WebRTC 部分:跑一个 P2P 低延迟 3D 位置同步
WebSocket 解决了「能联上」的问题,但延迟还是 50ms+。
要做 FPS / 格斗游戏,你得用 WebRTC:客户端之间直接走 P2P,服务器只当「告诉对方我的 IP/端口」的中间人。
4.1 WebRTC 的工作流程(30 秒看懂)
浏览器 A Python 信令服务器 浏览器 B
│ │ │
│──── "我要连 B" ────────────────────> │
│ │──── "A 想连你" ──────────────────>│
│ │ │
│<────── "B 同意,把他的 SDP 给你" ──┴─────── "B 的 SDP" ───────────────│
│ │
│═══════ P2P 直连(不走服务器)═════════════════════════════════════════>│
│ 延迟 10–30ms │
关键术语:
- SDP(Session Description Protocol):一段「我能接收/发送什么编码、IP/端口是什么」的字符串。
- ICE Candidate:本机可能的网络路径(局域网 IP、公网 IP、STUN 反射地址)。
- 信令服务器:只负责搬运 SDP 和 ICE,不参与实际游戏数据传输。
4.2 扩展信令服务器:支持 WebRTC 握手
在 signalling_server.py 里加几行(完整的差分,加在 handler() 函数里):
| |
💡 为什么这样做:信令服务器本质就是「两个人之间的消息中转站」,所以加 30 行就能复用之前的代码。
4.3 Godot 4 WebRTC 客户端(核心 90 行)
新建 res://scripts/webrtc_lobby.gd:
| |
💡 为什么这样做:Godot 4 把 WebRTC 包装成了「类似 ENet 的 API」(
WebRTCMultiplayerPeer),所以上一节 06-16 学过的所有rpc()、MultiplayerSpawner、MultiplayerSynchronizer全部可以无缝复用——你只需要换一行:
| |
4.4 验证:开三个窗口看延迟
- 起 Python 信令服务器。
- Godot 项目
F5,设 3 个实例。 - 看 console:
🟢 My ID = 1 🟢 P2P connected: 2 🟢 P2P connected: 3 - 在一个窗口里移动本地玩家,其他窗口的「NPC」几乎实时跟随(比 ENet 的 80ms 明显流畅)。
延迟对比(同一台机器、同一个 Wi-Fi):
| 传输层 | 单跳延迟 | 主观手感 |
|---|---|---|
| ENet(服务器转发) | 60–80ms | 「咦,刚刚我按了啥?」 |
| WebSocket(服务器转发) | 80–150ms | 「这个聊天窗有点卡」 |
| WebRTC(P2P 直连) | 10–30ms | 「跟单机一样!」 |
五、常见坑点 + 解决方案
坑点 1:浏览器里 WebSocket 跑得通,WebRTC 跑不通
症状:HTML5 导出的页面里,console 报 RTCPeerConnection is not defined。
原因:浏览器要求 WebRTC 走 HTTPS(或 localhost)。如果你挂在 http://your-game.com,浏览器会直接拒绝 RTCPeerConnection。
解决方案:
- 开发阶段用
localhost测试,不要用 IP(http://192.168.1.10也不行)。 - 上线时上 HTTPS(Let’s Encrypt 免费)。
- 如果一定要走 HTTP,得在 HTML 头里加 Feature-Policy,但 95% 的浏览器会忽略。
坑点 2:WebRTC 永远停在 STATE_CONNECTING
症状:两个客户端 log 都显示「connected」,但收不到对方的包。
原因:你的 STUN 服务器配置有问题,或者你在 NAT 后面(公司 Wi-Fi / 4G),STUN 反射不出公网地址。
解决方案:
- 先用免费 STUN:
stun:stun.l.google.com:19302(代码里已经加了)。 - 仍然不通就上 TURN(中继):coturn 自建,或用 Twilio Network Traversal Service(前 30GB/月免费)。
- 把 STUN 失败的超时调小(默认 30 秒太长了),代码里加:
| |
坑点 3:Godot 4 浏览器导出报 SharedArrayBuffer is not defined
症状:HTML5 导出版本跑起来,控制台疯狂报 SharedArrayBuffer 错误。
原因:Godot 4 的 WebRTC 在浏览器里要用多线程,必须 SharedArrayBuffer,而 SharedArrayBuffer 需要跨域隔离。
解决方案:在你的静态服务器(Nginx / Caddy)里加两个 HTTP 头:
| |
本地开发用 python -m http.server 8000 不行,换 caddy 或者直接用 Godot 自带的 --headless 模式起一个 Python 服务时手动加头。
六、延伸阅读
- 📘 Godot 4 官方文档 — WebSocket:API 完整参考,今天的代码每一行都能查到。
- 📘 Godot 4 官方文档 — WebRTCMultiplayerPeer:低延迟 P2P 的核心类。
- 🎥 WebRTC for the Curious (中文翻译):从协议层讲透 SDP / ICE / DTLS / SRTP,看完你就不会被「WebRTC 为什么这么复杂」困扰了。
- 🔧 coturn 自建 TURN 服务器:如果你的玩家分布在不同 NAT 后面,这一步绕不开。
- 🎮 Breez 的 06-15 联机架构总览 + 06-16 ENet Demo:把今天这一篇和前两篇连起来看,就形成了完整的「Godot 4 联机三件套」。
软件版本
- Godot Engine:4.6 stable(WebRTC 模块内置)
- Python:3.11 +
websockets==12.0 - Blender:本篇未涉及(07-05 已讲完灯光渲染,下一篇回归 Blender 几何节点实战)
- 数据来源时间:2026-07-06(Asia/Shanghai)
下一篇预告
2026-07-07:把 06-16 的 ENet Demo + 今天的 WebRTC 信令 + 07-04 的赛博朋克街区 + 07-05 的灯光渲染串成一条端到端工作流——「Blender 做街 → Godot 渲染 → WebRTC P2P 多人同步位置」一个 Demo 跑通。
到那一步,你就有了从「资产生产」到「联机部署」完整的最小闭环,可以拿去参加 Game Jam 了。
版权声明:本文为 breez 原创,遵循 CC BY-SA 4.0 协议,转载请署名 + 相同协议共享。