I forgot how to detect player / client / server disconnection. Anyone can tell me?

I must be glossing over something important. In NetworkBehaviour, I see that there are two event methods I can use for detecting disconnection: OnDisconnectFromServer() and OnPlayerDisconnected().

When a network game starts and the client connects to the server, I added the NetworkBehaviour script component containing OnDisconnectFromServer() and OnPlayerDisconnected(). When the client disconnects from the server, however, both the OnDisconnectedFromServer() and OnPlayerDisconnected() event methods did not fire at all.

At the bottom of this Manual article, I found the closest event method related to player/client/server connection and disconnection. But even that event doesn’t fire.

It must be telling me I cannot add new script components at runtime and expect the new script components to call on OnDisconnectFromServer() or OnPlayerDisconnected() methods when the client disconnects from server.

What should I do? What details am I forgetting?

EDIT:

In fact, I don’t even know what Network Manager is doing when it is stopping the connection to disconnect the client from the server. Why is OnPlayerDisconnected() or OnDisconnectedFromServer() not called when connection is stopped for client and server? No Log messages or anything.

EDIT 2:

NetworkManager calls on Destroy() for game objects spawned in with NetworkServer.Spawn() or NetworkServer.SpawnWithClientAuthority(). The game objects with NetworkBehaviours or MonoBehaviours attached will not get a chance to run OnDisconnectFromServer(), OnPlayerDisconnected(), or any On…() event methods. Go for OnDestroy() when using NetworkManager to handle/destroy game objects.

Still, it would be nice to know how to trigger OnDisconnectFromServer() and OnPlayerDisconnected() if the client disconnects from server in UNET. Thread is still relevant and open.

those functions (OnDisconnectFromServer,OnPlayerDisconnected,etc) are from the legacy networking API, not UNet.

Ah. Back to the dreadful docs again.

So, what event methods are triggered that UNET uses?

If they don’t use event methods, what class object does UNET handle server/client/player disconnection?

There’s this method which will be called on your server network manager component when a client disconnects:
http://docs.unity3d.com/ScriptReference/Networking.NetworkManager.OnServerDisconnect.html

Could you please explain how we could get the client GameObject name / transform.name from the conn parameter?
Thnx !

I want to print out soemthing like “player xxx disconnected” in my multiplayer chat.

We all want to be able to do that, but sadly guys at unity think that type of feature is not needed on the HLPI… Lol?
You have to build your own “PlayerManager” to be able to do stuff like that, UNET is player “object” oriented, not player “connection” oriented it seems like.

http://forum.unity3d.com/threads/player-manager.350351/

1 Like

In my system, once a player connects and has authorized/validated I store their particulars in a custom player class. Within that is a field for their current connection id, so I can perform a lookup (though that connection id can belong to someone else at a different time in the game session after connections & disconnections, so additional validation can be required).

Unity is holding a lot of data about the client in that network connection object too though, including a list of clientOwnedObjects which might give you a shortcut to get their player object on your server.

https://docs.unity3d.com/ScriptReference/Networking.NetworkConnection.html
https://docs.unity3d.com/ScriptReference/Networking.NetworkConnection-clientOwnedObjects.html

Hope this helps :slight_smile:

conn.playerControllers[0].gameObject seemed to do the trick…

i’m doing Destroy(conn.playerControllers[0].gameObject) in that method.
Can anybody confirm this is the correct way to do this?

thnx

The easiest way to manage something like a Call whenever a player is connected or not is actually a tad bit simple when you do get how Unity Unet works… but only when you get it.

Detecting when a player join or disconnect can be done like this :

  1. First, as you’re obviously making an Online game, you mostly must have a NetworkManager component on some gameobject that doesn’t get destroyed on load. If it hasn’t already been done, you should create your own custom version of it. It’s surely the most easy thing ever : Create a new script. Name it whatever you want (such as “NetworkManagerCustom” for the sake of explaination). Add “using UnityEngine.Networking;” and change MonoBehaviour to NetworkManager. I suggest you do it first as this and not just remove the original NetworkManager so you can easily access and put back the references within the “new” custom NetworkManager. (It’s easily so that you don’t forget or change a value or reference unwillingly.) Once the NetworkManagerCustom is exactly like your NetworkManager, you’ll be able to remove the NetworkManager component as you custom script will now inherit is parameters.

  2. Now, you have pretty much access to every kind of original functions that were prior to the Unet implementation, but they are slightly different in how they requires you to use them. I suggest you take a look at the Official NetworkManager docs and check every public functions.

  3. Now, you’re able to use a function like this in the Custom NetworkManager script you added :

    public override void OnServerConnect(NetworkConnection Conn){ //Being called when a new client connect onto the host or server)
}

In the example above, OnServerConnect will only be called on the Host client/server so you got to implement your own way of allowing the Custom NetworkManager script to communicate with whatever other manager (like a UI manager) script you might need it to update. There’s many way of doing it and how to do it will depend on what should be happening when a new player connect and what kind of information you might want from it.

Note that, for the host (if you have an host), OnServerConnect will be called in the Awake() so if you wish to refer to some instances through that, you might have to do a small work-around by adding if(Conn.hostId>=0){} condition.

This an example I’m currently using :

    public override void OnServerConnect(NetworkConnection Conn){
        if(Conn.hostId >= 0){
        Debug.Log("New Client Connected");
            SM_Manager.Instance.UpdateMatchNameString();
        }
    }

For me, it’s set in a way that the Host can change the game name and the connected client have it updated both when they connect and when it’s changed while they are connected. While the modification of the String works if the sting is modified after the clients are connected, the initial state of the string is not updated when the client connect and is left empty. By adding that code above to my Custom NetworkManager script, as soon as the a new client is connected, the UI text string of that player (and, for the sake of safety, all the other clients connected) is updated with the right information. In my case, I’m building my game with my own lobby system which involve an customization menu and a bunch of different cameras that takes a % of the screen and all. It’s a really complex multi-layered overlay + camera based UI system which is more or less self managed as the host has some available button and field that are displayed as Text component for connected clients or simply inactive/invisible.

The Conn.hostID >= 0 is kind of a special trick that allows you to have a simple condition for the host.
For the host, NetworkConnection.hostID is always equals to -1 because he’s connected to its own server within the application itself (which doesn’t requires a remote access) while for all the connected clients, NetworkConnection.hostID should return 0 because 0 equals the server. This is why you have to watch out if you’re doing something by comparing the ID from the host or from a client perspective as both will return different ID values.

For something like printing a text into a chat window, you could simply implement a system that allow the server to add its own set of string onto the chat window through a ChatManager script and then call it whenever required.

Something like :

using UnityEngine;
using UnityEngine.Networking;

public class NetworkManagerCustom : NetworkManager {

    //When a new client connect to the Host server.
    public override void OnServerConnect(NetworkConnection Conn){
        if(Conn.hostId >= 0 && Chat_Manager.Instance != null){
            Chat_Manager.Instance.ServerChatMsg("New Player has joined");
        }
    }
}

Where chat manager has something like this :

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;

public class Chat_Manager : NetworkBehaviour {

    public static Chat_Manager Instance;

    void Awake(){
        Chat_Manager.Instance = this;
    }

    [ClientCallbackAttribute]
    void AddMsgToChat(String Msg){
        // Here is how you manage each client to spawn the chat strings. Be it by instantiating or editing a value or whatever you want.
    }

    [Server]
    public void ServerChatMsg(string Msg){
        AddMsgToChat(Msg);
    }

}

Now, the reason why I’m passing the string through a [server] attribute onto a [ClientCallbackAttribute] is just to show you how you could make it so that the server/host might store the message onto some .txt archive file or something while each clients wouldn’t requires it. It might also be useful if you want the new clients which connect to the host to access some of the previous chat entries.

I know this might not be the best for everyone, but it’s something that works with Unet.

1 Like