在浏览器端构建多人 3D 应用时,Three.js 负责高性能渲染,而 SpacetimeDB 的订阅(pub-sub)机制提供权威服务器状态实时同步,避免传统 WebSocket 轮询的复杂性。这种集成特别适合物理模拟和多人互动场景,如游戏或协作编辑器,能实现低延迟的实体位置、旋转和动画同步。
SpacetimeDB 订阅机制核心原理
SpacetimeDB 将游戏逻辑嵌入数据库模块(支持 Rust/TS 等),定义表存储世界状态,如 Player(id、position: Vector3、rotation: Quaternion、velocity),Entity(通用物体)。客户端通过 WebSocket 连接订阅特定查询,例如 tables.player.where(r => r.world_id.eq(currentWorld)),服务器立即推送匹配行作为初始快照,并实时广播 insert/update/delete 更新。
官方文档指出:“Subscriptions replicate database rows to your client in real-time. When you subscribe to a query, SpacetimeDB sends you the matching rows immediately and then pushes updates whenever those rows change。” 这确保客户端本地缓存始终与服务器一致,读取延迟为零。
服务器端使用 reducer 处理输入,如 update_player_input(player_id, input: InputState, timestamp),验证后更新表行,自动触发订阅推送。典型 tick rate 为 1Hz(服务器),客户端输入 20Hz,避免作弊。
客户端集成与 Three.js 场景同步
-
连接与绑定生成
使用 SpacetimeDB CLI 生成 TS 绑定:spacetime generate --lang typescript --out-dir src/generated。在 React/Three.js app 中初始化:import { DbConnection, tables } from './generated/module_bindings'; const conn = DbConnection.builder() .withUri('wss://your-db.spacetimedb.com') .withDatabaseName('multiplayer_game') .build();连接成功后订阅:
ctx.subscriptionBuilder().subscribe([tables.player, tables.entity])。 -
事件回调绑定 Three.js
维护Map<entity_id, THREE.Mesh>,监听行事件:onInsert(ctx, row): 创建 Mesh,设置 position/rotation,从 GLTF 加载模型,加入 scene。onUpdate(ctx, old, new): 更新 mesh.matrixWorld,应用 lerp 平滑:position.lerp(new.position, 0.1)。onDelete(ctx, row): mesh.dispose () 并移除。
示例代码:
conn.db.player.onInsert((ctx, player) => { const mesh = createPlayerMesh(player.class); entityMeshes.set(player.id, mesh); scene.add(mesh); }); -
输入处理与预测
捕获 WASD / 鼠标,立即客户端预测移动(Three.js update),同时调用 reducer 发送输入。服务器确认后 reconciliation:如果偏差 > 阈值(0.5m),瞬移或渐变修正。预测步长:16ms(60fps)。
可落地工程参数与清单
-
订阅优化(减少带宽):
参数 值 说明 空间裁剪 where(r => distance(r.pos, myPos) < 50)仅附近实体,动态更新订阅 分组订阅 全局 (announcements)+ 动态 (shop_items.lte (level)) 避免重叠查询 最大订阅行 500 / 客户端 免费 tier 限,超阈值分页视图 -
同步参数:
场景 lerp alpha 阈值 回滚策略 位置 0.05-0.15 2m 渐变 200ms 旋转 0.1 10° 瞬转 动画状态 0.2 N/A 跨帧混合 -
监控点:
- RTT: <100ms 绿色,>200ms 警告(ping reducer)。
- 订阅活跃:
subscription.isActive()。 - 序列化开销:监控 reducer 调用率,限 100/s。
- 物理: Cannon.js/Ammo.js 客户端模拟,服务器验证速度 <max_vel (10m/s)。
-
部署清单:
- server/lib.rs 定义表 /reducer。
spacetime publish your_module。- 客户端 vite build,托管 Vercel/Netlify。
- 测试:npm run simulate 50 bots。
- 回滚:订阅 fallback 到全表,限玩家数 < 10。
潜在风险与缓解
延迟抖动:用固定 timestep 服务器 tick,客户端缓冲 2-3 帧输入。免费 tier 限 100 并发,使用 paid $25/mo 扩展。浏览器兼容:WebGL2+,polyfill WebSocket。
这种方案已在 Vibe Coding Starter Pack 验证,该项目用 React Three Fiber + SpacetimeDB 实现角色动画多人移动,GitHub star 活跃。
资料来源:
[1] https://github.com/majidmanzarpour/vibe-coding-starter-pack-3d-multiplayer
[2] https://spacetimedb.com/docs/clients/subscriptions/
[3] https://discourse.threejs.org/t/spacetimedb-threejs-support-and-free-tier/90052