You can use session management to ensure that when a player disconnects, some data is kept and accurately assigned back to that player when they reconnect.
To reassign data to the right player when they reconnect, we need to link this data to the player.
The clientId generated by Netcode for GameObjects (Netcode) cannot be used, because it generates when a player connects and is disposed of when they disconnect. That ID may then be assigned to a different player if they connect to the server after the first one disconnected.
To properly link data to a specific player, we need an ID that is not tied to the current connection, but persists through time and is unique to that player. Some options include
- A login system with unique player accounts
- A Globally Unique Identifier (GUID). For example, a GUID generated via
System.Guid.NewGuid()and then saved to the
With this unique identifier, we can map each player's data that is needed when reconnecting, such as the current state of their character (last known position, health, etc). We then ensure this data is up to date and kept host side after a player disconnects to properly repopulate that player's data when they reconnect.
You can also decide to clear all data when a session completes or add a timeout to purge the data after a specific amount of time.
Reconnecting players depends on your game. For example, if we use a Player Object, a new
Default Player Prefab automatically spawns when any player connects to the game (including when they reconnect). You can then use the player's previously saved session data to update that object so that its state returns to what it was before disconnecting. In those cases, we would need to keep all the important data that we want to restore and map it to the player using our identification system. This data could be saved when a player disconnects, or updated periodically. We can then use the
OnNetworkSpawn event on the Player Object's
NetworkBehavior(s) to obtain this data and apply it where needed.
In cases where we don't use the Player Object approach and instead manually attribute client ownership to
NetworkObject(s), we could keep the objects that a player owns when they disconnect, and set the reconnected player as their new owner. To accomplish this, the only data we would need to keep would be the mapping between those objects and their owning player's identifier, then when a player reconnects we could use this mapping to set them as the new owner. This mapping can be as simple as a dictionary mapping the player identifier with the
NetworkObjectId(s) of the
NetworkObject(s) they own. Then, in the
OnClientConnectedCallback from the
NetworkManager, the server could set the ownership of these objects.
Here is an example from the Boss Room sample, showing some simple session management. The game uses the Player Object approach and a GUID to identify unique players.
This class allows BossRoom to handle player session data, represented by a struct
T implementing the
ISessionPlayerData interface, by providing mechanisms to initialize, obtain and edit that data, and to associate it to a specific player. It also handles the clearing of data that is no longer used and the reinitialization of data between sessions.
In this case, since game sessions are quite short, the session data is only cleared for disconnected players when a session ends, or if a player leaves before a session starts. This makes sure that if a player disconnects during a session and then reconnects during the next session, the game properly treats it as a new connection. The definition of when a session ends and when a session starts might vary from game to game, but in BossRoom a session is considered to start after character selection and end when the players win or loose the game and enter the post-game scene. In other cases, one might want to add a timeout to session data and clear it after a specified time instead.
This code is in Boss Room's utilities package so it can be easily reused. You can add this package via the
Package Manager window in the Unity Editor by selecting
add from Git URL and adding the following URL: "https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop.git?path=/Packages/com.unity.multiplayer.samples.coop#main"
Or you can directly add this line to your
manifest.json file: "com.unity.multiplayer.samples.coop": "https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop.git?path=/Packages/com.unity.multiplayer.samples.coop#main"