multiplayer game dev
Building Real-Time Multiplayer Sync: State Management for Connected Games
Back to Multiplay Guide
Real-Time Sync13 min readReal-time

Building Real-Time Multiplayer Sync: State Management for Connected Games

TR
Tomás Reyes
#state sync#real-time#multiplayer#state management

The hardest problem in multiplayer game development isn't rendering or physics, it's keeping everyone's version of reality in sync. When four players see four different versions of the game world, your multiplayer experience breaks down. Real-time state synchronization is the discipline of making distributed systems feel unified, and it borrows more from distributed databases than you might expect.

This guide covers the practical patterns for keeping game state synchronized across clients, from simple approaches for casual games to production techniques used by AAA studios.

The State Synchronization Problem

At its core, multiplayer sync is a distributed systems problem. You have N clients, each maintaining a local copy of the game state, and they need to agree on a single authoritative version of reality. This is complicated by network latency, packet loss, and the fact that players are generating new inputs constantly.

There are two fundamental approaches: state transfer and input transfer.

State transfer means the server sends the entire (or delta-compressed) game state to every client. The client renders whatever the server tells it to render. This is simpler to implement and more resilient to edge cases, but uses more bandwidth.

Input transfer means the server (or peers) only share player inputs. Every client runs the same deterministic simulation, so given the same inputs, they arrive at the same state. This uses minimal bandwidth but requires perfect determinism, which is harder than it sounds, especially with floating-point math.

Authoritative State: Who Decides?

In most multiplayer games, the server is the authority. It accepts inputs, simulates the game, and tells clients the result. But there's a spectrum of authority:

  • Fully server-authoritative: Server controls everything. Client is just a render terminal. High security, high latency feel. Used in competitive games.
  • Client-authoritative with validation: Client controls its own entity, server validates. Lower latency feel, some cheat risk. Common in cooperative games.
  • Ownership-based: Different entities are authoritative on different clients. The player who "owns" an object controls its state. Good for games with lots of interactive objects.

Implementing Ownership-Based Sync

// Each networked entity has an owner
interface NetworkedEntity {
  id: string;
  ownerId: string;        // Which client is authoritative
  position: Vector3;
  rotation: Quaternion;
  customState: any;
  lastUpdateTick: number;
}

// Only the owner sends updates for this entity
function updateEntity(entity: NetworkedEntity, localPlayerId: string) {
  if (entity.ownerId === localPlayerId) {
    // We're authoritative, send our state
    sendStateUpdate(entity);
  } else {
    // We're not authoritative, interpolate to received state
    interpolateToLastReceived(entity);
  }
}

Conflict Resolution: When States Diverge

No matter how good your sync is, states will diverge. A player picks up an item at the same time on two clients. Two bullets hit simultaneously. A physics object is pushed by two players at once. You need strategies for resolving these conflicts.

The simplest approach: server wins. When there's a conflict, the server's state takes priority. This is predictable and easy to implement. The downside is that it can feel jarring, the client was showing one thing, and suddenly it snaps to something different.

A better approach: priority-based resolution. Assign priorities based on timestamp, player ID, or game logic. The earliest timestamp wins. In case of ties, the lower player ID wins. This is deterministic across all clients.

Practical Sync Patterns for Indie Games

You don't need AAA infrastructure to build multiplayer sync. Here are patterns that work at indie scale:

Snapshot + Interpolation: The server sends full snapshots at 10-20 Hz. Clients interpolate between snapshots. This is simple, robust, and works well for games that aren't frame-precise (casual games, social games, turn-adjacent games).

Reliable Event + Unreliable State: Use reliable delivery (TCP-like) for critical events (player died, item picked up, game state changed) and unreliable delivery (UDP) for continuous state (positions, rotations). This gives you the best of both worlds, important events never get lost, but position updates don't clog the pipe.

Room-Based Isolation: Don't sync the entire world. Divide your game into rooms, instances, or zones. Each room has its own state and its own sync loop. Players in Room A don't receive updates about Room B. This dramatically reduces bandwidth and server load.

Modern Tools and Frameworks

Building sync from scratch is educational but not always practical. Modern tools abstract the hard parts:

  • Photon / Normcore: Managed multiplayer infrastructure with built-in sync primitives.
  • Mirror (Unity): Open-source networking library with automatic state sync.
  • Colyseus: Node.js multiplayer framework with room-based state management.
  • WebSocket + Custom: Roll your own with WebSockets for web-based games.

For developers who want to prototype multiplayer concepts quickly, AI-powered builders like Chatforce can help validate the loop before a team commits to infrastructure. Multiplayer frameworks like Colyseus and Photon solve a different problem: state sync, rooms, transport, and production behavior. Treat the AI builder as the fast concept pass and the networking stack as the engineering decision.

Testing Sync in the Real World

The most important thing about sync testing: never test only on localhost. On localhost, every message arrives in under 1ms with zero packet loss. This tells you nothing about real-world performance.

Use network conditioning tools to simulate real conditions:

  • Add 50-200ms of artificial latency
  • Simulate 1-5% packet loss
  • Test with players in different geographic regions
  • Stress test with the maximum number of concurrent players

Real-world networks are messy. WiFi introduces jitter. Mobile connections drop packets. Players on the other side of the world have 200ms+ ping. Your sync system needs to handle all of this gracefully. Build for the worst case, and the average case will feel great.