Documentation

Multiplayer

Multiplayer

Competitive multiplayer quickstart guide

Install the competitive quickstart sample to get started with a server-authoritative competitive multiplayer game.
Read time 6 minutesLast updated 2 days ago

This quickstart uses Netcode for GameObjects and the Multiplayer Services SDK to run a server-authoritative 1v1 competitive game against a dedicated server. Players connect by quick-joining a Multiplayer Session that the server creates and publishes. Clients send their gameplay inputs to the server. All gameplay relevant movement is calculated on the server and transmitted to the client. This is the pattern to build on for any game where players compete against each other and client-side cheating (speed hacks, teleports, wallhacks) would ruin the experience.
You can use Multiplayer Play Mode to simulate a dedicated server and two clients locally to test the implementation. Install the sample via the Multiplayer Center to quickly add it to your project.

Required components

When creating a multiplayer game using Netcode for GameObjects, there are some core components that must always be present to enable basic network functionality:
  • NetworkManager: specifies global network settings and must be initialized before any network-related processes can occur (such as spawning objects). The Multiplayer Services SDK starts and configures NetworkManager for you as part of session creation, so you don't call
    NetworkManager.StartServer()
    yourself.
  • Transport: the sample uses the default Unity Transport package, configured for a direct connection, a fixed IP address and port. The client connects directly to the server, rather than using Relay, because a dedicated server has a known, reachable address.
  • Multiplayer Roles: a
    MultiplayerRolesData
    component that tags which scripts and components run in the Server role versus the Client role, so a single project can represent both a dedicated server and a client build.
  • Dedicated Server package: a server build target support so the same project can be built as a headless dedicated server binary.

Set up the project

Unlike the sample's scenes, scripts, and prefabs, a few settings live at the project level and don't update automatically with the imported sample.
Important
It's important that you account for these additional settings, if any of them are missing or incomplete the sample won't work properly.
To ensure your project runs properly complete the following steps before entering Play mode.
  1. Import the Competitive Sample sample through Multiplayer Center
  2. Navigate to Project Settings > Multiplayer > Samples > Competitive Sample to apply the define and set your service account in the Editor.
    1. The Apply all button on the settings page applies the define, roles, and scene list changes for you; the service account fields are saved separately.
  3. Select the Multiplayer Play Mode scenario if it's not already selected and select Play.

NetworkObjects and network prefabs

To synchronize a GameObject over a network so that multiple clients can interact with it, you need to attach a NetworkObject component at the root of the GameObject. The NetworkObject component provides the properties and methods required to manage the GameObject’s state. When you create a GameObject prefab that contains a NetworkObject component, it’s referred to as a network prefab.
Netcode for GameObjects provides other components to manage networked GameObjects, such as NetworkTransform, which synchronizes a GameObject’s Transform, and NetworkBehaviour, which allows you to add network-aware scripts to a GameObject. Refer to the Netcode for GameObjects documentation for a complete list of available components.
The sample's
Player
prefab has a NetworkObject and a NetworkTransform. The Player prefab's NetworkTransform is server-authoritative, meaning only the server writes to it and every client, including the owning client, receives and interpolates the result. A client never moves its own cube directly which prevents player cheating.

Connecting to a multiplayer session

Instead of a single connection script, the sample has one script per role, both living on the persistent
ConnectionSetup
and
NetworkManager
objects in the Bootstrap scene, gated by Multiplayer Roles so only the relevant one runs.
  • ServerConnection
    (server role only) signs in and creates the session. Once signed in, the script creates a session using the server API and a direct network connection
  • ClientConnection
    (client role only) waits for the
    PlayerAuthentication
    component's
    SignedIn
    event, then Quick Joins an existing session; it never creates one.
Setting
CreateSession = false
guarantees a client only ever joins the dedicated server's session and never becomes a host itself if no session is available yet. Refer to Match players for more on quick-join matchmaking.
Both scripts compute a matching
scope
value, the local device ID in the Editor, or
"CompetitiveSample-1v1-{Application.version}"
in a build. Use the scope value as a session property (server) and filter (client), so a client only ever connects to the server it's meant to, rather than any public session that happens to be running.

Loading the game scene

The competitive sample splits a persistent Bootstrap scene, connection and NetworkManager objects that must survive scene loads, from a separate Game scene. Once the dedicated server's session is created, a
NetworkSceneLoader
component network-loads the Game scene through NGO's own scene manager.

Movement scripts

The competitive sample uses server-authoritative click-to-move so a client can never assert its own position, direction, or speed.
PlayerMovement
reads two Input System actions on the owning client only, a
MoveCommand
button (left-click or tap) and a
Point
position, raycasts against the ground, and sends the hit point to the server through an RPC.
The server clamps the requested destination to the arena bounds and the player's current height before accepting it, then moves the object toward that target itself every frame with
Vector3.MoveTowards
. Because the object's NetworkTransform is server-authoritative, writing to
transform.position
on the server replicates the result to every client, which interpolates it. A client can request where it wants to go, but only the server decides if and how it actually gets there.

Multiplayer Services SDK

Note
The Multiplayer Services SDK uses multiple Unity Gaming Services to provide its functionality, which contributes to the billing of those services.
This sample uses the Multiplayer Services SDK from both sides of a client/server split: the server-side API (
MultiplayerServerService
,
ServerAuthenticationService
) to create and authenticate the session, and the client-side API (
MultiplayerService
,
PlayerAuthentication
) to sign in anonymously and quick-join it. Refer to Create a session and Game server hosting support for background on both sides of this API.

Testing

Test the sample with Multiplayer Play Mode using its pre-configured Session (Multiplayer Services) Play mode scenario, which launches the Main Editor in the Server role and two clone Player instances in the Client role. Select it from the drop-down menu next to the Play button and press Play.
The service account you enter under Project Settings > Multiplayer > Samples > Competitive Sample must have the Unity Environments Viewer and Multiplayer Session Details Viewer roles. Without both, the Main Editor instance can authenticate but fails to create or read back the session, and the scenario won't connect the clients. Refer to Create a service account for how to assign roles to a service account.

Modify the quickstart

You can use the competitive quickstart as the basis of your own server-authoritative implementation. When imported via the Multiplayer Center, it's installed as an embedded package. You can either modify the package directly, or copy assets from the package into your project to edit them. Common starting points are raising
MaxPlayers
and the scene's spawn logic beyond 1v1, replacing quick-join with advanced matchmaking for skill-based matches, or adding backfilling so a session refills a slot when a player disconnects mid-match.

Additional resources