# Details

> Run your Unity Netcode game globally with no code change beyond swapping the transport.

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

Run your Unity Netcode game with no code change other than the transport swap.
Install `com.clutchcall.transport`. It is a replacement for
`com.unity.transport` (UTP). Your **Netcode for GameObjects** or
**Netcode for Entities** project then delivers over a global relay mesh instead
of bare UDP. Your `NetworkManager` / DOTS code stays unchanged. Every Unity
Netcode sample (server-authoritative, client prediction, ECS sync) works after
you swap one prefab.

The transport implements UTP's `INetworkInterface`. Thus `Connect` / `Send` /
`Disconnect` behave the way you expect. Reliable channels map onto **MoQT
subgroup streams**. Unreliable channels map onto **QUIC datagrams**. Peer
discovery uses a namespace subscription on the relay.

> **NOTE:**
> If you build a non-Unity game, or if you want explicit control of the channels,
> use the [Games SDK](/modalities/games/sdk-methods) directly. Use the Unity
> transport when you 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. You want global relay
    delivery, and you do not want to rewrite your networking layer.
  - **UTP-shaped semantics** — You want `Connect`, `Send`, `GetCurrentRtt`, and `MaxPayloadSize` to behave
    like UTP, but 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. You do not operate self-hosted relay servers.
  - **One token, one connection** — The transport authenticates with the same FirstByte token as every other
    modality. It multiplexes over a single QUIC connection.

## Wire model

The transport reproduces UTP's two-channel model on top of the MoQT track
primitive. Internally, 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. Thus **namespace subscription is the natural join/leave
channel**. A client appears in the host's roster the moment it announces. It
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:**
> The unreliable channel is a real **QUIC datagram**. Thus the transport rejects
> payloads larger than the path MTU. It does not fragment them. Query
> `MaxPayloadSize()` for the live datagram budget. Keep snapshot/input deltas
> under it. Send anything larger on the reliable channel.

## Lanes & QoS

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

- **Reliable lane** — a per-peer frame track over **subgroup streams**.
  Delivery is in order, with retransmits. Use this lane for messages that you
  cannot drop.
- **Broadcast lane** — a game-state-style fan-out frame track from the
  authority to all peers. It also uses subgroup streams when you request
  reliability.
- **Unreliable lane** — each frame flagged as datagram travels in a single
  **QUIC DATAGRAM**. There is no head-of-line blocking and no retransmit. The
  latest frame wins. Use this lane for your tick-rate state and input
  snapshots.

Pick the lane the same way as in UTP. Send high-frequency, latest-wins traffic
on the unreliable lane. Keep the reliable lane for low-rate messages that must
arrive.

## ECS racing sample

The Unity-provided
[ECS-Network-Racing-Sample](https://github.com/Unity-Technologies/ECS-Network-Racing-Sample)
runs end-to-end over FirstByte after the transport swap. After you assign
the host and client roles, the `[Server]` / `[Client]` "Go in game" connection
lifecycle completes. Netcode assigns `NetworkId`. Tens of thousands of
datagrams flow through the relay per match. They all use the unreliable lane.
Reliable spawns and RPCs use 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 tests. DOTS environments use a static id registry internally
> (transparent to UTP), because raw GC-handle round-tripping is not available
> there. On Linux, headless players can need the usual Unity native-library shims
> on the runtime library path. The package README documents the exact recipe.

## How it works

You keep your UTP surface. The transport does the rest. Every UTP call forwards
into a shared, language-agnostic star-session layer in C++. Thus the same
host-plus-N-peers shape (reliable + unreliable + discovery) backs any engine
integration, not just Unity. The Unity package is a thin managed wrapper around
that session: a QUIC-datagram pipe plus synthetic UTP endpoints. To integrate a
non-Unity engine, you implement a small set of engine-side hooks: discovery,
RTT, max-datagram, capture-time telemetry, and the datagram-lane mapping. The
rest is reused.

  **Global rooms with no server of your own**

Two players on different continents share one logical room. Neither player
    runs a server. 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. Reliable channels are MoQT
    subgroup streams. Unreliable channels are QUIC datagrams. Both use the same
    connection.

  **Tens of thousands of datagrams per match, no stutter**

A single relay node fans room traffic without GC pauses or lock contention.
    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.
    **Lock-free SPSC / SPMC ring buffers** hand work between stages.

  **Predictable sub-millisecond relay latency under load**

On the relay's data plane, packets move through a **kernel-bypass** NIC
    path. The path steers room traffic into a per-core buffer pool. The engine
    reads and writes frames **zero-copy**, without a syscall per packet. Thus
    processing latency stays predictable, even under load.

  **One token, every modality**

The token that you set in the transport inspector authorizes the QUIC
    session. The same token shape works across every FirstByte modality.
    Thus a title that also uses voice chat or live streaming reuses one
    credential and one connection.

## Related

  - **[SDK methods](/modalities/netcode/sdk-methods)** — This page covers the install, the ClutchCallTransport component, and the
    inspector surface.
  - **[Cookbook](/modalities/netcode/cookbook)** — This page has task snippets: swap UTP, set lanes, read RTT, and run a
    headless server.
  - **[Recipes](/modalities/netcode/recipes)** — This page has end-to-end examples: the ECS racing sample and a headless
    dedicated server.
  - **[Games modality](/modalities/games/details)** — This transport is a UTP shape over the pure-MoQT games modality.
