Quick answer: Add the Multiplayer plugin to your project, connect to a signaling server, have one player create a room (host) and others join it (peers). The host runs the authoritative game simulation and syncs object positions to peers. Use the Multiplayer object’s built-in sync system for object state, handle latency with interpolation, and implement disconnect/host migration logic for robustness.
Adding multiplayer to a Construct 3 game is one of the most rewarding — and most challenging — features you can build. Construct 3’s built-in Multiplayer plugin uses WebRTC for peer-to-peer connections, which means players connect directly to each other without needing a game server. This keeps hosting costs near zero, but it also means you need to understand how peer-to-peer networking works and how to keep game state consistent across all connected players.
Understanding the Architecture
Construct 3’s multiplayer model is host-authoritative peer-to-peer. One player is the host and runs the real game simulation. All other players are peers who send their inputs to the host and receive game state updates back. The signaling server is only used for the initial connection handshake — once players are connected, all game data flows directly between them via WebRTC data channels.
This architecture means:
The host is always right. If there is a conflict between what the host sees and what a peer sees, the host’s version wins. Peers display an interpolated, slightly delayed view of the game.
The host bears the bandwidth cost. Every peer sends input to the host, and the host sends state updates to every peer. With 4 players, the host handles 3 incoming and 3 outgoing connections.
Latency is unavoidable. Peers see the game state as it was a few milliseconds (or more) ago. Your game design needs to accommodate this.
Setting Up the Signaling Connection
Add the Multiplayer object to your project (Insert New Object > Multiplayer). You do not place it on the layout — it is a global plugin. The first step is connecting to a signaling server, which brokers the initial connection between players.
// Connect to the signaling server
// On Start of Layout (lobby layout)
System: On start of layout
→ Multiplayer: Connect to signaling server
"wss://multiplayer.construct.net/signalling"
// Handle connection result
Multiplayer: On connected to signaling server
→ Multiplayer: Log in with PlayerNameInput.Text
Multiplayer: On logged in
→ StatusText: Set text to
"Logged in as: " & Multiplayer.MyAlias
Multiplayer: On signaling error
→ StatusText: Set text to
"Connection failed: " & Multiplayer.ErrorMessage
After logging in, you need room management. The host creates a room and peers join it:
// Host creates a room
Button_Host: On clicked
→ Multiplayer: Create room
RoomNameInput.Text max peers 4
// Peer joins a room
Button_Join: On clicked
→ Multiplayer: Join room
RoomNameInput.Text
// Room events
Multiplayer: On room created
→ StatusText: Set text to "Room created. Waiting for players..."
Multiplayer: On joined room
→ StatusText: Set text to
"Joined room. Host: " & Multiplayer.HostAlias
Multiplayer: On peer connected
→ StatusText: Set text to
Multiplayer.PeerAlias & " joined the game"
Syncing Game Objects
Once players are in a room and you transition to the game layout, you need to sync game objects. The host creates authoritative instances and associates them with peers. Each peer only controls their own input — the host processes everything.
// On start of game layout (HOST ONLY)
Multiplayer: Is host
System: On start of layout
// Create a player object for each connected peer
→ System: Create object Player at (100, 300)
→ Player: Set instance variable PeerID to
Multiplayer.MyID
→ Multiplayer: Sync object Player
// Also create a player for each peer
Multiplayer: Is host
Multiplayer: For each peer
→ System: Create object Player at
(100 + loopindex * 80, 300)
→ Player: Set PeerID to
Multiplayer.PeerID
→ Multiplayer: Sync object Player
The sync system automatically replicates the object’s position, angle, and size to all peers. For custom data like health, score, or animation state, you need to send that data explicitly:
// Sync custom data from host to peers
// Send reliable messages for important state changes
System: Every 0.1 seconds
Multiplayer: Is host
→ Multiplayer: Send message
tag "score"
to all peers
message Player.Score
mode reliable ordered
// On the peer side, receive and apply
Multiplayer: On message "score"
→ ScoreText: Set text to
"Score: " & Multiplayer.Message
Handling Input and Latency
Peers send their input to the host rather than directly moving their character. The host processes the input and the result syncs back to all peers. This prevents cheating and keeps the game state consistent.
// Peer sends input to host
Multiplayer: Is NOT host
System: Every tick
→ Multiplayer: Send message
tag "input"
to host
message
Keyboard.IsKeyDown("ArrowLeft") & "," &
Keyboard.IsKeyDown("ArrowRight") & "," &
Keyboard.IsKeyDown("ArrowUp")
mode unreliable
// Host receives and processes peer input
Multiplayer: Is host
Multiplayer: On message "input"
// Parse the input string
→ Player: Pick by comparison
Player.PeerID = Multiplayer.PeerID
// Apply movement based on received input
→ Player: Simulate Platform pressing
Left if tokenat(Multiplayer.Message, 0, ",") = "1"
→ Player: Simulate Platform pressing
Right if tokenat(Multiplayer.Message, 1, ",") = "1"
→ Player: Simulate Platform pressing
Jump if tokenat(Multiplayer.Message, 2, ",") = "1"
Input messages use unreliable mode because they are sent every tick. If one is lost, the next one arrives immediately. Using reliable mode for high-frequency messages creates congestion and increases latency.
The Multiplayer plugin includes built-in client-side interpolation. When enabled, peers see smooth movement for remote players even when updates arrive at irregular intervals. Enable it in the Multiplayer object properties or via events:
// Enable interpolation for smooth remote movement
System: On start of layout
→ Multiplayer: Set interpolation to Enabled
// Interpolation adds a small delay (typically 80-120ms)
// so the client always has two data points to interpolate between.
// This trades a tiny bit of latency for much smoother visuals.
Host Migration and Disconnection
In peer-to-peer games, the host leaving is catastrophic if not handled. You need to detect disconnections and either migrate the host role or end the session gracefully.
// Handle peer disconnection (on host)
Multiplayer: Is host
Multiplayer: On peer disconnected
// Remove their player object
→ Player: Pick by comparison
Player.PeerID = Multiplayer.PeerID
→ Player: Destroy
→ Multiplayer: Send message
tag "player-left"
to all peers
message Multiplayer.PeerAlias
mode reliable ordered
// Handle host disconnection (on peer)
Multiplayer: On host disconnected
→ StatusText: Set text to
"Host disconnected. Returning to lobby."
→ System: Wait 2.0 seconds
→ System: Go to layout "Lobby"
For true host migration — where another peer automatically becomes the new host — you need to implement it manually. The Multiplayer plugin does not handle this automatically. The typical approach is to have peers maintain enough game state locally that one can take over the host role:
// Basic host migration strategy
// 1. All peers keep a local copy of critical game state
// 2. On host disconnect, the peer with the lowest ID becomes new host
// 3. New host creates a new room and existing peers rejoin
Multiplayer: On host disconnected
// Check if we should become the new host
// (lowest peer ID among remaining players)
→ System: Set ShouldHost to
true // simplified - compare peer IDs in production
System: ShouldHost = true
→ Multiplayer: Create room
OriginalRoomName & "-migrated" max peers 4
// Restore game state from local copy
// Other peers join the new room name
Performance Tips for Multiplayer
Reduce sync frequency for non-critical objects. Not everything needs to sync every tick. Slowly moving objects or UI elements can sync every 5-10 ticks. Use the Multiplayer object’s bandwidth settings to control update rates.
Use unreliable mode for frequent updates. Position, rotation, and input data should use unreliable mode. Reserve reliable ordered mode for game events like scoring, player death, or chat messages.
Minimize the data you send. Instead of syncing entire object states, send only what changed. Use compact message formats — send a single string with comma-separated values rather than multiple separate messages.
Test with simulated latency. Use your browser’s network throttling tools to simulate high-latency connections during development. A game that feels good at 20ms latency can become unplayable at 150ms if you have not accounted for it.
Related Issues
If the signaling server connection fails, see Fix: Construct 3 Multiplayer Signaling Connection Failed. For AJAX and network-related errors, check Fix: Construct 3 AJAX Request CORS Error. If your game runs well in single player but has low FPS in multiplayer, see Fix: Construct 3 Performance Low FPS Lag. And if save/load breaks after adding multiplayer state, see Fix: Construct 3 Save/Load System Not Restoring State.
Start with two players. Get that working perfectly before adding more.