How to detect when a disconnection has happened?

  1. Detecting disconnection from Client in the Server

Is there a callback I can listen to?

I know that when a client disconnects, its “NetworkConnection” entity (the one that has a NetworkIdComponent) is destroyed in the Server World. Clearly, Netcode for Entities does detect when a client disconnects. How can my server’s logic detect that too?

I am aware that there is a “proper” way to disconnect with NetworkStreamRequestDisconnect. I don’t want to rely on that, if the client crashes or the player kills the game’s process I want to know that they disconnected.

  1. Detecting disconnection from Server in the Client

What is the appropriate way?

Thank you for your help!

Hey Emma,

Yes, you can track both connections and disconnections via the optional ConnectionState ICleanupComponentData.

“PlayerList” is a new sample showing this feature off, found here: EntityComponentSystemSamples/NetcodeSamples/Assets/Samples/PlayerList at master · Unity-Technologies/EntityComponentSystemSamples · GitHub
This sample uses RPCs to create a “feed” of players who have connected/disconnected.
One other approach (which isn’t demonstrated here) is to implement this behaviour via a static-optimized ghost (with an IBufferElementData containing all connected players).

For this implementation, take a look at the server logic here: EntityComponentSystemSamples/NetcodeSamples/Assets/Samples/PlayerList/ServerPlayerListSystem.cs at master · Unity-Technologies/EntityComponentSystemSamples · GitHub

ConnectionState is added on like 67, where we have a query of all new NetworkStreamConnection entities, where we add the optional component.

New joiners are handled in the HandleNewJoinersJob on line 101. We wait for a client to send an RPC containing their Username. Thus, each client must opt-into being seen in the player list. Obviously, for your own game, you can source usernames however you like. E.g. The GameServer could communicate with a backend instead.

For disconnecting players (regardless of disconnect reason): The NotifyPlayersOfDisconnectsJob job on line 184 will show you the query, and how it’s used to detect disconnects.

The ClientPlayerListSystem:

  • Registers a username with the “PlayerList” sub-system.
  • Receives these “PlayerList” change events.
  • Uses a cache of this data to draw the Player List, and all NOTIFICATIONS (via IMGUI).

You can also use new controls in the “Multiplayer > Window: PlayMode Tools” to test various forms of disconnect. The next few pre-releases will contain improvements to this window.

4 Likes

Nice, this was really helpful.

To continue talk about disconnections, is there a particular reason why ALL ghost entities are automatically destroyed on clients if the server disconnects? Is there a way to keep them, so I can kill the game gracefully? At the moment, because a lot of the visuals are made of ghosted entities, the world disppearing is very jarring, and I don’t particularly want to hard-cut to a fullscreen “connection lost” popup to hide it.

Supporting ‘reconnecting with existing state’ is a non-trivial feature that we simply haven’t had time to build yet. It’s on our radar, but feature-work likely won’t start for a long time. If you need this, you’ll need to roll it yourself via a package fork.

Unfortunately not easily, but again it’s on our radar.

If you only want to keep them (but not reconnect with this cached state), you can probably hack in a thing that prevents those ghosts from succeeding the delete query. My guess (not at PC) is to remove the GhostInstance component when you detect a disconnect.

I’m still not sure what the reason is for deleting ghost entities when disconnected, but removing GhostInstance does the trick. Many thanks!

1 Like

It’s only in case you reconnect. Doing so - with ‘stale’ ghosts already spawned on the client - would confuse netcode and lead to unknown/undefined behaviour.

1 Like