# IGP Unity Multiplayer

`cn.indiegp.sdk.unity.multiplayer` owns the complete Unity multiplayer surface:

- Hosted session bootstrap and lifecycle
- Room, player, team, scene-gate, realtime message/state/RPC APIs
- selectable KCP/TCP reliable and optional raw-UDP unreliable data planes
- network diagnostics and multiplayer C# events
- optional Mirror integration in `IGP.Multiplayer.Mirror`

The `IGP.Multiplayer` assembly depends only on `IGP.UnitySDK`. Mirror is optional; `IGP.Multiplayer.Mirror` is compiled only when the `MIRROR` define is present.

## Scene Setup

```text
IGPRuntimeRoot
├── IGPRuntimeManager
└── IGPMultiplayerRuntime

MirrorNetworkRoot (optional)
├── IGPMirrorTransport
└── Mirror NetworkManager
```

Assign the single project `IGPConfig` to `IGPRuntimeManager`. One call to `IGPRuntimeManager.InitializeAsync()` initializes Multiplayer automatically.

When hosted attach plus Room/Player context becomes valid, `IGPMultiplayerRuntime` requests a descriptor and starts the selected reliable transport without any Mirror call. A successful KCP or TCP authentication is required for `Ready`; UDP starts afterward, is optional, and never falls back to reliable.

Reliable interruption disconnects established Mirror logical connections once, then Multiplayer reacquires the descriptor with `1s, 2s, 5s, 10s, 30s` retry delays. It does not start or restart `Mirror.NetworkManager`.

`ReliableTransportPreference` defaults to `KcpOnly` for upgrade compatibility. Choose `TcpOnly` to require the descriptor's TCP endpoint or `PreferTcp` to try TCP and, after obtaining a fresh descriptor/token, fall back once to KCP. Changing the property does not interrupt an active connection.

```csharp
multiplayer.ReliableTransportPreference = IGPReliableTransportPreference.PreferTcp;
Debug.Log(multiplayer.CurrentReliableTransport); // Kcp, Tcp, or null
```

TCP uses Unity/.NET `System.Net.Sockets.Socket`; the package adds no TCP networking dependency. TCP is plaintext in this release.

`IGPMirrorTransport` sends reliable application frames at `30 Hz` by default. Set `Reliable Send Rate` in the Inspector or `ReliableSendRate` in code to choose a value from `1` to `60`; this setting does not change the reliable transport tick or raw-UDP unreliable sends.

Reserved state and RPC messages are converted before `MessageReceived` is invoked. Read `IGPMessageReceivedEvent.Content` as `StateSetContent`, `StateGetResponseContent`, `StateResetResponseContent`, `RPCCallContent`, or `RPCResponseContent`; custom messages keep their original payload shape. Use `GetValue<T>()` and `GetData<T>()` for game-defined values. Use `RespondRPCAsync` with `RPCCallContent.callerPlayerId` so RoomNode can route the response to the caller.

Runtime events are subscribed in code with `+=` and removed with `-=`. They are not serialized or shown in the Inspector. See the Multiplayer package's [event reference](Documentation~/EVENT-REFERENCE.md) for the maintained list.

See [Documentation~/README.md](Documentation~/README.md) and [MIRROR.md](MIRROR.md).
