How to assign different UI panels for each joining player? Mirror

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.

To assign different UI panels for each joining player using Mirror, you can use the NetworkIdentity component and the NetworkBehaviour component.
First, you need to create a UI panel that you want to assign to each joining player. Then, you need to attach a NetworkIdentity component to the UI panel game object. This will allow Mirror to synchronize the UI panel across the network.MyBalanceNow
Next, you need to create a script that inherits from NetworkBehaviour. This script will be responsible for assigning the correct UI panel to each joining player. Inside the script, you can use the OnStartClient() method to detect when a new player has joined the game.
In the OnStartClient() method, you can use the isLocalPlayer property to check if the new player is the local player. If the new player is the local player, you can use the GetComponent() method to get a reference to the UI panel attached to the NetworkIdentity component.

Hey @Theodore21Thompson thank you so much for the time you spent on your answer. I had been looking for a solution for a long time and I decided to create a youtube video for everyone who wants to create something similar. Hope that helps someone, here is the link: https://youtu.be/NbmtDQJRxPc

Take care everyone!