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 :
-
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.
-
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.
-
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.