#Syncing usernames

1 messages · Page 1 of 1 (latest)

timber moss
#

Post you code here and we can see what's wrong. If you are using NGO, then NetworkVariable<FixedString32Bytes> will work

late knot
#

Alright, if there is anything wrong with the logic, please let me know as im really not familiar with the syntax of netcode and most of the logic behind it.

I have a script JoinMenu
I've put this on my UI menu where the player can enter a name and an ip, then he presses host or connect, These buttons call the HostLobby() or ConnectLobby() functions respectively

So far the connection part works, i can connect host and client and move around freely ( Note that i have left out the animation syncing intentionally for the moment).

I basically connect the player and then switch scenes to the game scene, then i instantiate the player prefab, which is saved in a seperate script that i've just put ontop of my network manager

#

JoinMenu ==>

using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;
using UnityEngine.SceneManagement;
using System.Net;
using System.Linq;
using UnityEditor.Experimental.GraphView;
using Telepathy;

public class JoinMenu : MonoBehaviour
{
    
    [SerializeField] private DefaultNetworkManager networkManager = null;

    [SerializeField] private GameObject PagePanel = null;
    [SerializeField] private TMP_Text client_name = null;
    [SerializeField] private TMP_Text ip_adress = null;
   
    public void HostLobby()
    {

        string ip = System.Text.RegularExpressions.Regex.Replace(ip_adress.text, "[^0-9.]", "");
        string name = client_name.text.Trim();
        if (!IsValidIP(ip))
        {
            Debug.LogError("Invalid IP Address");
            return;
        }
        PlayerPrefs.SetString("username", client_name.text); // set name
        //networkManager.GetComponent<UnityTransport>().ConnectionData.Address = ip;
        //networkManager.GetComponent<UnityTransport>().ConnectionData.Port = 6666;
        Debug.Log($"IP: {ip}");

        var unityTransport = networkManager.GetComponent<UnityTransport>();
        unityTransport.SetConnectionData(ip,7777);
        //unityTransport.name = name;// experimental
        

        
      
        


        networkManager.StartHost();

        
        SceneManager.LoadScene("NetworkTestConnect");

       
        SceneManager.sceneLoaded += OnSceneLoaded;
    }
    private bool IsValidIP(string ip)
    {
        if (string.IsNullOrWhiteSpace(ip)) return false;

        var splitValues = ip.Split('.');
        if (splitValues.Length != 4) return false;

        byte tempForParsing;
        return splitValues.All(r => byte.TryParse(r, out tempForParsing));
    }
    public void ConnectLobby()
    {
        string ip = System.Text.RegularExpressions.Regex.Replace(ip_adress.text, "[^0-9.]", "");
        string name = client_name.text;

        if (!IsValidIP(ip))
        {
            Debug.LogError("Invalid IP Address");
            return;
        }
       
        var unityTransport = networkManager.GetComponent<UnityTransport>();
        unityTransport.SetConnectionData(ip, 7777);
        unityTransport.name = name;
        networkManager.StartClient();


        SceneManager.LoadScene("NetworkTestConnect");

        
        SceneManager.sceneLoaded += OnSceneLoaded;

    }
    private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
       
        if (scene.name == "NetworkTestConnect")
        {
            
            SceneManager.sceneLoaded -= OnSceneLoaded;



            if (NetworkManager.Singleton.IsServer)
            {
                if (networkManager.IsHost)
                {
                    OnClientConnected(NetworkManager.Singleton.LocalClientId);
                }

                
                NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnected;
            }
            

        }

    }
    private void OnClientConnected(ulong clientId)
    {
        if (NetworkManager.Singleton.IsServer)
        {
            GameObject player = Instantiate(networkManager.data.PlayerPrefab);
           
            NetworkObject networkObject = player.GetComponent<NetworkObject>();

            networkObject.SpawnAsPlayerObject(clientId);

            var DisplayPlayerName = player.GetComponent<DisplayPlayerName>();
            DisplayPlayerName.PlayerName.Value = new NetPlayerName() { username = client_name.text };
            
            
           
        }
        
    }

    
    



}

#

DisplayerPlayerName==> (script located on the player prefab)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Networking;
using Unity.Netcode;
using TMPro;
using UnityEditor;
using Unity.Netcode.Transports.UTP;
using Unity.Collections;
using System;


public class DisplayPlayerName : Unity.Netcode.NetworkBehaviour
{
    public NetworkVariable<NetPlayerName> PlayerName = new NetworkVariable<NetPlayerName>(new NetPlayerName() { username = "" });


    public override void OnNetworkSpawn()
    {
        base.OnNetworkSpawn();
        if (IsServer)
        {
            PlayerName.OnValueChanged += OnPlayerNameChanged;
        }


    }

    private void OnPlayerNameChanged(NetPlayerName previousValue, NetPlayerName newValue)
    {
        if (IsServer)
        {
            Debug.Log($"Player {OwnerClientId} changed name from {previousValue.username} to {newValue.username}");

            gameObject.GetComponentInChildren<TMP_Text>().text = newValue.username;
        }

    }
}
public struct NetPlayerName : INetworkSerializable, System.IEquatable<NetPlayerName>
{
    public string username;
    public bool Equals(NetPlayerName other)
    {
        if (String.Equals(other.username, username, StringComparison.CurrentCultureIgnoreCase))
        {
            return true;
        }
        return false;
    }

    public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
    {
        if (serializer.IsReader)
        {
            var reader = serializer.GetFastBufferReader();
            reader.ReadValueSafe(out username);
        }
        else
        {
            var writer = serializer.GetFastBufferWriter();
            writer.WriteValueSafe(username);
        }
    }
}
#

to be fair, for the DisplayPlayerName script, i was trying to use chatgpt as a guide but it didn't really work out, lol.

#

Im open for criticism, Any help is appreciated. i have tried using mirror for the connection part aswell but i couldn't get it to work so i just decided i'd use the default netcode from unity, since with that i can atleast get host and client connections working lol.

timber moss
#

Ok, since you are saving the user name to player prefs. all you need to do is retrieve it in OnNetworkSpawn() and set the network variable to it. with PlayerName.Value = PlayerPrefs.GetString("username") . The tricky part is that OnValueChanged does not get called when an object first spawns so you'll also need to set the TMP text object there as well

late knot
timber moss
#

PlayerName.OnValueChanged does not get fired when the player first spawns in. the PlayerName.Value will already be the correct value. so in the Display PlayerName OnNetworkSpawn() you'll need to call GetComponentInChildren<TMP_Text>().text = PlayerName.Value in order to set the text to the player name

late knot
#

@timber moss I have tried doing what you said and modified the onNetworkSpawn method as following

public override void OnNetworkSpawn()
    {
        base.OnNetworkSpawn();
        if (IsServer)
        {
            PlayerName.OnValueChanged += OnPlayerNameChanged;
            // get the current spawned players name from playerprefs
            string username = PlayerPrefs.GetString("username");
            PlayerName.Value = new NetPlayerName() { username = username };
            
        }
        GetComponentInChildren<TMP_Text>().text = PlayerName.Value.username;



    }
#

this is the current result

#

now names are being set for the client

#

but it's all just the host's name

#

Ah, i forgot to set playerprefs in the Connect Method , only had it in the host method

#

this is the curent result

#

left being the host, right the client

#

Okay, i've tried messing around with chat gpt and it actually got it to work somehow, i still don't understand what was the issue and it'd be really interesting to know

#

DisplayPlayerName ==>

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Networking;
using Unity.Netcode;
using TMPro;
using UnityEditor;
using Unity.Netcode.Transports.UTP;
using Unity.Collections;
using System;

public class DisplayPlayerName : Unity.Netcode.NetworkBehaviour
{
    public NetworkVariable<NetPlayerName> PlayerName = new NetworkVariable<NetPlayerName>(new NetPlayerName() { username = "" });

    public override void OnNetworkSpawn()
    {
        base.OnNetworkSpawn();

        if (IsServer)
        {
            PlayerName.OnValueChanged += OnPlayerNameChanged;
            string username = PlayerPrefs.GetString("username");
            PlayerName.Value = new NetPlayerName() { username = username };
        }
        UpdatePlayerNameUI(PlayerName.Value.username.ToString());
    }

    private void OnPlayerNameChanged(NetPlayerName previousValue, NetPlayerName newValue)
    {
        Debug.Log($"Player {OwnerClientId} changed name from {previousValue.username} to {newValue.username}");
        UpdatePlayerNameUI(newValue.username.ToString());
    }

    public void SetPlayerName(string name)
    {
        if (IsServer)
        {
            PlayerName.Value = new NetPlayerName() { username = name };
        }
    }

    private void UpdatePlayerNameUI(string name)
    {
        GetComponentInChildren<TMP_Text>().text = name;
    }
}

public struct NetPlayerName : INetworkSerializable, System.IEquatable<NetPlayerName>
{
    public FixedString64Bytes username;

    public bool Equals(NetPlayerName other)
    {
        return username.Equals(other.username);
    }

    public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
    {
        serializer.SerializeValue(ref username);
    }
}



#

Join Menu ==>

using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;
using UnityEngine.SceneManagement;
using System.Net;
using System.Linq;
using UnityEditor.Experimental.GraphView;
using Telepathy;

public class JoinMenu : MonoBehaviour
{
    [SerializeField] private DefaultNetworkManager networkManager = null;
    [SerializeField] private GameObject PagePanel = null;
    [SerializeField] private TMP_Text client_name = null;
    [SerializeField] private TMP_Text ip_adress = null;

    public void HostLobby()
    {
        string ip = System.Text.RegularExpressions.Regex.Replace(ip_adress.text, "[^0-9.]", "");
        string name = client_name.text.Trim();

        if (!IsValidIP(ip))
        {
            Debug.LogError("Invalid IP Address");
            return;
        }

        PlayerPrefs.SetString("username", name); // set name
        var unityTransport = networkManager.GetComponent<UnityTransport>();
        unityTransport.SetConnectionData(ip, 7777);

        networkManager.StartHost();
        SceneManager.LoadScene("NetworkTestConnect");

        SceneManager.sceneLoaded += OnSceneLoaded;
    }

    private bool IsValidIP(string ip)
    {
        if (string.IsNullOrWhiteSpace(ip)) return false;
        var splitValues = ip.Split('.');
        if (splitValues.Length != 4) return false;
        return splitValues.All(r => byte.TryParse(r, out _));
    }

    public void ConnectLobby()
    {
        string ip = System.Text.RegularExpressions.Regex.Replace(ip_adress.text, "[^0-9.]", "");
        string name = client_name.text.Trim();

        if (!IsValidIP(ip))
        {
            Debug.LogError("Invalid IP Address");
            return;
        }

        PlayerPrefs.SetString("username", name); // set name
        var unityTransport = networkManager.GetComponent<UnityTransport>();
        unityTransport.SetConnectionData(ip, 7777);

        networkManager.StartClient();
        SceneManager.LoadScene("NetworkTestConnect");

        SceneManager.sceneLoaded += OnSceneLoaded;
    }

    private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        if (scene.name == "NetworkTestConnect")
        {
            SceneManager.sceneLoaded -= OnSceneLoaded;

            if (NetworkManager.Singleton.IsServer)
            {
                OnClientConnected(NetworkManager.Singleton.LocalClientId);
                NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnected;
            }
        }
    }

    private void OnClientConnected(ulong clientId)
    {
        if (NetworkManager.Singleton.IsServer)
        {
            GameObject player = Instantiate(networkManager.data.PlayerPrefab);
            NetworkObject networkObject = player.GetComponent<NetworkObject>();
            networkObject.SpawnAsPlayerObject(clientId);

            var displayPlayerName = player.GetComponent<DisplayPlayerName>();
            displayPlayerName.SetPlayerName(PlayerPrefs.GetString("username"));
        }
    }
}

timber moss
#

this is how I do it

public class NetworkPlayer : NetworkBehaviour
{    

    public NetworkVariable<FixedString32Bytes> DisplayName = new();
    public LocalPlayerData_SO LocalPlayer;

    public override void OnNetworkSpawn()
    {
        DisplayName.OnValueChanged += (_, player) =>
        {            
            UpdateName(player.ToString());           
        };

        if (HasAuthority)
        {        
            DisplayName.Value = LocalPlayer.Data.UserName; 
        }
        else
        {
            UpdateName(DisplayName.Value.ToString());
        }
    }

    private void UpdateName(string name)
    {
        GetComponentInChildren<TMP_Text>().text = name;
    }
}
late knot
#

I tried doing it like this:


public void SetPlayerGameObject(Character prefab)
    {
        
       
        networkManager.data.PlayerPrefab = prefab;

    }

// this method is inside the JoinMenu Script




public class CharacterButtonHandler : MonoBehaviour
{
    [SerializeField]List<Button> characterButtons = new List<Button>();
    [SerializeField] List<Character> Prefabs = new List<Character>();
    [SerializeField] public JoinMenu joinMenu = null;

    private void Start()
    {
        foreach (Button button in characterButtons)
        {
            button.onClick.AddListener(() => joinMenu.SetPlayerGameObject(Prefabs[characterButtons.IndexOf(button)]));
        }
    }
    }
#

Currently it just takes the prefab selected by the host for all the clients

#

no matter what the client picks

#

Prefab is taken in the onClientConnected via networkManager.data.PlayerPrefab.characterPrefab

timber moss
#

Yea. you would need to send the index of the Prefabs list the player chose either in an RPC or in a Network Variable