Why my player's name doesn't change.

Hello,
I have a small PlayerName script applied to my player prefab.
When player spawn, it changes their username network variable and then all player's TMP text (to update even previous player that joined).

The expected behaviour is when a player joins, it updates all players names.
What I get is that: from server perspective, all is good. But the client has only their TMP text having the default network variable value, it is good for everyone else.

using Debug;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
namespace Player
{
    public class PlayerUsername : NetworkBehaviour
    {
        [SerializeField] TMP_Text nameField;

        // 64 characters max - changes are server authoritative
        NetworkVariable<FixedString32Bytes> username = new NetworkVariable<FixedString32Bytes>("Player");

        public override void OnNetworkSpawn()
        {
            if (IsOwner)
                SetUsernameServerRpc(PlayerPrefs.GetString("Username"));
        }

        [ServerRpc]
        void SetUsernameServerRpc(string playerUsername)
        {
            if (playerUsername is "")
            {
                // Default username
                playerUsername = "Player " + OwnerClientId;
            }
            else
            {
                // Limiting size to fit on network variable
                if (playerUsername.Length > 64)
                    playerUsername = playerUsername[..64];
            }
            RLogger.LogInfo($"Setting username to {playerUsername}");
            username.Value = playerUsername;
            UpdateNameClientRpc();
        }

        [ClientRpc]
        void UpdateNameClientRpc()
        {
            RLogger.LogInfo("Received Client RPC");
            // Going through all players and updating their name
            foreach (var player in GameObject.FindGameObjectsWithTag("Player"))
            {
                player.GetComponent<PlayerUsername>().nameField.text = player.GetComponent<PlayerUsername>().username.Value.Value;
            }
        }
    }
}

I'm new to Netcode and I think it's only a about my logic, but I can't spot my mistake.

Thank you in advance.

Ok so I fixed the problem, but I don't know if it is the best way possible and why it is fixed haha.

What I did is subscribe to an event OnValueChanged() a lambda (a, b) => nameField.text = b.Value.
I you can help me better understand what the problem was and is there a better way of doing this I would be a significant help.

Hi @Faysou , that’s the right way to do what you did with NetworkVariables, you don’t need to send a ClientRPC for updateding the vlaue on clients.

Thank you Riku

1 Like

Would you mind sharing your code since I’m struggling with the same exact problem and any kind of solution would make me keep at least some of my hair :slight_smile:

Haha sure here is a little script I wrote for you, I think it is working but did not test :

using System;
using System;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;

namespace Release.Scripts.Player
{
    public class PlayerName : NetworkBehaviour
    {
        [SerializeField] private TMP_Text nameText;

        // Create a new network variable that can by default only be modified by the server
        private readonly NetworkVariable<FixedString32Bytes> _playerName = new();

        public override void OnNetworkSpawn()
        {
            base.OnNetworkSpawn();
            _playerName.OnValueChanged += (_, newPlayerName) =>
            {
                nameText.text = newPlayerName.ToString();
            };
        }

        private void Start()
        {
            // When spawn ask the server to change our name
            if (IsOwner && IsLocalPlayer)
                ChangePlayerName(PlayerPrefs.GetString("PlayerName"));

        }

        private void ChangePlayerName(string playerName)
        {
            if (IsServer)
                _playerName.Value = playerName;
            else
                ChangePlayerNameServerRpc(playerName);
        }

        [ServerRpc]
        private void ChangePlayerNameServerRpc(string playerName)
        {
            _playerName.Value = playerName;
        }
    }
}

Some explanations :
- When a client join, it will call OnValueChanged if the value of the variable is not the same that the one you used to initialize it, in our case we did new() so the value is "".
- If we are playing the host, we are the server and the player. We know that the server cannot call ServerRpc so we have to use an alternative way. We first call ChangePlayerName() to try to change our name on our own if we are the server and if not we asked for it with a ServerRpc

Tell me if you have any issues :)

1 Like

Thanks for the script, but it seems to have the same issue where the name is applied only for the client instances but not for the user being a host. And every time I change something to get the host name set, then the client is left out.

I must be missing something completely obvious here and I'm looking forward for the moment where I can feel myself stupid again ;)