You can use session management to keep data when a player disconnects and accurately reassign it to the player when they reconnect.
Linking data to players
To reassign data to the correct player when they reconnect, you need to link this data to the player.
The clientId generated by Netcode for GameObjects (Netcode) can't 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 isn't 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, you can map each player's data (that's needed when reconnecting), such as the current state of their character (last known position, health, and the like). You then ensure this data is up to date and kept host side after a player disconnects to 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.
The best way to reconnect players depends on your game. For example, if you use a Player Object, a new
Default Player Prefab automatically spawns when a player connects to the game (including when they reconnect). You can use the player's earlier saved session data to update that object so that it returns to the same state before disconnecting. In those cases, you would need to keep all the important data that you want to restore and map it to the player using your identification system. You can save this data when a player disconnects or update it periodically. You can then use the
OnNetworkSpawn event on the Player Object's
NetworkBehavior(s) to get 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 can 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 can 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 can 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 Boss Room to handle player session data, represented by a struct
T implementing the
ISessionPlayerData interface, by providing mechanisms to initialize, get and edit that data, and to associate it to a specific player. It also handles the clearing of data that's 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 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 Boss Room, a session starts after character selection and ends when the players 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"