Web Engine Docs
Preparing documentation
Use the search bar to quickly find any topic
Preparing documentation
Use the search bar to quickly find any topic
Build real-time multiplayer games with Web Engine's comprehensive networking system powered by Colyseus, featuring automatic state sync, client prediction, and advanced optimization.
Web Engine includes a production-ready multiplayer system built on Colyseus, providing authoritative server architecture, automatic state synchronization, delta compression, client-side prediction, and lag compensation for smooth, responsive networked gameplay.
Networked entities automatically sync position, rotation, and custom state across all clients with delta compression.
Create, join, and leave game rooms with matchmaking, private rooms, and invite codes.
Server validates all game state to prevent cheating. Client-side prediction for responsive gameplay.
Only changed state is sent over the network. Achieves 70-90% bandwidth reduction.
Built on Colyseus with load balancing, horizontal scaling, and connection recovery.
Client prediction, server reconciliation, and lag compensation for fair hit detection.
Web Engine uses an authoritative server architecture where the server is the single source of truth:
┌──────────────┐ Input Packets ┌──────────────────┐│ Client 1 │ ─────────────────────── │ ││ (Predicted) │ │ Game Server ││ │ ◄───────────────────── │ (Authoritative) │└──────────────┘ State Updates │ ││ - Validates all │┌──────────────┐ │ - Runs physics ││ Client 2 │ ◄───────────────────── │ - Manages state ││ (Interpolate)│ └──────────────────┘└──────────────┘Client Prediction → Server Validation → State Broadcast → Reconciliation
Web Engine integrates with Colyseus, a powerful multiplayer framework that provides:
import { NetworkManager } from '@web-engine-dev/core/network';const network = NetworkManager.getInstance();// Connect to server and join/create roomawait network.connectToColyseus('ws://localhost:2567','game_room',{name: 'Player1',avatarId: 'avatar-001'});// Create private roomawait network.createPrivateRoom('game_room', {name: 'Host',avatarId: 'avatar-001'});// Join by invite codeawait network.joinPrivateRoom('ABC123', {name: 'Player2',avatarId: 'avatar-002'});
The networking system supports multiple transport implementations:
Production transport using WebSockets via Colyseus:
// Features:// - Automatic reconnection with exponential backoff// - Room state synchronization// - Binary and JSON message support// - Connection quality monitoring// - Heartbeat/ping systemconst transport = new ColyseusTransport('ws://localhost:2567','game_room',{ name: 'Player1' },{maxReconnectAttempts: 5,baseReconnectDelay: 1000,maxReconnectDelay: 30000,useJitter: true});// Listen for reconnection eventstransport.setReconnectionCallbacks({onReconnecting: (attempt, maxAttempts) => {console.log(`Reconnecting... (${attempt}/${maxAttempts})`);},onReconnected: () => {console.log('Reconnected successfully!');},onReconnectFailed: () => {console.error('Failed to reconnect');}});
In-memory transport for offline play and editor testing:
// Start local session for editor/offline playawait network.startLocalSession('host');// Simulate network conditions for testingnetwork.configureSimulation({latencyMs: 100, // 100ms latencyjitterMs: 20, // ±20ms jitterpacketLoss: 0.02, // 2% packet lossduplicateChance: 0 // No duplication});
Add Networked component to entities that need synchronization:
import { addComponent } from 'bitecs';import { Networked, Transform } from '@web-engine-dev/core';// Mark entity for network synchronizationaddComponent(world, Networked, playerId);addComponent(world, Transform, playerId);// Entity's transform now automatically syncs across all clients// Set network sync propertiesNetworked.ownerId[playerId] = clientId;Networked.authoritative[playerId] = 1;
# Start the multiplayer serverpnpm server# Server runs on ws://localhost:2567
const network = NetworkManager.getInstance();await network.connectToColyseus('ws://localhost:2567','game_room',{ name: 'Player1', avatarId: 'default' });console.log('Connected! Room ID:', network.getRoomId());
// In your game scriptexport default (api) => {return (dt) => {// Only process input for local playerif (!api.network.isLocalPlayer) {return;}// Move local playerconst { move } = api.input;api.controller.move({x: move.x * 5 * dt,y: 0,z: move.y * 5 * dt});};};
The system defines several packet types for different purposes:
enum PacketType {CONNECT = 0, // Initial connection handshakeWELCOME = 1, // Server assigns client IDSTATE_UPDATE = 2, // Entity state synchronizationINPUT = 3, // Player input packetsSPAWN = 4, // Entity spawning (reliable)DESPAWN = 5, // Entity removal (reliable)CHAT = 6, // Chat messagesSDP_OFFER = 7, // WebRTC signaling (P2P)SDP_ANSWER = 8, // WebRTC signaling (P2P)ICE_CANDIDATE = 9, // WebRTC signaling (P2P)SCENE_DATA = 10 // Scene serialization/loading}
// Typical Performance Metrics:// Delta Compression:// - 70-90% bandwidth reduction for entity updates// - O(1) compression with zero allocations// - ~0.5μs per entity compression// Snapshot Interpolation:// - O(log n) binary search for bracketing snapshots// - Smooth 60 FPS rendering from 20 Hz server updates// - 100ms default interpolation delay// Network LOD:// - Reduce update rate by distance// - Can handle 100k+ entities at 60 FPS// - Adaptive precision based on distance// Reliable UDP:// - Automatic retransmission for critical packets// - Sequence number tracking// - ACK/NACK system with packet ordering// Bandwidth:// - ~50-200 bytes per entity per update (with delta compression)// - ~10-20 KB/s for 100 entities at 20 Hz// - Scales linearly with entity count and update rate
Learn how to configure and run the multiplayer server
Deep dive into delta compression and entity sync
Send custom events and remote procedure calls
Implement prediction, reconciliation, and lag compensation
Learning Path
Start with Server Setup to configure your multiplayer server, then learn about State Synchronization to understand how data flows. Move on to Custom Messages for game events, and finish with Latency Handling to create responsive gameplay.