Sync usernames between clients

Hello there,

I’m new at Unity UNET and I’m trying to sync usernames between clients and server. I tried the next code but the problem is that the first player (which is the server) can see every new client username, the second player can only see his username and the 3rd username, and the last player can only see his username. Every new player can’t see old players username but the oldest can see everyones username.

public class TankController : NetworkBehaviour
[SyncVar]
    string nickname;

    public override void OnStartLocalPlayer()
    {

        foreach (MeshRenderer child in GetComponentsInChildren<MeshRenderer>())
        {
            child.material.color = Color.blue;
        }
        nickname = "Client";
        CmdSendNicknameToServer("Client");
    }

    [Command]
    void CmdSendNicknameToServer(string s)
    {
        RpcSetPlayerName(s);
        GetComponentInChildren<Text>().text = s;
    }

    [ClientRpc]
    void RpcSetPlayerName(string s)
    {
        GetComponentInChildren<Text>().text = s;
    }
}

Can anyone tell me what’s wrong? Thank you so much

You aren’t changing the variable: nickname on the server, so it’s not transmitting using the syncvar

try something like this

(untested)

using UnityEngine;
using UnityEngine.Networking;

public class tank : NetworkBehaviour
{
    [SyncVar]
    public string syncUsername;

    public override void OnStartLocalPlayer()
    {
        CmdSendNickname("clientname");
    }

    [Command]
    void CmdSendNickname(string username)
    {
        syncUsername = username;
    }

    void Update()
    {
        Debug.Log(syncUsername);
    }
}

Thanks for your response, but I tried to save the variable nickname and it’s not transmitting. The only way to achieve it is to put a CmdSendNicknameToServer(nickname); into Update function, but I think it’s not a good way, always sending data…

Hm… the code above here that I wrote should work, have u tried it?

Defiled’s snippet should work, however I offer an extra way to do this using hooks:

public class TankController : NetworkBehaviour
{
    [SyncVar(hook = "UpdateUsername")]
    string Nickname;

    public override void OnStartClient()
    {
        if (isLocalPlayer)
        {
            foreach (MeshRenderer child in GetComponentsInChildren<MeshRenderer>())
            {
                child.material.color = Color.blue;
            }
            CmdSendNicknameToServer("Client");
        }

        // hooks are only called when a variable is updated on the server. So if a client joins after, we need to manually invoke the hook
        if (!string.IsNullOrEmpty(Nickname))
        {
            UpdateUsername(Nickname);
        }
    }

    public void UpdateUsername(string nickname)
    {
        Nickname = nickname;
        GetComponentInChildren<Text>().text = Nickname;
    }

    [Command]
    void CmdSendNicknameToServer(string nickname)
    {
        UpdateUsername(Nickname);
    }
}

I don’t know why it doesn’t work… I uploaded the two codes and I still have the same issue… I attach an image of what happens (two Unity3D open, same code but one has “server” as nickname and the other one has “client”):

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

public class TankController : NetworkBehaviour
{
    public GameObject bulletPrefab;
    public Transform bulletSpawn;

    [SyncVar(hook = "UpdateUsername")]
    string nickname;

    void Update()
    {
        if (!isLocalPlayer)
        {
            return;
        }

        var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
        var z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;

        transform.Rotate(0, x, 0);
        transform.Translate(0, 0, z);

        if (Input.GetKeyDown(KeyCode.Space))
        {
            CmdFire();
        }
        //GetComponentInChildren<Text>().text = nickname;
        //CmdSendNicknameToServer(nickname);
        //Debug.Log(nickname);
    }

    // This [Command] code is called on the Client …
    // … but it is run on the Server!
    [Command]
    void CmdFire()
    {

        // Create the Bullet from the Bullet Prefab
        var bullet = (GameObject)Instantiate(
            bulletPrefab,
            bulletSpawn.position,
            bulletSpawn.rotation);

        // Add velocity to the bullet
        bullet.GetComponent<Rigidbody>().velocity = bullet.transform.forward * 6;

        // Spawn the bullet on the Clients
        NetworkServer.Spawn(bullet);

        // Destroy the bullet after 2 seconds
        Destroy(bullet, 2.0f);
    }

    public override void OnStartLocalPlayer()
    {
        if (isLocalPlayer)
        {
            foreach (MeshRenderer child in GetComponentsInChildren<MeshRenderer>())
            {
                child.material.color = Color.blue;
            }
            CmdSendNicknameToServer("server");
        }

        if (!string.IsNullOrEmpty(nickname))
        {
            UpdateUsername(nickname);
        }

        //nickname = GetInstanceID().ToString();
        //CmdSendNicknameToServer("clientname");
        //GetComponentInChildren<Text>().text = "clientname";

    }

    public void UpdateUsername(string nick)
    {
        nickname = nick;
        GetComponentInChildren<Text>().text = nickname;
    }

    [Command]
    void CmdSendNicknameToServer(string nick)
    {
        UpdateUsername(nick);
    }
}

Might be better off using a ClientRpc / TargetRpc to send the player who just joined the correct name on initial start

That’s why you check if the variable has a value in OnStartClient and manually invoke the hook

Thank you all so much, but finally I got a solution in youtube. From 17:00 the explanation works for me: