Tier 2 · Networking

Choosing a netcode stack & Netcode for GameObjects

Pick the stack per project, verify connections, and NGO spawning and serialization rules.

Pick the stack per project, verify connections, and NGO spawning and serialization rules.

UNITY-NETWORKING-IS-PROJECT-SELECTED (HARD — project policy)

Record the actual project's multiplayer requirements and selected stack; never make one project's NGO/DOTS/Mirror choice, transport, topology or service set the default for all Unity projects.

Select and record the network design

  • Reconcile developer-confirmed choices before asking anything. Record player count, supported platforms, online/local modes, join/start/leave flow, topology, authority, stack, transport, backend dependencies and the phase in which each must work. Preserve undecided rows explicitly.
  • Distinguish real networked peers from local bots, pass-and-play and vendor-owned competitions. A single-player prototype can be a visual/rules reference for a multiplayer product; absence of networking in the reference does not cancel the developer's multiplayer requirement.
Choice Meaning Rules to open
No networked multiplayer No gameplay transport/replication requirement Project requirements and relevant local gameplay rules
Netcode for GameObjects GameObject/MonoBehaviour networking selected by this project the NGO rules below
DOTS NetCode ECS networking selected by this project the Netcode for Entities page, the Netcode scale page
Mirror/vendor/custom Selected alternative with its own authority and lifecycle contracts the Mirror page, vendor or project contract
  • Record transport and reachability separately: direct/LAN, relay, dedicated server or other selected deployment. Use the chosen stack's compatible transport; adding a package is not proof peers can connect. Internet/Relay, hosting and identity-provider choices are not inferred solely from selecting a netcode framework.
  • Separate backend responsibilities. Auth identifies players; Lobby groups/configures players; matchmaking finds a group; transport/Relay moves network traffic; netcode replicates gameplay. Install only project-selected services and their required dependencies. For UGS, follow the UGS page and the compatible SDK guidance for the chosen Editor.

Define authority, state and presentation before implementation

  • Declare one authoritative owner for every action and state transition. Validate player identity, permissions, turn/order, legal inputs, timing and rate at that owner. Non-authoritative peers request actions rather than authoring outcomes. The selected stack/topology may vary, but trust and ownership must be explicit before code.
  • Record which state is shared, owner-private or server-only; choose audience, precision and frequency by actual consumers. Do not replicate a hidden hand or secret RNG state to everyone and attempt to hide it only in UI. Apply the selected stack's security/replication rules.
  • Keep deterministic/domain rules independent of UI and transport where practical. Define the action/state/event boundary that netcode adapts; preserve the reference's visible behavior and animation timings without making client animation completion own authority.
  • Specify spawning/despawning, ownership, object registration, scene synchronization, late join, reconnect, disconnect, host loss and session cleanup. Required recovery is project-selected; do not imply lobby host migration also migrates the authoritative game session.
  • For NGO projects, verify the installed com.unity.netcode.gameobjects API and compatible transport, explicitly author NetworkManager/transport/network prefabs, choose scene-management ownership, and use network lifecycle callbacks and correctly owned RPC/state replication. Follow the NGO rules below; do not add a second network stack to solve a wiring gap.

Connect the actual product flow

  • Map reference/product actions to network/service operations: identify, discover/create/join, readiness, connection approval, synchronized match start, gameplay, results, leave/rejoin. Use the same production flow the player operates, with one owner per transition.
  • If live service integration is explicitly deferred, build real typed SDK-backed foundations, configuration, errors, cancellation and cleanup now as requested. Mark them built; integration pending; do not manufacture peers, successful login/join responses or online test evidence. Deferred Auth/Lobby work does not silently remove the gameplay multiplayer requirement.
  • Keep integration status in developer records/tools. Preserve the selected reference UI rather than adding implementation explanations or replacing it with a generic networking sample.

Verify multiplayer at the right tier

  • Resolve/pin compatible packages and prove assemblies compile. For runnable multiplayer, exercise at least two genuinely separate peers with the required host/server/client roles. One process displaying several seats or an Editor-only bot match is not connected-peer evidence.
  • Verify the actual join-to-results flow, matching authoritative state, legal-action rejection, per-player privacy, scene/spawn readiness and duplicate-action handling. Exercise late join, disconnect/rejoin/host loss where required, then confirm complete subscription/session teardown.
  • Add latency/loss, reconnect and capacity measurements when they are part of acceptance or the reported symptom. Capture exact versions, peer identities/roles, configuration, logs and results. Keep direct/LAN proof distinct from Relay/internet/backend proof and target-platform builds.
  • Update the project's feature matrix, ledger and canonical evidence. A package install, compile, lobby room or local preview never substitutes for required live multiplayer verification.

References (verify against installed package versions when implementing): - Unity NGO and Multiplayer Services integration. - Unity Lobby and Relay responsibilities.

Netcode for GameObjects (NGO) — non-DOTS netcode

For DOTS NetCode see the Netcode for Entities page; for Mirror see the Mirror page.

Spawned objects vs app-driven scene flow

See also: the scene flow page - the app & scene flow hub (bootstrap -> load -> transitions/additive -> runtime lifecycle -> teardown).

  • With EnableSceneManagement=false, a dynamically spawned NetworkObject lives in whatever scene was ACTIVE on each peer at spawn time — and dies with it. A client that spawns the object while still in a menu scene, then unloads that scene to follow the match, destroys its own replica: OnNetworkDespawn runs, statics null out, and the game renders default state with NOTHING logged. Replication looks broken; replication was flawless. Fix: OnNetworkSpawn moves the object to the persistent boot scene on EVERY peer (SceneManager.MoveGameObjectToScene) — not DontDestroyOnLoad if the project uses a named persistent scene. (a card game.)
  • With NGO scene sync off, clients must follow the match themselves: subscribe to the spawned object's first replication and drive your own scene flow from it. The host reaching the game scene does nothing for anyone else.

Serialization for structs outside netcode assemblies

  • For an unmanaged struct in an assembly with NO netcode reference (rules kept unit-testable), wrap it: NetworkVariable<ForceNetworkSerializeByMemcpy<T>> and the same wrapper for RPC parameters. Do NOT reach for [GenerateSerializationForType] — it emitted an initializer that threw BadImageFormatException inside NGO's own InitializeOnLoad and took down serialization for EVERY NetworkVariable in the project. (a card game.)
  • Two NetworkPrefabsLists holding the same prefab UNREGISTER it — NGO auto-maintains DefaultNetworkPrefabs.asset; a second list makes a duplicate GlobalObjectIdHash, NGO drops the registration with two WARNINGS, and Spawn silently fails at runtime. Keep only the default list.

Presentation vs authority

  • Animation never gates authority. The authority resolves instantly and appends to an event log; each client replays the log at human speed while every render stays a function of authoritative state MASKED by not-yet-presented events (pending NumberPlaced hides a line card, pending Stay holds the stamp and the banked total). Masks beat replaying state — subtracting pending facts from truth cannot diverge from the engine, and an event-less reconnecting client renders plain truth from cold. Add back-pressure: fast-forward past ~10 queued events, hard-snap past ~25.
  • Authority-side pacing is for DECISIONS, not visuals: bot think delay, human turn timeouts. A lone human should never be timed out (the table waits, as a real one would); arm timeouts only when a rival human is actually waiting.