Search Unity

Question Why my player's name doesn't change.

Discussion in 'Netcode for GameObjects' started by Faysou, Mar 5, 2023.

  1. Faysou

    Faysou

    Joined:
    Feb 22, 2021
    Posts:
    12
    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.

    Code (CSharp):
    1. using Debug;
    2. using TMPro;
    3. using Unity.Collections;
    4. using Unity.Netcode;
    5. using UnityEngine;
    6. namespace Player
    7. {
    8.     public class PlayerUsername : NetworkBehaviour
    9.     {
    10.         [SerializeField] TMP_Text nameField;
    11.  
    12.         // 64 characters max - changes are server authoritative
    13.         NetworkVariable<FixedString32Bytes> username = new NetworkVariable<FixedString32Bytes>("Player");
    14.  
    15.         public override void OnNetworkSpawn()
    16.         {
    17.             if (IsOwner)
    18.                 SetUsernameServerRpc(PlayerPrefs.GetString("Username"));
    19.         }
    20.  
    21.         [ServerRpc]
    22.         void SetUsernameServerRpc(string playerUsername)
    23.         {
    24.             if (playerUsername is "")
    25.             {
    26.                 // Default username
    27.                 playerUsername = "Player " + OwnerClientId;
    28.             }
    29.             else
    30.             {
    31.                 // Limiting size to fit on network variable
    32.                 if (playerUsername.Length > 64)
    33.                     playerUsername = playerUsername[..64];
    34.             }
    35.             RLogger.LogInfo($"Setting username to {playerUsername}");
    36.             username.Value = playerUsername;
    37.             UpdateNameClientRpc();
    38.         }
    39.  
    40.         [ClientRpc]
    41.         void UpdateNameClientRpc()
    42.         {
    43.             RLogger.LogInfo("Received Client RPC");
    44.             // Going through all players and updating their name
    45.             foreach (var player in GameObject.FindGameObjectsWithTag("Player"))
    46.             {
    47.                 player.GetComponent<PlayerUsername>().nameField.text = player.GetComponent<PlayerUsername>().username.Value.Value;
    48.             }
    49.         }
    50.     }
    51. }
    52.  
    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.
     
  2. Faysou

    Faysou

    Joined:
    Feb 22, 2021
    Posts:
    12
    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.
     
  3. RikuTheFuffs-U

    RikuTheFuffs-U

    Unity Technologies

    Joined:
    Feb 20, 2020
    Posts:
    440
    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.
     
  4. Faysou

    Faysou

    Joined:
    Feb 22, 2021
    Posts:
    12
    Thank you Riku
     
    RikuTheFuffs-U likes this.
  5. VTTJake

    VTTJake

    Joined:
    Nov 21, 2013
    Posts:
    5
    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 :)
     
  6. Faycal94

    Faycal94

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

    Code (CSharp):
    1. using System;
    2. using System;
    3. using TMPro;
    4. using Unity.Collections;
    5. using Unity.Netcode;
    6. using UnityEngine;
    7.  
    8. namespace Release.Scripts.Player
    9. {
    10.     public class PlayerName : NetworkBehaviour
    11.     {
    12.         [SerializeField] private TMP_Text nameText;
    13.        
    14.         // Create a new network variable that can by default only be modified by the server
    15.         private readonly NetworkVariable<FixedString32Bytes> _playerName = new();
    16.  
    17.         public override void OnNetworkSpawn()
    18.         {
    19.             base.OnNetworkSpawn();
    20.             _playerName.OnValueChanged += (_, newPlayerName) =>
    21.             {
    22.                 nameText.text = newPlayerName.ToString();
    23.             };
    24.         }
    25.  
    26.         private void Start()
    27.         {
    28.             // When spawn ask the server to change our name
    29.             if (IsOwner && IsLocalPlayer)
    30.                 ChangePlayerName(PlayerPrefs.GetString("PlayerName"));
    31.                
    32.         }
    33.  
    34.         private void ChangePlayerName(string playerName)
    35.         {
    36.             if (IsServer)
    37.                 _playerName.Value = playerName;
    38.             else
    39.                 ChangePlayerNameServerRpc(playerName);
    40.         }
    41.        
    42.         [ServerRpc]
    43.         private void ChangePlayerNameServerRpc(string playerName)
    44.         {
    45.             _playerName.Value = playerName;
    46.         }
    47.     }
    48. }
    49.  
    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 :)
     
    Last edited: Aug 30, 2023
    mtahacilli8118 likes this.
  7. VTTJake

    VTTJake

    Joined:
    Nov 21, 2013
    Posts:
    5
    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 ;)