Hi, I have three buttons, three players, and I want to know which player clicked on which button by assigning them a different popup UI color. Let’s say player 1- red, player 2 - green, player 3 - white.
So when player 1 clicks on button(1), the red panel will be visible for all other players telling them who did that.
Possible solution: I have been advised to call to the Host with a Cmd method and pass the connectionId of the player who click on it. Then check the list of players on the NetworkManager, and find the matching player object. Once it has that player object, it would get the name and Id, and calls a RPC to the clients to show the UI element, passing them the correct text and color.
**What I Have: ** I have list of my players:
public List<MyNetworkPlayer> players { get; } = new List<MyNetworkPlayer>();
and i can use my player by
MyNetworkPlayer player = conn.identity.GetComponent<MyNetworkPlayer>();
I also can attatch my NetworkManager if that can help:
public class MyNetworkManager : NetworkManager
{
public static event Action ClientOnConnected;
public static event Action ClientOnDisconnected;
// players should't be able to join the lobby during the game.
private bool isGameInProgress = false;
// here, we create a list of players, in order to display them in the lobby later.
public List<MyNetworkPlayer> players { get; } = new List<MyNetworkPlayer>();
#region Serwer
public override void OnServerConnect(NetworkConnection conn )
{ //kick a player if the game is in progress
if (!isGameInProgress) { return; }
base.OnServerConnect (conn);
conn.Disconnect();
}
// here i write some own logic about what heppens when a client connects to a server. If the connection is successful
// the message about connection will be display in a console!
public override void OnServerDisconnect(NetworkConnection conn)
{ // when the server disconnects someone
// lets grab that player
MyNetworkPlayer player = conn.identity.GetComponent<MyNetworkPlayer>();
players.Remove(player);
base.OnServerDisconnect(conn);
}
public override void OnStopServer()
//what happens when we stop running the server
{
players.Clear();
isGameInProgress = false;
}
public void StartGame()
{ // the game won't start with the less than 2 players
if(players.Count <2){return;}
//if we have more than 2 we can start the game
isGameInProgress = true;
//also we change our scene here
ServerChangeScene("GameScene");
}
public override void OnServerAddPlayer(NetworkConnection conn)
{
base.OnServerAddPlayer(conn);
//reference to network player
MyNetworkPlayer player = conn.identity.GetComponent<MyNetworkPlayer>();
players.Add(player);
// here I assign player's name base on joining order
player.SetDisplayName($"Player {players.Count}");
Debug.Log("Player conn ID: " + conn.connectionId);
//here we dclare who will be a party owner
// if there is only one player he will be a party owner
player.SetPartyOwner(players.Count == 1);
Debug.Log($"There are now {numPlayers} players");
}
//when a client stops, we shold also clear the player's list and currently we only
// add to it on the server
public override void OnStopClient()
{
players.Clear();
}
#endregion
#region Client
[System.Obsolete]
public override void OnClientConnect(NetworkConnection conn)
{
base.OnClientConnect(conn);
Debug.Log("Client connected: " + conn.connectionId);
ClientOnConnected?.Invoke();
}
[System.Obsolete]
public override void OnClientDisconnect(NetworkConnection conn)
{
base.OnClientDisconnect(conn);
ClientOnDisconnected?.Invoke();
}
#endregion
}
And MyNetworkPlayer:
public class MyNetworkPlayer : NetworkBehaviour
{
//Here i refer to a player text and change it based on current player number.
[SerializeField] private TMP_Text displayNameText= null;
[SyncVar(hook = nameof(AuthorityHandlePartyOwnerStateUpdated))]
private bool isPartyOwner = false;
// syncvar that will allow other players to store our name
[SyncVar(hook = nameof(ClientHandleDisplayNameUpdated))]
public string displayName;
// this below is the event created in order to handle the changes of client info
// like it's colour and so on
public static event Action ClientOnInfoUpdated;
//public string which returns the display name
public string GetDisplayName()
{
return displayName;
}
public bool GetIsPartyOwner()
{
return isPartyOwner;
}
public static event Action<bool> AuthorityOnPartyOwnerStateUpdated;
#region Serwer
public override void OnStartServer()
{
DontDestroyOnLoad(gameObject);
}
[Server]
// checking who the party owner is
public void SetPartyOwner(bool state)
{
isPartyOwner = state;
}
[Server]
public void SetDisplayName(string newDisplayName)
{
displayName = newDisplayName;
}
#endregion
#region Commands
[Command]
private void CmdSetDisplayName(string newDisplayName)
{
//here I add the codition saying that the player length can not be shorter than 2 characters
//if(newDisplayName.Length <2 || newDisplayName.Length > 20){ return; }
RpcLogNewName(newDisplayName);
SetDisplayName(newDisplayName);
}
[Command]
// A command so client can tell the server that he wants to start the game
public void CmdStartGame()
{
if(!isPartyOwner) { return; }
//otherwise tell the NetworkManager to stop the game
((MyNetworkManager)NetworkManager.singleton).StartGame();
}
#endregion
#region Authorities
private void AuthorityHandlePartyOwnerStateUpdated(bool oldState, bool newState)
{
// it allows you to change who the party owner is during the lobby
// its goinna be a button to change the authority of the ownershit
if(!hasAuthority) {return; }
// this down below is for the UI button change its statement
AuthorityOnPartyOwnerStateUpdated?.Invoke(newState);
}
#endregion
#region Client
// Here we change the player's name
private void HandleDisplayNameUpdated(string oldName, string newName)
{
displayNameText.text = newName;
}
// Here we connect the reference from MyNetworkManager
public override void OnStartClient()
{
if (NetworkServer.active) {return;}
// whenever a client starts and we're not the host, if we just end up a client, we can
// be added to our list of the players
((MyNetworkManager)NetworkManager.singleton).players.Add(this);
// this below prevcents our player objects from being destroyed when
// changing the scanes
DontDestroyOnLoad(gameObject);
}
private void ClientHandleDisplayNameUpdated(string oldDisplayName, string newDisplayName)
{ // we need to display people's name when they got updated (in the UI)
ClientOnInfoUpdated?.Invoke();
}
public override void OnStopClient()
{
ClientOnInfoUpdated?.Invoke();
//if we are not the server we do this for everyone:
if (!isClientOnly) {return; }
// Here we remove a player from the list of players
((MyNetworkManager)NetworkManager.singleton).players.Remove(this);
//if we are the server we do this for everyone:
if (!hasAuthority) { return; }
}
[ClientRpc]
//rpc log new name is one of our new names being set
private void RpcLogNewName(string newDisplayName)
{
Debug.Log(newDisplayName);
}
#endregion
}
My problem: As I said in possible solution, I don’t know how to send connectionId to host and then, based on that, assign corresponding UI element for each different player. I would be really thankful for any advise on how to code that.