# Netcode (Unity) — Details

> Drop-in replacement for com.unity.transport. Run Netcode for GameObjects / Entities over the QUIC + MoQT relay mesh.

<img src="/images/diagrams/netcode.png" alt="netcode data flow" />

The Unity Transport Package (`com.unity.transport`, UTP) is the foundation for
Unity **Netcode for GameObjects** and **Netcode for Entities**. ClutchCall
ships a **drop-in replacement** — `com.clutchcall.transport` — that
implements UTP's `INetworkInterface` but carries traffic over the ClutchCall
relay mesh instead of bare UDP. Reliable and unreliable channels map onto
**MoQT subgroup streams** and **QUIC datagrams**, and peer discovery rides a
namespace subscription on the relay.

This is the **Unity-shaped face of the [Games](/modalities/games/details)
modality**. The games modality gives you `state` / `input` / `event` channels
addressed by track namespace; the Unity transport gives you the same wire model
behind UTP's `Connect` / `Send` / `Disconnect` surface, so every Unity Netcode
sample — server-authoritative, client prediction, ECS sync — works over
ClutchCall by swapping one prefab.

> **NOTE:**
> If you are building a non-Unity game, or want explicit control over the
> channels, use the [Games SDK](/modalities/games/sdk-methods) directly. Reach for
> the Unity transport when you already have a Netcode project and want to keep its
> `NetworkManager` / DOTS code unchanged.

## When to use it

  - **Existing Unity Netcode project** — You have a Netcode for GameObjects / Entities game and want global relay
    delivery without rewriting your networking layer.
  - **UTP-shaped semantics** — You want `Connect`, `Send`, `GetCurrentRtt`, `MaxPayloadSize` to behave like
    UTP — just over a QUIC pipe with reliable + unreliable channels.
  - **Global edge fan-out** — Players connect to the nearest relay POP; the mesh fans state and input
    between regions. No self-hosted relay servers to operate.
  - **One token, one connection** — The transport authenticates with the same ClutchCall token as every other
    modality and multiplexes over a single QUIC connection.

## Wire model

The transport reproduces UTP's two-channel model on top of the MoQT track
primitive. Under the hood the host opens an **authority namespace**; each client
publishes its own **discovery namespace** plus per-peer reliable and broadcast
channels.

| UTP channel | Carried by | Delivery | Use it for |
| ----------- | ---------- | -------- | ---------- |
| **Reliable** | MoQT subgroup stream | ordered, guaranteed | spawns, RPCs, lobby, settlement |
| **Unreliable** | QUIC datagram | lossy, latest-wins | tick snapshots, inputs, transforms |
| **Discovery** | namespace subscribe | event | peer join / leave roster |

The relay forwards a namespace announcement only to sessions that subscribed to
a matching prefix, so **namespace subscription is the natural join/leave
channel** — a client appears in the host's roster the moment it announces, and
disappears when its session drops.

| UTP API | Backed by |
| ------- | --------- |
| `INetworkInterface` | the shared C++ session layer over QUIC + MoQT |
| Reliable + unreliable channels | MoQT subgroup streams + QUIC datagrams |
| Peer discovery | namespace subscribe on the relay |
| `GetCurrentRtt()` | the QUIC transport's smoothed RTT |
| `MaxPayloadSize()` | the negotiated max datagram size |
| capture-time telemetry | a MoQT extension header used for glass-to-glass analytics |

> **TIP:**
> Because the unreliable channel is a real **QUIC datagram**, payloads larger than
> the path MTU are rejected rather than fragmented. Query `MaxPayloadSize()` for
> the live datagram budget and keep snapshot/input deltas under it; spill anything
> larger onto the reliable channel.

## Lanes & QoS

The two UTP channels map to the same QUIC lanes the games modality uses:

- **Reliable lane** — per-peer frame track over **subgroup streams**.
  In-order, retransmitted. This is the fallback for anything you cannot drop.
- **Broadcast lane** — a game-state-style fan-out frame track from the
  authority to all peers, also over subgroup streams when reliability is
  requested.
- **Unreliable lane** — frames flagged as datagram ride a single **QUIC
  DATAGRAM** each: no head-of-line blocking, no retransmit, latest wins. This is
  the lane your tick-rate state and input snapshots should use.

Pick the lane the way you would in UTP: send your high-frequency, latest-wins
traffic unreliable, and reserve reliable for low-rate, must-arrive messages.

## The shared session under the wrapper

Beneath the Unity component sits a **language-agnostic star-session layer** in
C++. The host opens an authority namespace; each client publishes a discovery
namespace plus per-peer reliable and broadcast channels. The session
multiplexes the reliable, broadcast, unreliable, and peer-roster lanes described
above, and is exposed to other languages through a small native FFI surface.
The Unity package is a managed wrapper around that session: a QUIC-datagram pipe
plus synthetic UTP endpoints. Every UTP call forwards into the substrate.

Because that session layer is shared, the same host-plus-N-peers shape (reliable
+ unreliable + discovery) backs any engine integration, not just Unity. If you
are wiring up a non-Unity engine, the integration reduces to a handful of
engine-side hooks — discovery, RTT, max-datagram, capture-time telemetry, and
the datagram-lane mapping — and the rest of the session machinery is reused.

## Architecture

<AccordionGroup>
  <Accordion title="QUIC + MoQT relay mesh" icon="network-wired">
    Every player holds **one QUIC connection** to its nearest relay POP and
    speaks **MoQT** (Media over QUIC Transport) over it. The relay mesh fans
    state and input between regions, so two players on different continents share
    one logical room without either running a server. Reliable channels are MoQT
    subgroup streams; unreliable channels are QUIC datagrams — both ride the
    same connection.
  </Accordion>
  <Accordion title="Shard-per-core relay engine" icon="microchip">
    The relay is a **shard-per-core** (thread-per-core) reactor: each core owns a
    slice of connections with no cross-core locking on the hot path, using
    **lock-free SPSC / SPMC ring buffers** to hand work between stages. This is
    what lets a single relay node fan tens of thousands of datagrams per match
    without GC pauses or lock contention.
  </Accordion>
  <Accordion title="Kernel-bypass NIC fast path" icon="bolt">
    On the relay's data plane, packets move through an **AF_XDP** kernel-bypass
    path: an **eBPF/XSK** program steers room traffic into a per-core **UMEM**,
    and the engine reads/writes frames **zero-copy** without a syscall per
    packet. The result is predictable sub-millisecond relay processing latency
    under load.
  </Accordion>
  <Accordion title="One auth token, all modalities" icon="key">
    The token configured in the transport inspector authorizes the QUIC session.
    The same token shape works across every ClutchCall modality, so a title
    that also uses voice chat or live streaming reuses one credential and one
    connection.
  </Accordion>
</AccordionGroup>

## ECS racing sample

The Unity-provided
[ECS-Network-Racing-Sample](https://github.com/Unity-Technologies/ECS-Network-Racing-Sample)
runs end-to-end over ClutchCall with the transport swap. With the host and
client roles assigned, the `[Server]` / `[Client]` "Go in game" connection
lifecycle completes, `NetworkId` is assigned, and tens of thousands of datagrams
flow through the relay per match — all through the unreliable lane, with reliable
spawns and RPCs on subgroup streams.

## Limitations

> **WARNING:**
> The Unity package targets **Mono and IL2CPP players**. Editor batch-mode
> `World.Update()` does not drive Netcode — you need a **built player** for true
> end-to-end testing. DOTS environments use a static id registry internally
> (transparent to UTP) because raw GC-handle round-tripping is unavailable there.
> On Linux, headless players may need the usual Unity native-library shims on the
> runtime library path; the package README documents the exact recipe.

## Related

  - **[SDK methods](/modalities/netcode/sdk-methods)** — Install, the ClutchCallTransport component, and the inspector surface.
  - **[Cookbook](/modalities/netcode/cookbook)** — Task snippets: swap UTP, set lanes, read RTT, headless server.
  - **[Recipes](/modalities/netcode/recipes)** — End-to-end: ECS racing sample + a headless dedicated server.
  - **[Games modality](/modalities/games/details)** — The pure-MoQT modality this transport is a UTP shape over.
