How should I Send a Player Disconnected Message to Remaining Connected Clients?

When a connected client calls StopClient, I see in the console of my host player a "[MLAPI] Disconnect Event From… " message.

My intention was to listen for that event on the server/host, and then broadcast that message via RPC to the remaining connected clients, along with the disconnecting player ID so remaining connected players can clean up various UI and objects related to the now disconnected player.

However, when I try
NetworkManager.Singleton.OnClientDisconnectCallback += PlayerDisconnectClientRpc,

I start the server/host, and connect Client A and Client B, then when Client B disconnects,
After the Disconnect Event I get a NullReferenceException: Could not get NetworkObject for the NetworkBehaviour. Are you missing a NetworkObject component? error on the server/host,

Client A console shows a Trying to destroy object [client B ID] but it doesn’t seem to exist anymore! warning,

The script is attached to the same gameObject with the MLAPI NetworkManager component (it’s actually the HelloWorldManager from the MLAPI example), And the only logic in the Rpc method is a Debug.Log(“Player DC”); statement for testing.

Am I approaching this correctly, and just implementing the messages incorrectly? Or should I be looking at some other synced variable or event to have the server let other players know when and who disconnects?

After further testing I believe I resolved this, the main issue seems to be that the script component where I was calling the ClientRpc from did not have an MLAPI NetworkObject component attached to it. It did have the MLAPI NetworkManager attached to it, which doesn’t allow you to also have a NetworkObject component attached at the same time.

To resolve all of this, I moved the script component that was sending the ClientRpc to a different object in the scene, and attached a MLAPI Network Object component to it. Now, whenever any non host client disconnects, all other players are notified via Rpc which client disconnected.

Hey! I have recently got into the same problem and here is something that I think will be useful for you.

First of all, there is a difference between NetworkObjectId and the clientId that is passed in the OnClientDisconnectCallback function. That’s because MLAPI gives player objects NetworkObjectId, which can be assigned to network objects aswell (NPCs, mobs, etc.) and clientId, which is unique ID ONLY for players. For example if you have multiple network objects in your game, if you try the following:
Debug.Log(NetworkObjectId) and Debug.Log(NetworkManager.Singleton.LocalClientId)
the output will most likely be different, because in the first case you get the unique network object id, and in the second case you get the unique PLAYER ONLY id.

I think your get that null exception, because you try to take the networkObjectId of the disconnected client, which is no longer there. The only thing you have access to is the clientId, that is passed in the callback function.

The second thing I could advice you, the NetworkManager callbacks are invoked ONLY on the server. I do not advice you to assign ClientRpc to the callback function. Better create a function (it will be executed on the server), and from this function call ClientRpc in order to tell the clients that the player with “clientId” has disconnected and then you can do whatever you want with it.

I hope I explained it as good as I can.

1 Like

Thanks for the input! I did find that there is a difference between the networkObjectId and the clientId when joining and removing connected players and spawning objects on the server, in my test case though I wasn’t using either Id in any logic, only a Debug.Log statement here and there. But the console error really led me to believe that MLAPI needs a network object component on anything that also wants to use Rpc’s, and I guess by design you can’t have an object with both the NetworkManager and the NetworkObject components simulateously.

I’ll use your suggestion about subscribing a non-Rpc method to the callback though, that seems like a better way to do what I’m aiming for!

You are right any script which wants to use RPCs must be on a GameObject with a NetworkObject component. In addition you can only put RPC functions on scripts deriving from NetworkBehaviour and not on regular MonoBehaviours.

Thank you for the verification @luke-unity ! Double checking the documentation I see it is also expressed clearly on the NetworkObject page, however the various RPC related pages do not explicitly mention that requirement. If I could make a suggestion, it would be to request whoever adds to the documentation to include this fundamental information on those pages as well!