SKILL DETAIL
setup-multiplayer-services
unity-technologies/skills/setup-multiplayer-services
This skill guides the development of online multiplayer experiences where players connect, group, and interact in real-time using Unity Multiplayer Services. It is used when the user asks for topology choice, player grouping, hosting, matchmaking, discovery, network setup, and session-based play (rooms, parties, lobbies) using the Unity Multiplayer Services APIs. The skill prioritizes implementing against Unity.Services.Multiplayer using IMultiplayerService and ISession, and provides a curated documentation map and reference order to help developers choose the appropriate APIs for their tasks. For dedicated game servers, it offers guidance on Unity.Services.Multiplayer.Server. Underlying service clients (such as Lobbies, Matchmaker, Relay) are used only when primary APIs are insufficient or when the user explicitly requests those namespaces.
Installation
npx skills add https://github.com/unity-technologies/skills --skill setup-multiplayer-services
Skill files
SKILL.md
Last synced · Sep 13, 2026
references/dgs-entrypoint.md›
## Table of Contents
- [Overview](#overview)
- [Build and assembly constraints](#build-and-assembly-constraints-unity_server)
- [`IMultiplayerServerService` capabilities](#imultiplayerserverservice-capabilities)
- [Method signatures](#method-signatures)
- [Matchmaker server extensions](#matchmaker-server-extensions-matchmakerserverextensions)
- [Session options (shared types)](#session-options-shared-types)
- [Errors](#errors)
## Overview
Dedicated Game Server (DGS) session entrypoints live in the **`Unity.Services.Multiplayer.Server`** assembly only. They complement the client **`IMultiplayerService`** surface documented in **`entrypoints.md`**.
| Topic | Details |
|--------|---------|
| **Assembly** | **`Unity.Services.Multiplayer.Server`** |
| **Service access** | **`MultiplayerServerService.Instance`** (static) or **`unityServices.GetMultiplayerServerService()`** via **`Unity.Services.Core.UnityServicesExtensions`** after Services initialization on a server build. |
| **Core type** | **`IMultiplayerServerService`** — create and resolve **server** sessions; async methods return **`IServerSession`** (session handle for dedicated server; types from the main **`Unity.Services.Multiplayer`** assembly). |
## Build and assembly constraints (`UNITY_SERVER`)
The **`Unity.Services.Multiplayer.Server`** assembly is compiled only when **`UNITY_SERVER`** or **`ENABLE_UCS_SERVER`** is defined (see the package **`Unity.Services.Multiplayer.Server.asmdef`** **`defineConstraints`**).
Any **game or tool code** that references **`Unity.Services.Multiplayer.Server`** must satisfy one of the following:
| Approach | What to do |
|----------|------------|
| **Scripting define** | Wrap references (types, calls, `using` that pulls server-only APIs) in **`#if UNITY_SERVER`** … **`#endif`** (or a define that implies the same server build), so non-server targets do not compile that code. |
| **Assembly Definition** | In the **`.asmdef`** of the assembly that references **`Unity.Services.Multiplayer.Server`**, set **`defineConstraints`** to include **`UNITY_SERVER`** so the dependent assembly is not built for client-only targets. |
Use one or both so client/player builds never require the Server assembly to be present or linked incorrectly.
## `IMultiplayerServerService` capabilities
| Area | What to use |
|------|-------------|
| **Create session** | **`CreateSessionAsync(SessionOptions)`** — new server session from options. |
| **Create or join by id** | **`CreateSessionAsync(string sessionId, SessionOptions)`** — server session with a chosen session id (create if missing, join if present per SDK behavior). |
| **Create from matchmaker** | **`CreateMatchSessionAsync(string matchId, SessionOptions)`** — server session tied to a Matchmaker match id; uses matchmaker configuration on options when applicable. |
> **`GetSessionAsync`** exists on **`IMultiplayerServerService`** for package-internal use and is **`internal`** in the SDK source; treat the three **`Create*`** methods above as the supported public server entry surface for session creation from game code.
## Method signatures
```csharp
// Creates a new dedicated-server session. Returns IServerSession. Throws SessionException on failure.
Task<IServerSession> CreateSessionAsync(SessionOptions sessionOptions)
// Creates or joins a server session using an explicit session id.
Task<IServerSession> CreateSessionAsync(string sessionId, SessionOptions sessionOptions)
// Creates a server session from a Matchmaker match id and session options.
Task<IServerSession> CreateMatchSessionAsync(string matchId, SessionOptions sessionOptions)
```
## Matchmaker server extensions (`MatchmakerServerExtensions`)
All members below are declared in **`Unity.Services.Multiplayer.Server`** (`MatchmakerServerExtensions`).
```csharp
// Configure backfill behavior on SessionOptions before create/match session.
T WithBackfillingConfiguration<T>(this T options, bool enable, bool automaticallyRemovePlayers,
bool autoStart, int playerConnectionTimeout, int backfillingLoopInterval) where T : SessionOptions
// Start backfilling on a matchmade session (server / session handle).
Task StartBackfillingAsync(this ISession session)
// Stop backfilling on a matchmade session.
Task StopBackfillingAsync(this ISession session)
```
## Session options (shared types)
**`SessionOptions`** and related lobby/network fields are defined in **`Unity.Services.Multiplayer`**, not in the Server assembly. For property tables, fluent **`SessionOptionsExtensions`**, and networking helpers, use **`entrypoints.md`** — apply the same options when calling **`IMultiplayerServerService`** create APIs on dedicated servers.
## Errors
Async methods on **`IMultiplayerServerService`** throw **`SessionException`** on failure (same family as the client **`IMultiplayerService`** session APIs).
references/entrypoints.md›
## Table of Contents
- [Overview](#overview)
- [IMultiplayerService capabilities](#imultiplayerservice-capabilities)
- [Method signatures](#method-signatures)
- [Options reference](#options-reference)
- [Session configuration](#session-configuration-sessionoptions-joinsessionoptions-basesessionoptions)
- [Netcode with session options](#netcode-with-withnetwork-session-options)
- [Networking model](#networking-model-session-side)
- [Host / server session](#host--server-session-ihostsession-iserversession)
- [Matchmaking results](#matchmaking-results-on-a-session)
- [Errors and observation](#errors-and-observation)
- [Editor / glue](#editor--glue-unityservicesmultiplayercomponents)
## Overview
| Topic | Details |
|--------|---------|
| **Service access** | `MultiplayerService.Instance` (static) or `unityServices.GetMultiplayerService()` via `UnityServicesExtensions` after Services initialization. |
| **Core type** | **`ISession`** — session state, players, properties, role (host/member/server), **`Network`** (client), **`LeaveAsync`**, **`ReconnectAsync`**, **`RefreshAsync`**, **`SaveCurrentPlayerDataAsync`**; cast to **`IHostSession`** / **`IServerSession`** when hosting or dedicated server. |
### `IMultiplayerService` capabilities
| Area | What to use |
|------|-------------|
| **Session registry** | `Sessions` (read-only map); events `SessionAdded`, `SessionRemoved`, `AddingSessionStarted`, `AddingSessionFailed`. |
| **Create / join** | `CreateSessionAsync`, `CreateOrJoinSessionAsync`, `JoinSessionByIdAsync`, `JoinSessionByCodeAsync`, `ReconnectToSessionAsync`, `GetJoinedSessionIdsAsync`. |
| **Matchmaking into a session** | `MatchmakeSessionAsync` with **`QuickJoinOptions`** (filters, timeout, optional create) or **`MatchmakerOptions`** (queue, ticket attributes, player properties) + **`SessionOptions`**; optional `CancellationToken` on the `MatchmakerOptions` overload. |
| **Discovery** | `QuerySessionsAsync` + **`QuerySessionsOptions`** (filters, sort, skip/count, continuation token); **`QuerySessionsResults`** may **`StartPolling`** / **`StopPolling`**. |
### Method signatures
```csharp
// Creates a new session. Returns IHostSession (host-side). Throws SessionException on failure.
Task<IHostSession> CreateSessionAsync(SessionOptions sessionOptions)
// Joins session by ID, or creates it if it does not exist.
Task<ISession> CreateOrJoinSessionAsync(string sessionId, SessionOptions sessionOptions)
// Joins an existing session by its ID.
Task<ISession> JoinSessionByIdAsync(string sessionId, JoinSessionOptions sessionOptions = default)
// Joins an existing session via a human-readable join code.
Task<ISession> JoinSessionByCodeAsync(string sessionCode, JoinSessionOptions sessionOptions = default)
// Reconnects to a previously joined session after a disconnect.
Task<ISession> ReconnectToSessionAsync(string sessionId, ReconnectSessionOptions options = default)
// Finds and joins a session using Unity's matchmaker service. Supports cancellation.
Task<ISession> MatchmakeSessionAsync(MatchmakerOptions matchOptions, SessionOptions sessionOptions, CancellationToken cancellationToken = default)
// Finds a session using session filters with retries up to a timeout. Can optionally create a session if none is found.
Task<ISession> MatchmakeSessionAsync(QuickJoinOptions quickJoinOptions, SessionOptions sessionOptions)
// Browses available sessions matching the provided query options.
Task<QuerySessionsResults> QuerySessionsAsync(QuerySessionsOptions queryOptions)
// Returns IDs of all sessions the current player is already part of.
Task<List<string>> GetJoinedSessionIdsAsync()
```
### Options reference
#### `SessionOptions` _(create / create-or-join / matchmake)_
Inherits `BaseSessionOptions`.
| Property | Type | Default | Description |
|---|---|---|---|
| `Name` | `string` | new GUID | Session display name |
| `MaxPlayers` | `int` | `0` | Max players including host. Must be > 0 when creating |
| `IsLocked` | `bool` | `false` | Locked sessions reject new joins |
| `IsPrivate` | `bool` | `false` | Private sessions are hidden from queries and quick-join |
| `Password` | `string` | `null` | 8–64 char password required to join. Not readable back from the session |
| `SessionProperties` | `Dictionary<string, SessionProperty>` | empty | Custom game-specific session properties (e.g. `"map"`). Up to 20 total |
| `Type` | `string` _(from base)_ | new GUID | Client-side key identifying the session type |
| `PlayerProperties` | `Dictionary<string, PlayerProperty>` _(from base)_ | empty | Per-player properties (e.g. `"role"`). Up to 10 per player |
Fluent extensions (on `SessionOptionsExtensions`): `.WithRelayNetwork()`, `.WithDirectNetwork()`, `.WithDistributedAuthorityNetwork()`, `.WithNetworkHandler()`, `.WithHostMigration()`, `.WithPlayerName()`
---
#### `JoinSessionOptions` _(join by ID / join by code / quick-join fallback)_
Inherits `BaseSessionOptions`.
| Property | Type | Default | Description |
|---|---|---|---|
| `Password` | `string` | `null` | Password required if the session is password-protected |
| `Type` | `string` _(from base)_ | new GUID | Client-side session type key |
| `PlayerProperties` | `Dictionary<string, PlayerProperty>` _(from base)_ | empty | Per-player properties |
---
#### `ReconnectSessionOptions` _(reconnect)_
| Property | Type | Default | Description |
|---|---|---|---|
| `Type` | `string` | new GUID | Client-side session type key |
Fluent: `.WithNetworkHandler(INetworkHandler)` — disables default NGO/NfE integration.
---
#### `MatchmakerOptions` _(matchmake via Unity Matchmaker)_
| Property | Type | Default | Description |
|---|---|---|---|
| `QueueName` | `string` | `null` | Name of the Matchmaker queue |
| `TicketAttributes` | `Dictionary<string, object>` | empty | Attributes sent with the matchmaking ticket |
| `PlayerProperties` | `Dictionary<string, PlayerProperty>` | empty | Per-player properties forwarded to matchmaker |
---
#### `QuickJoinOptions` _(matchmake via filters)_
| Property | Type | Default | Description |
|---|---|---|---|
| `Filters` | `List<FilterOption>` | empty | Filters a session must satisfy to be joined |
| `Timeout` | `TimeSpan` | default | How long to retry before giving up and optionally creating a new session |
| `CreateSession` | `bool` | `false` | Create a new session if none is found within the timeout |
> Do not set `Timeout` unless explicitly requested.
---
#### `QuerySessionsOptions` _(query)_
| Property | Type | Default | Description |
|---|---|---|---|
| `Count` | `int` | `100` | Max results to return |
| `Skip` | `int` | `0` | Pagination offset |
| `FilterOptions` | `List<FilterOption>` | empty | Filters to narrow results |
| `SortOptions` | `List<SortOption>` | empty | Sort order for results |
| `ContinuationToken` | `string` | `null` | Token for fetching the next page |
---
#### `FilterOption` _(used in `QuickJoinOptions` and `QuerySessionsOptions`)_
Constructor: `FilterOption(FilterField field, string value, FilterOperation operation)`
| Enum | Values |
|------|--------|
| **`FilterField`** | `MaxPlayers`, `AvailableSlots`, `Name`, `Created` (RFC3339), `LastUpdated` (RFC3339), `IsLocked`, `HasPassword`, `StringIndex1–5`, `NumberIndex1–5` |
| **`FilterOperation`** | `Contains` _(Name only)_, `Equal`, `NotEqual`, `Less`, `LessOrEqual`, `Greater`, `GreaterOrEqual` |
---
#### `SortOption` _(used in `QuerySessionsOptions`)_
Constructor: `SortOption(SortOrder order, SortField field)`
| Enum | Values |
|------|--------|
| **`SortOrder`** | `Ascending`, `Descending` |
| **`SortField`** | `Name`, `MaxPlayers`, `AvailableSlots`, `CreationTime`, `LastUpdated`, `Id`, `StringIndex1–5`, `NumberIndex1–5` |
---
#### `AddingSessionOptions` _(event payload — read-only)_
| Property | Type | Description |
|---|---|---|
| `Type` | `string` | The session type passed to the create/join call |
---
### Session configuration (`SessionOptions`, `JoinSessionOptions`, `BaseSessionOptions`)
| Topic | Details |
|--------|---------|
| **Lobby-like fields** | Max players, name, password, locked/private flags, typed **`Type`**, **session** and **player** properties with **`VisibilityPropertyOptions`** (Public / Member / Private) and indexed slots (**`PropertyIndex`**) for query filters. |
| **Networking** (`SessionOptionsExtensions`) | **`WithRelayNetwork`**, **`WithDirectNetwork`** (listen/publish IP/port or **`DirectNetworkOptions`**), **`WithNetworkOptions`** (e.g. **`RelayProtocol`**), **`WithNetworkHandler`** for custom **`INetworkHandler`**. |
| **Host migration** | **`WithHostMigration`** + **`IMigrationDataHandler`**; on **`IHostSession`**: **`GetHostMigrationDataAsync`** / **`SetHostMigrationDataAsync`**. |
| **Player name** | **`WithPlayerName`** (visibility). |
| **Matchmaker backfill** | **`MatchmakerServerExtensions.WithBackfillingConfiguration`** on **`SessionOptions`**; on matchmade **`ISession`**: **`StartBackfillingAsync`** / **`StopBackfillingAsync`**. See **`llms.txt`** and package docs for hosting constraints. |
### Netcode with `With*Network*` session options
| Condition | Behavior |
|-----------|----------|
| **`SessionOptionsExtensions`** include gameplay networking (**`WithRelayNetwork`**, **`WithDirectNetwork`**, **`WithNetworkOptions`**, **`WithNetworkHandler`**, …) | **create / join / matchmake / reconnect** bring up **NGO** or **NFE** as configured—no separate Netcode start for that path. |
### Networking model (session side)
| Surface | Role |
|---------|------|
| **`IHostSessionNetwork`** | **`StartDirectNetworkAsync`**, **`StartRelayNetworkAsync`**, **`StopNetworkAsync`**; state and failure events; **`INetworkHandler`**. |
| **`IClientSessionNetwork`** | Client **`NetworkState`** and events; **`NetworkHandler`**. |
| **`NetworkConfiguration`** | UTP endpoints and Relay server data; **`NetworkType`**: Direct, Relay, **DistributedAuthority**; **`NetworkRole`**: Client, Server, Host. |
### Matchmaking results on a session
| API | Use when |
|-----|----------|
| **`MatchmakerExtensions.GetMatchmakingResults(ISession)`** | Stored matchmaking results are needed after a matchmade session exists. |
### Errors and observation
All async methods on **`IMultiplayerService`** throw **`SessionException`** on failure; **`SessionException`** exposes a specific session error type and message.
| Type | Role |
|------|------|
| **`SessionException`** / **`SessionError`** | Session and composed flows. |
| **`SessionObserver`** | Watch add/fail events for a given session **type**. |
### Editor / glue (`Unity.Services.Multiplayer.Components`)
| Item | Role |
|------|------|
| **`MultiplayerSession`** (ScriptableObject) | Holds **`ISession`** and UnityEvent groups (lifecycle, session, players). |
| **`SessionConnector`** / **`SessionConnectorBehaviour`** | Create or create-or-join flows (e.g. on sign-in). |
references/examples.md›
## Examples: user-facing language
These illustrate **User-facing questions and explanations** in [implementation-fit.md](implementation-fit.md). They are for prose to the user, not for code or file edits (those may use real API names).
### Clarifying questions
**Bad (SDK / product vocabulary):**
- "Do you want to use **Lobby** for the server list, or **Sessions** only?"
- "Should we call **`QuerySessionsAsync`** or **`MatchmakeSessionAsync`**?"
- "Do you need **Relay** or is **direct** fine?"
**Good (game / product terms):**
- "Should players **see a list of open games** and pick one, or **join with a code or invite** only?"
- "Should matchmaking be **automatic** (the game finds opponents for you) or **manual** (players choose a room)?"
- "When two players are on different home networks, is **mediated connectivity** (no open ports on a router) a requirement?"
### Explanations and plans
**Bad (splitting named backend products):**
- "We'll use **Lobby** for metadata, **Relay** for NAT traversal, and **Matchmaker** for ranked."
- "**Sessions** wraps **Lobby** so you don't need **Lobby** directly."
**Good (plain language, same ideas):**
- "We'll keep **room metadata** (map, rules) in one place, use **brokered connectivity** when direct links are unreliable, and **automatic pairing** for ranked."
- "The **main multiplayer package API** can own **room state and joins** so you don't add a second room system on top."
### When the user already named a product
If they wrote e.g. "we're on **Relay** already," you may **mirror their wording** in discussion; still avoid **extra** product enumeration they did not ask for.
references/implementation-fit.md›
## Implementation fit: clarify multiplayer requirements
Before recommending architecture or APIs internally, the agent **must** ground advice in the right product choices for *this* application. Map answers to [entrypoints.md](entrypoints.md) and the **Priority: Multiplayer Sessions first** section in [SKILL.md](../SKILL.md) only **after** requirements are clear (from context, project, or user). For concrete phrasing samples, see [examples.md](examples.md).
**How to obtain requirements (in order):**
1. **Conversation and task context** — Use stated goals (e.g. "2-player co-op", "ranked 5v5", "mobile", "host leaves often").
2. **Project state when available** — Inspect the workspace (e.g. `Packages/manifest.json` for Netcode / multiplayer packages, existing multiplayer or networking scripts, platform settings) and align recommendations with what is already chosen.
3. **Ask the user** — If a dimension below would **change** the recommended approach and is not inferable from (1) or (2), ask a **short, targeted** question instead of assuming. Follow **User-facing questions and explanations** below.
### User-facing questions and explanations
- **Clarifying questions** must stay **high level**: player count, how people **find or join** a game, who **runs** the match (e.g. one player's machine vs a dedicated machine), fairness/latency expectations, disconnect/reconnect and "host leaves" behavior, target platforms, and which **Unity networking stack** the project already uses **only if** the user has brought it up or it is visible in the project. Phrase questions in **game / product** terms.
- **Do not** name or ask about Unity **product or service** implementations in questions: e.g. avoid the terms **Sessions**, **Lobby**, **Matchmaker**, **Relay**, and avoid prompting with **API or type names** (`ISession`, `QuerySessionsAsync`, etc.). The user should not need SDK vocabulary to answer.
- In **explanations, summaries, and plans** addressed to the user (outside of code blocks and file edits), **do not mention** Lobby, Matchmaker, Relay, or Multiplayer **Sessions** as named products, and **do not** contrast or enumerate those **underlying services**—unless the **user explicitly** asked about them by name or asked for that level of SDK/architecture detail. Use plain language (e.g. "list of open games", "automatic pairing", "brokered connectivity when direct player-to-player links are unreliable", "the main Unity multiplayer package API") when a concept must be described.
- **Code, API references, and file contents** may use the exact types, namespaces, and methods from this skill and from `llms.txt` as needed for a correct implementation.
### Dimensions to consider
- **Player count and topology** — Players per match and rough scale (many small matches vs few large ones). Whether the simulation can run on a **host client** (often with mediated connectivity) or needs a **dedicated server** / server-authoritative hosting story. *Internal mapping:* relay vs direct listen/publish, host vs dedicated server roles, capacity limits on the multiplayer entrypoint APIs.
- **Casual vs competitive** — Tolerance for **host-based authority** and latency variance vs need for **stricter authority, consistency, and fairness** (often favoring dedicated servers and careful netcode choices). Informs how strongly to push dedicated hosting, tick/interpolation choices, and cheat-sensitive design (without duplicating full anti-cheat guidance here).
- **Discovery and how matches form** — Join codes or invites vs **browsing a list** of open games vs **automatic pairing**; visibility and filterable game metadata. *Internal mapping:* query/list flows, quick-join-style filters, ticket/queue flows; session properties and indexes as needed.
- **Connection model and resilience** — **NAT / home networks** (need for mediated connectivity vs published listen addresses), **reconnect** after disconnects, and **moving the host** without ending the match. *Internal mapping:* relay vs direct network options, `ReconnectAsync`, host migration hooks, network start/stop.
- **Platform constraints** — Targets (e.g. **mobile** dropouts and backgrounding, **console** networking and certification expectations) that affect match lifetime, reconnect UX, and viable connection patterns.
- **Team skills and codebase stack** — **Netcode for GameObjects** vs **Netcode for Entities** (or other networking) must match packages and patterns already in the project; prefer extending the stack in `manifest.json` and existing code rather than introducing a parallel net model without an explicit user request.
references/underlying-services.md›
## Underlying services (use only when necessary)
**Agent-only reference** for implementation when the primary API is insufficient or the user explicitly requested these—**do not** surface this table or product names to the user unless they asked for them.
Summarized for reference—not the default path:
| Area | Namespace | Role |
|------|-----------|------|
| **Lobby** | `Unity.Services.Lobbies` | Standalone lobby CRUD, query, realtime lobby events, migration payloads—prefer **Sessions** unless you need lobby-only workflows. |
| **Matchmaker** | `Unity.Services.Matchmaker` | Low-level tickets, backfill ticket APIs, ticket status—prefer **`MatchmakeSessionAsync`** + **`MatchmakerOptions`** on **`IMultiplayerService`** first. |
| **Relay** | `Unity.Services.Relay` | Raw allocations and join codes—prefer **`WithRelayNetwork`** / **`StartRelayNetworkAsync`** on the session network first. |references/workflows-prerequisites.md›
## Workflow prerequisites (packages and cloud setup)
**Agent-only sanity check** before recommending a path: match the user's **intent** to **dependencies** and **live services / deployment** (see **`llms.txt`** install, init, deployment, and tutorial pages for authoritative steps). Package IDs can vary slightly by Unity/editor version—verify in Package Manager or docs when implementing.
**Which workflow applies** must be **inferred** when possible from **conversation context** and **project state** (e.g. `Packages/manifest.json`, server vs client build targets, existing multiplayer scripts, deployment assets). If more than one row in the table could fit and the choice **changes** prerequisites or APIs, **ask the user** with **high-level** questions (see **User-facing questions and explanations** in [implementation-fit.md](implementation-fit.md)), not by naming product rows from this table. This aligns with **Implementation fit** in [implementation-fit.md](implementation-fit.md): infer first, then clarify if ambiguous.
Unity Gaming Services **initialization** and **authentication** are required for all workflows.
| Workflow (what the product is doing) | Typically required |
|--------------------------------------|-------------------|
| Rooms / join-in-progress **without** starting the session **gameplay network** (metadata, codes, lists, properties only) | `com.unity.services.multiplayer`. **No** Netcode gameplay package required unless they add a custom **`INetworkHandler`** or later start **`StartRelayNetworkAsync`** / **`StartDirectNetworkAsync`**. |
| **Gameplay** simulation synced over the session **Network** (host/client or server roles with Relay or direct transport) | **Exactly one** gameplay stack: **NGO** — `com.unity.netcode.gameobjects` **or** **NFE** — `com.unity.netcode.entities` (Netcode for Entities). Integrate transport with session network APIs per Unity's session + Netcode guides; do not assume both stacks. |
| **Quick join** (filter-based auto pick / create) | Session **type** and **indexed** properties for filters; **`QuickJoinOptions`** in code. |
| **Ticket matchmaking** into a **player-hosted** match | A deployed **Matchmaker queue (MMQ)** (name matches **`MatchmakerOptions`**), Matchmaker **environment** / dashboard setup, and authenticated players. |
| **Ticket matchmaking** with a **dedicated game server (DGS)** | **MMQ** configured for the **DGS / server allocation** flow, a **server build** and **hosting** setup (e.g. Game Server Hosting / Multiplay—see **`llms.txt`** hosting and deployment topics), server process using the **server** session role where applicable, and often **`WithBackfillingConfiguration`** + **`StartBackfillingAsync`** / **`StopBackfillingAsync`** when refilling player slots on an existing allocation. |
| **Editor wiring** with **`MultiplayerSession`** / **`SessionConnector`** | Same multiplayer package (components assembly **`Unity.Services.Multiplayer.Components`**); still subject to the Netcode row above if gameplay networking is used. |
| **Deploying** Matchmaker queues or Multiplayer assets from the Editor | Unity **Deployment** window / deployment docs under **`llms.txt`** (queue, environment, multiplayer config) so cloud resources exist before code calls into them. |
SKILL.md›
---
name: setup-multiplayer-services
description: >-
Guides the development of online multiplayer experiences where players connect, group, and interact in real-time using Unity Multiplayer Services.
Use when the user asks for topology choice, player grouping, hosting, matchmaking, discovery, network setup,
and session-based play (rooms, parties, lobbies) using the Unity Multiplayer Services APIs.
Not for leaderboards, cloud saves, or backend features that involve no real-time connection
between players; those belong to the build-live-game skill.
---
# Multiplayer SDK (Unity Multiplayer Services)
## Instructions
1. **Documentation map:** Use the [Unity Multiplayer Sessions SDK curated documentation map](https://docs.unity.com/en-us/mps-sdk/llms.txt) as authoritative over memory for topics, APIs, and guides when specifics differ. Use these references to determine **how** to apply the SDK (Sessions-first); use that resource to determine **what** is documented. **Never** mention the `llms.txt` filename to the user. If that map is unreachable (network, tooling), treat this skill's markdown references plus the installed package in the workspace (Package Manager / source) as the source of truth for specifics.
2. **Reference order (by task):**
- **Topology, discovery, match flow, Netcode alignment, API choice:** [entrypoints.md](references/entrypoints.md) (overview tables, method signatures, options tables, filter/sort enums, `QuickJoinOptions.Timeout`, errors) → [implementation-fit.md](references/implementation-fit.md) → [examples.md](references/examples.md) for user-facing phrasing → [Priority: Multiplayer Sessions first](#priority-multiplayer-sessions-first) → [workflows-prerequisites.md](references/workflows-prerequisites.md) for extra depth.
- **Dedicated game server (`Unity.Services.Multiplayer.Server`):** [dgs-entrypoint.md](references/dgs-entrypoint.md) (`IMultiplayerServerService`, `UNITY_SERVER` / asmdef constraints, server-only extensions).
- **Lower-level service clients:** [underlying-services.md](references/underlying-services.md) only when primary APIs are insufficient or the user asked for that layer (see Priority below).
## Priority: Multiplayer Sessions first
When the task is **choosing** topology, discovery, match flow, or Netcode alignment—not only calling APIs—ground recommendations via [implementation-fit.md](references/implementation-fit.md) (conversation → project → short targeted questions).
**Primary path:** Implement against **`Unity.Services.Multiplayer`** using **`IMultiplayerService` / `MultiplayerService.Instance`** and **`ISession`** (surface summary in [entrypoints.md](references/entrypoints.md)); keep composed flows consistent with `llms.txt`.
**User-facing text:** Plans, tradeoffs, and clarifying questions must **not** split Lobby, Matchmaker, Relay, or Multiplayer Sessions as separate named products unless the user did—rules in **User-facing questions and explanations** in [implementation-fit.md](references/implementation-fit.md), samples in [examples.md](references/examples.md). Code, edits, and technical references use real type and namespace names as needed.
**Underlying clients** (`Unity.Services.Lobbies`, `Unity.Services.Matchmaker`, `Unity.Services.Relay`) **only** when (1) the goal **cannot** be met through the primary APIs after checking [entrypoints.md](references/entrypoints.md), or (2) the user **explicitly** asked for those namespaces or products. Do **not** default implementations there.
## Additional resources
Read from this entrypoint only; links are one level under this skill folder (no `references/index.md` or README hub).
- **[implementation-fit.md](references/implementation-fit.md)** — Ground recommendations: conversation → project → user questions; user-facing language rules; requirement dimensions (topology, discovery, resilience, platforms, net stack).
- **[examples.md](references/examples.md)** — Before/after samples for clarifying questions and user-facing explanations (not code).
- **[entrypoints.md](references/entrypoints.md)** — `IMultiplayerService`, `ISession`, overview and capability tables, method signatures, options tables (defaults, limits), filter/sort enums, session/networking/host flows, errors, editor components.
- **[dgs-entrypoint.md](references/dgs-entrypoint.md)** — Dedicated server: `Unity.Services.Multiplayer.Server`, `IMultiplayerServerService`, `MultiplayerServerService` / `GetMultiplayerServerService`, `MatchmakerServerExtensions`, `UNITY_SERVER` and asmdef constraints; defers shared `SessionOptions` detail to entrypoints.
- **[workflows-prerequisites.md](references/workflows-prerequisites.md)** — Package and cloud prerequisites by workflow (tables).
- **[underlying-services.md](references/underlying-services.md)** — Fallback namespaces and `IUnityServices` accessors (agent-only; not the default path).