Multiplayer Overview

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.

Key Features#

Automatic State Sync

Networked entities automatically sync position, rotation, and custom state across all clients with delta compression.

Room Management

Create, join, and leave game rooms with matchmaking, private rooms, and invite codes.

Server Authority

Server validates all game state to prevent cheating. Client-side prediction for responsive gameplay.

Delta Compression

Only changed state is sent over the network. Achieves 70-90% bandwidth reduction.

Scalable Architecture

Built on Colyseus with load balancing, horizontal scaling, and connection recovery.

Lag Compensation

Client prediction, server reconciliation, and lag compensation for fair hit detection.

Networking Architecture#

Web Engine uses an authoritative server architecture where the server is the single source of truth:

  • Server (Authority) — Runs the canonical simulation, validates all inputs, and broadcasts state updates.
  • Clients — Send inputs to server, receive state updates, predict local player movement.
  • Transport Layer — WebSocket-based with Colyseus or fallback to local loopback for offline/editor mode.
  • Synchronization — Delta compression, snapshot interpolation, and packet batching for efficiency.
┌──────────────┐ 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

Client-Server Model#

Server Responsibilities#

  • Run authoritative game simulation at fixed tick rate (e.g., 20 Hz)
  • Validate all client inputs (movement, actions, etc.)
  • Process game logic, physics, and AI
  • Broadcast state updates to all connected clients
  • Handle spawning/despawning of networked entities
  • Manage room lifecycle (creation, joining, leaving)

Client Responsibilities#

  • Capture player input and send to server
  • Predict local player movement for responsiveness
  • Receive state updates from server
  • Reconcile predictions with authoritative server state
  • Interpolate remote entities between snapshots
  • Render the game state at 60+ FPS

Colyseus Integration#

Web Engine integrates with Colyseus, a powerful multiplayer framework that provides:

  • Room-based architecture — Each game session is a room with isolated state
  • Schema-based state — Type-safe state synchronization with automatic delta updates
  • Presence system — Track players joining/leaving rooms
  • Matchmaking — Built-in matchmaking and lobby system
  • Monitoring — Web dashboard for monitoring active rooms and connections
  • Scalability — Horizontal scaling across multiple server instances
Connecting to Colyseus Server
typescript
import { NetworkManager } from '@web-engine/core/network';
const network = NetworkManager.getInstance();
// Connect to server and join/create room
await network.connectToColyseus(
'ws://localhost:2567',
'game_room',
{
name: 'Player1',
avatarId: 'avatar-001'
}
);
// Create private room
await network.createPrivateRoom('game_room', {
name: 'Host',
avatarId: 'avatar-001'
});
// Join by invite code
await network.joinPrivateRoom('ABC123', {
name: 'Player2',
avatarId: 'avatar-002'
});

WebSocket & Transport Layer#

The networking system supports multiple transport implementations:

ColyseusTransport#

Production transport using WebSockets via Colyseus:

Colyseus Transport Features
typescript
// Features:
// - Automatic reconnection with exponential backoff
// - Room state synchronization
// - Binary and JSON message support
// - Connection quality monitoring
// - Heartbeat/ping system
const transport = new ColyseusTransport(
'ws://localhost:2567',
'game_room',
{ name: 'Player1' },
{
maxReconnectAttempts: 5,
baseReconnectDelay: 1000,
maxReconnectDelay: 30000,
useJitter: true
}
);
// Listen for reconnection events
transport.setReconnectionCallbacks({
onReconnecting: (attempt, maxAttempts) => {
console.log(`Reconnecting... (${attempt}/${maxAttempts})`);
},
onReconnected: () => {
console.log('Reconnected successfully!');
},
onReconnectFailed: () => {
console.error('Failed to reconnect');
}
});

LocalTransport#

In-memory transport for offline play and editor testing:

Local/Offline Mode
typescript
// Start local session for editor/offline play
await network.startLocalSession('host');
// Simulate network conditions for testing
network.configureSimulation({
latencyMs: 100, // 100ms latency
jitterMs: 20, // ±20ms jitter
packetLoss: 0.02, // 2% packet loss
duplicateChance: 0 // No duplication
});

Quick Start Guide#

1. Mark Entities for Networking#

Add Networked component to entities that need synchronization:

import { addComponent, Networked, NetworkedTransform } from '@web-engine/core';
// Mark entity for network synchronization
addComponent(world, Networked, playerId);
addComponent(world, NetworkedTransform, playerId);
// Entity's transform now automatically syncs across all clients

2. Start the Server#

Terminal
bash
# Start the multiplayer server
pnpm server
# Server runs on ws://localhost:2567

3. Connect from Client#

const network = NetworkManager.getInstance();
await network.connectToColyseus(
'ws://localhost:2567',
'game_room',
{ name: 'Player1', avatarId: 'default' }
);
console.log('Connected! Room ID:', network.getRoomId());

4. Handle Network Authority#

// In your game script
export default (api) => {
return (dt) => {
// Only process input for local player
if (!api.network.isLocalPlayer) {
return;
}
// Move local player
const { move } = api.input;
api.controller.move({
x: move.x * 5 * dt,
y: 0,
z: move.y * 5 * dt
});
};
};

Network Packet Types#

The system defines several packet types for different purposes:

enum PacketType {
CONNECT = 0, // Initial connection handshake
WELCOME = 1, // Server assigns client ID
STATE_UPDATE = 2, // Entity state synchronization
INPUT = 3, // Player input packets
SPAWN = 4, // Entity spawning (reliable)
DESPAWN = 5, // Entity removal (reliable)
CHAT = 6, // Chat messages
SDP_OFFER = 7, // WebRTC signaling (P2P)
SDP_ANSWER = 8, // WebRTC signaling (P2P)
ICE_CANDIDATE = 9, // WebRTC signaling (P2P)
SCENE_DATA = 10 // Scene serialization/loading
}

Performance Characteristics#

// 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

Multiplayer Best Practices#

  • Minimize synced state — Only sync essential data. Derive everything else locally (animations, particles, sounds).
  • Use client prediction — Predict local player movement for instant feedback, reconcile with server.
  • Validate on server — Never trust client input. Always validate moves, actions, and state changes.
  • Handle latency gracefully — Design gameplay that works with 50-200ms latency.
  • Interpolate remote entities — Smooth out network updates with interpolation, not raw state.
  • Test with simulated lag — Use the network simulator to test with realistic latency and packet loss.
  • Monitor connection quality — Show ping, packet loss, and quality indicators to players.
  • Implement reconnection — Handle temporary disconnects gracefully with automatic reconnection.

Next Steps#

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.

Multiplayer Overview | Web Engine Docs