Skip to content

00 — Overview & Vision

Part of the Lattice networking suite design set. See also: README · 01 High-Level Design · 02 Netcode LLD · 03 Auth Service · 04 Social Library · 05 Engine Integration · 06 Implementation Roadmap


1. Vision & Goals

Lattice is a standalone, engine-agnostic multiplayer networking suite. Its mission is to give game teams Photon-Fusion-class netcode — client-side prediction, server reconciliation/rollback, snapshot interpolation, lag compensation, and predictive "estimated physics for destination" — without locking them into a single engine, a hosted-only backend, or a single authority model.

Goals

  • One core, every engine. A single C++20 implementation (lattice-core) of transport, replication, prediction, and simulation, exposed through a stable C ABI and wrapped idiomatically per engine (Unity, Unreal, Godot, web).
  • Two authority models, first-class. Support server/host-authoritative (prediction + reconciliation/rollback) and shared/distributed authority (per-object ownership, authority transfer, eventual consistency) with the same data model.
  • Topology injected at runtime. The same game/backend simulation code compiles into both the dedicated server and the client (the shared simulation library), so a client can act as a P2P host with byte-for-byte identical logic. Dedicated, listen-server, and P2P-relayed topologies all run the same sim.
  • Own the wire. A custom UDP transport with its own reliability/ordering channels, congestion control, fragmentation, and encryption, plus our own relay for P2P fallback — with an optional QUIC/WebTransport backend for the browser.
  • Photon-Fusion-class performance. 60 Hz fixed sim tick, 20–30 Hz snapshots, ~100 ms interpolation buffer, sub-MTU (~1200 byte) packets, prediction + extrapolation/dead reckoning for smooth destination estimation.
  • Batteries-included backend. A lightweight control plane for authentication, matchmaking/session directory/fleet orchestration, and social — runnable self-hosted or managed.

Non-Goals

  • Not a game engine. Lattice does not render, simulate physics for you, manage scenes, or provide an ECS. It transports and replicates your state and runs your simulation tick.
  • Not an asset backend. No CDN, asset streaming, build pipeline, or content store. (See sibling skills/tools for asset generation; Lattice does not own that.)
  • Not a general-purpose RPC/microservice framework. The control-plane services exist to serve game sessions, not as a generic backend platform.
  • Not a hosted-only product. Managed hosting may exist, but the suite is fully self-hostable; nothing requires a vendor cloud.
  • Not an anti-cheat product. Server authority and signed tokens raise the bar, but Lattice is not a dedicated anti-cheat/anti-tamper solution.

2. The Problem & Audience

Building competitive real-time multiplayer is hard, and today's options force painful trade-offs:

  • Engine-bundled solutions (e.g., Unity Netcode, Unreal replication) tie you to one engine and are awkward to reuse across a multi-platform studio.
  • Vendor netcode (e.g., Photon Fusion/Quantum) delivers excellent prediction/rollback but is largely closed, hosted-leaning, and engine-scoped.
  • Open community libraries (e.g., Mirror, FishNet) are Unity/C#-only and rarely offer prediction + rollback, a custom encrypted transport, relay/NAT traversal, and an integrated backend together.

Lattice solves this by separating netcode from engine and from backend: a portable, encrypted, high-performance C++ core; first-class support for both authority models; and an optional self-hostable control plane — usable identically from Unity, Unreal, Godot, or the web.

Who it's for

  • Multi-engine / multi-platform studios wanting one netcode stack across titles.
  • Competitive / fast-action games needing prediction, rollback, and lag compensation.
  • Sandbox / co-op / social games needing shared authority, ownership transfer, and host migration.
  • Teams that need to self-host for cost, data-residency, or control reasons.

3. The Three Locked Decisions (with Rationale)

3.1 C++20 core + stable C ABI + per-engine bindings

Decision. All netcode lives in lattice-core (C++20), exposed across an extern "C" stable C ABI boundary; each engine gets an idiomatic wrapper (lattice-unity via P/Invoke, lattice-unreal as a UE module, lattice-godot as a GDExtension, lattice-web as WASM).

Rationale. - Write once, ship everywhere. Prediction, rollback, congestion control, and serialization are subtle and expensive to get right. Implementing them once avoids per-engine divergence and bugs. - Native performance & deterministic control. C++20 gives us tight memory layout, no GC pauses in the hot loop, and the determinism control rollback demands. - A C ABI is the universal contract. Unlike C++ name mangling/ABI churn, a flat extern "C" surface is callable from C#, UE, GDExtension, WASM, and beyond — and stays binary-stable across compiler versions. - Idiomatic wrappers keep gameplay engineers happy. The thin per-engine layer maps the C ABI to natural concepts (MonoBehaviours, UObjects, Nodes) so users never touch raw pointers.

3.2 Both authority models are first-class

Decision. Support server/host-authoritative netcode (client prediction + server reconciliation/rollback) and shared/distributed authority (per-object ownership, authority transfer, eventual consistency) within the same engine and data model.

Rationale. - Different games need different authority. Competitive shooters demand strict server authority and lag compensation; sandbox/co-op/social games benefit from distributed ownership and seamless host migration. - One data model, not two stacks. NetworkObject carries an explicit authority/ownership attribute, so the same replication, interest management, and serialization paths serve both modes — and objects can even mix modes within a session. - P2P needs distributed authority anyway. Since a client can act as a host, ownership and authority transfer are intrinsic to the P2P-relayed topology, not bolted on.

3.3 Custom UDP transport + our own relay (optional QUIC/WebTransport for web)

Decision. Build a custom UDP transport that owns reliability/ordering channels, congestion control, fragmentation, and encryption (X25519 + ChaCha20-Poly1305), plus STUN-style reflexive discovery, UDP hole punching, and a TURN-like relay for P2P fallback. Offer an optional QUIC/WebTransport backend for browsers.

Rationale. - Games need channel semantics TCP/QUIC don't expose cleanly. Per-channel reliability and ordering (Unreliable / Unreliable-Sequenced / Reliable-Unordered / Reliable-Ordered) with seq numbers + ACK bitfields (reliable.io style) is the right primitive for snapshots, inputs, and RPCs. - We control latency and congestion. Owning congestion control and packet pacing lets us tune for tick-rate traffic instead of bulk throughput, and keep packets under MTU (~1200 bytes) to avoid IP fragmentation. - NAT is unavoidable. STUN-style discovery + hole punching connects most peers directly; the relay guarantees connectivity when it fails — essential for P2P hosting. - The web can't do raw UDP. A QUIC/WebTransport backend lets the same higher-level netcode reach browsers without compromising the native path.


4. System Context

High-level view of who talks to what. Clients (in any engine) authenticate, get matched/placed by the director, then connect to a game server or a relayed P2P host; social runs alongside.

flowchart TD
    subgraph Clients["Clients / Engines"]
        U["Unity (lattice-unity)"]
        UE["Unreal (lattice-unreal)"]
        G["Godot (lattice-godot)"]
        W["Web (lattice-web, WASM)"]
    end

    subgraph Control["Control Plane (.NET 8)"]
        AUTH["lattice-auth (HTTPS 8443)"]
        DIR["lattice-director (8444): matchmaking, session directory, fleet"]
        SOC["lattice-social (WSS 9443)"]
    end

    subgraph Data["Data Plane (C++)"]
        GS["lattice-gameserver fleet (UDP 27015+)"]
        RLY["lattice-relay (UDP 7777)"]
    end

    subgraph Storage["Storage"]
        PG[("PostgreSQL: accounts, social graph")]
        RDS[("Redis: sessions, presence, pub/sub")]
        NATS[("NATS (optional): messaging")]
    end

    Clients -->|"login, token request"| AUTH
    Clients -->|"matchmake / find session"| DIR
    Clients <-->|"friends, presence, parties"| SOC

    DIR -->|"orchestrate / place"| GS
    DIR -->|"allocate fallback"| RLY

    Clients -->|"encrypted UDP gameplay"| GS
    Clients <-->|"P2P direct or relayed"| RLY

    AUTH --- PG
    SOC --- PG
    DIR --- RDS
    SOC --- RDS
    SOC -.-> NATS
    AUTH -->|"signed token (Ed25519)"| Clients
    GS -->|"validate token"| AUTH

5. Suite Component Map

How the modules relate. lattice-core and the shared game-sim library are the center of gravity; everything else either embeds them, wraps them, or coordinates them.

flowchart LR
    subgraph Core["lattice-core (C++20)"]
        TR["transport (UDP, crypto, congestion)"]
        REL["reliability channels"]
        SER["serialization (quantize, delta)"]
        REP["replication (NetworkObject, AoI, ownership)"]
        PRED["prediction / rollback / reconciliation"]
        SIM["simulation (fixed tick, dead reckoning)"]
        NAT["nat (STUN, hole punch, relay client)"]
        ABI(["extern \"C\" C ABI boundary"])
    end

    GAMESIM["game-sim (shared simulation library)"]

    subgraph Bindings["Engine Bindings"]
        BU["lattice-unity (P/Invoke C#)"]
        BUE["lattice-unreal (UE module)"]
        BG["lattice-godot (GDExtension)"]
        BW["lattice-web (WASM + QUIC/WebTransport)"]
    end

    subgraph DataPlane["Data-plane binaries"]
        GS2["lattice-gameserver"]
        RLY2["lattice-relay"]
    end

    subgraph ControlPlane["Control plane (.NET 8)"]
        A2["lattice-auth"]
        D2["lattice-director"]
        S2["lattice-social"]
    end

    TR --- REL --- SER --- REP --- PRED --- SIM
    NAT --- TR
    Core --> ABI
    ABI --> BU
    ABI --> BUE
    ABI --> BG
    ABI --> BW

    GAMESIM -->|"compiled into"| GS2
    GAMESIM -->|"compiled into (P2P host)"| BU
    Core -->|"linked by"| GS2
    Core -->|"client of"| RLY2

    D2 -->|"places / orchestrates"| GS2
    D2 -->|"allocates"| RLY2
    A2 -->|"tokens validated by"| GS2
    S2 -.->|"presence / invites"| Bindings

6. Glossary

Term Meaning in Lattice
Tick One step of the fixed-rate simulation loop (default 60 Hz). All game logic advances per tick; ticks are numbered and used to align inputs, snapshots, and rollback.
Snapshot A serialized view of replicated state at a given tick, sent to clients at 20–30 Hz (typically delta-compressed against a previously acked snapshot).
Prediction The client simulates the local player's (and sometimes others') state ahead of confirmed server state to hide latency, using buffered inputs.
Rollback On receiving authoritative state that disagrees with prediction, the client rewinds to the confirmed tick and re-simulates forward applying stored inputs.
Reconciliation The process of correcting predicted state against the server's authoritative snapshot (rollback + re-simulate), ideally invisible to the player.
Interpolation Smoothly displaying remote entities slightly in the past (default ~100 ms buffer) between received snapshots to mask jitter and packet loss.
Extrapolation / Dead Reckoning Estimating an entity's near-future position from its last known state + velocity (and inputs) when fresh data is missing — the "estimated physics for destination".
AoI / Interest Management Area-of-Interest filtering: each client is sent only the objects relevant to it (by distance, visibility, or grid cell), bounding bandwidth and CPU.
Authority Which peer is allowed to decide an object's state. Modes: server/host-authoritative or shared/distributed (per object).
Ownership Which peer currently controls/inputs an object; under distributed authority, ownership can be transferred between peers (authority transfer).
Relay Our TURN-like lattice-relay server that forwards packets between peers when direct P2P (hole punching) fails — guarantees connectivity for P2P hosts.
STUN Reflexive-discovery technique: a peer asks a server what its public IP:port looks like, enabling NAT traversal / hole punching (STUN endpoint on UDP 3478).
Host Migration When the current host/owner leaves, transferring authority of objects (and the session) to another peer so play continues without a full disconnect.
NetworkObject The unit of replication: an addressable networked entity carrying an id, owner, authority mode, and replicated/predicted fields.
RPC Remote Procedure Call: a one-off networked method invocation (client→server, server→client, or owner-scoped), routed over an appropriate reliability channel.
Delta Compression Sending only the fields that changed since a baseline (last acked snapshot) instead of full state, dramatically reducing bandwidth.
Quantization Packing values into the minimum bits needed (e.g., bounded positions, compressed quaternions) to shrink packets while keeping acceptable precision.

7. Competitive Comparison

How Lattice positions against established options. (Cells reflect typical/headline capabilities, not exhaustive feature lists.)

Dimension Lattice Photon Fusion Mirror FishNet
Core language C++20 core + C ABi; bindings (C#, UE, GDScript/C++, WASM) C# (Unity) C# (Unity) C# (Unity)
Engines / topologies Unity, Unreal, Godot, Web; dedicated, listen-server, P2P-relayed Unity; dedicated/host/shared/client Unity; server + listen-host Unity; server + listen-host
Authority models Server/host and shared/distributed (per-object), first-class Host/server and shared (per-mode) Server-authoritative Server-authoritative (+ client-auth options)
Prediction / rollback Yes — client prediction + reconciliation/rollback + lag comp Yes (Fusion's headline strength) Limited / community add-ons Yes — built-in prediction/reconciliation
Interest management Yes — AoI/grid + per-client filtering Yes (area of interest) Yes (interest mgmt/spatial) Yes (observers/interest)
Transport Custom encrypted UDP (4 channels) + optional QUIC/WebTransport Photon transport (proprietary) Pluggable (KCP, Telepathy, etc.) Pluggable (Tugboat/UDP, others)
Relay / NAT traversal Own relay + STUN-style discovery + UDP hole punching Photon Cloud relay Via transports / 3rd-party relays Via transports / 3rd-party relays
Social Yes — lattice-social (friends/presence/parties) Via separate Photon products No (out of scope) No (out of scope)
Auth Yes — lattice-auth (Ed25519-signed tokens) Via Photon services / app IDs No (DIY) No (DIY)
Source availability Source-available core + self-hostable backend Closed source, hosted-leaning Open source (MIT) Source-available / free tier

Notes: competitor capabilities evolve; this table captures the headline differentiators that motivate Lattice's design rather than a point-in-time feature audit.


8. A Note on Names

All product and component names used throughout this set — Lattice, lattice-core, lattice-gameserver, lattice-relay, lattice-auth, lattice-director, lattice-social, and the bindings — are working codenames. They are placeholders chosen for clarity and may be renamed before release; doing so changes branding only, not any architecture, interface, or parameter described in these documents.