Search Unity

MLAPI - GameObject name not updating to server

Discussion in 'Netcode for GameObjects' started by preynolds0521, Mar 25, 2021.

  1. preynolds0521

    preynolds0521

    Joined:
    Mar 25, 2021
    Posts:
    3
    I'm new to networking, so I'm sure this is a basic problem that has a simple solution, but I cannot figure it out.

    When I start as host a player prefab is created. I then find that player prefab and rename it. The issue I'm having is that the name change isn't showing for my client when it connects. It should be named "MyPrefab", but it's still keeping its basic name "PlayerPrefab(Clone)."

    The PlayerPrefab prefab has the NetworkedObject component. Here's the inspector:


    The code for starting my host and updating the player object is:

    Host/Client Start and object renaming code:
    Code (CSharp):
    1.  
    2.     public void StartGameAsHost()
    3.     {
    4.         Debug.Log("Starting game as host...");
    5.         NetworkingManager.Singleton.StartHost();
    6.         InitializePlayerObject();
    7.  
    8.         //NetworkSceneManager.SwitchScene(SPData.SCENEGameSetup);
    9.     }
    10.  
    11.     public void StartGameAsClient()
    12.     {
    13.         Debug.Log("Joining game as client...");
    14.         NetworkingManager.Singleton.OnClientConnectedCallback += OnClientJoins;
    15.         NetworkingManager.Singleton.StartClient();
    16.  
    17.     }
    18.  
    19.     private void InitializePlayerObject()
    20.     {
    21.         Player p = new Player(playerName); //Generate a player object
    22.         GameObject g = GameObject.Find(SPData.PREFABPlayer + "(Clone)");
    23.  
    24.         try
    25.         {
    26.             g.name = playerName + " Player";
    27.         }
    28.         catch (System.Exception ex)
    29.         {
    30.             Debug.LogError("Player object not found.\n" + ex.Message);
    31.         }
    32.  
    33.         PlayerPrefabManager ppm = g.GetComponent<PlayerPrefabManager>();
    34.         ppm.Init(p);
    35.     }
    36.  
    37.     public void OnClientJoins(ulong id)
    38.     {
    39.         Debug.Log($"Client joined: {id}");
    40.         InitializePlayerObject();
    41.     }
    42.  
    PlayerPrefabManager: (Basic, nothing much to it yet)
    Code (CSharp):
    1.  
    2. using MLAPI;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using UnityEngine;
    6.  
    7. public class PlayerPrefabManager : NetworkedBehaviour
    8. {
    9.     [Header("Player Reference:")]
    10.     public Player player;
    11.     [Header("Component References:")]
    12.     public PlayerUIHandler playerUIHandler;
    13.  
    14.     // Start is called before the first frame update
    15.     void Start()
    16.     {
    17.      
    18.     }
    19.  
    20.     // Update is called once per frame
    21.     void Update()
    22.     {
    23.      
    24.     }
    25.  
    26.     public void Init(Player p)
    27.     {
    28.         player = p;
    29.         playerUIHandler.SetPlayerName(p.Name);
    30.     }
    31. }
    32.  
    PlayerUIHandler:
    Code (CSharp):
    1.  
    2. using MLAPI;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using UnityEngine;
    6. using UnityEngine.UI;
    7.  
    8. public class PlayerUIHandler : NetworkedBehaviour
    9. {
    10.     [Header("UI References")]
    11.     public Text playerName;
    12.  
    13.     // Start is called before the first frame update
    14.     void Start()
    15.     {
    16.      
    17.     }
    18.  
    19.     // Update is called once per frame
    20.     void Update()
    21.     {
    22.      
    23.     }
    24.  
    25.     public void SetPlayerName(string n)
    26.     {
    27.         playerName.text = n;
    28.     }
    29. }
    30.  
    Player:
    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class Player
    7. {
    8.     private string playerName;
    9.     public string Name { get => playerName; private set { } }
    10.  
    11.     public Player(string n)
    12.     {
    13.         playerName = n;
    14.     }
    15. }
    16.  
    As I said, I'm sure this is something simple, but I could really use some help.



    I'm not sure if it's needed, but just in case, here's the full code of the LobbyUIHandler script that contains all of my client code. There's a lot of debugging and sequencing stuff in there since I'm still trying to figure out how networking works.

    Code (CSharp):
    1.  
    2. using MLAPI;
    3. using MLAPI.SceneManagement;
    4. using System.Collections;
    5. using System.Collections.Generic;
    6. using UnityEngine;
    7. using UnityEngine.UI;
    8.  
    9. public class LobbyUIHandler : NetworkedBehaviour
    10. {
    11.     [Header("UI References")]
    12.     public InputField fieldName;
    13.  
    14.     [Space(10)]
    15.     public Button buttonHost;
    16.     public Button buttonJoin;
    17.  
    18.     private string playerName;
    19.  
    20.     public void Start()
    21.     {
    22.         try
    23.         {
    24.             playerName = PlayerPrefs.GetString(SPData.PREFPlayerName);
    25.         } catch (System.Exception ex)
    26.         {
    27.             Debug.LogError(ex.Message);
    28.             playerName = "";
    29.         }
    30.  
    31.         fieldName.text = playerName;
    32.         UpdateButtonState();
    33.  
    34.         //DEBUG
    35.         NetworkSceneManager.OnSceneSwitchStarted += OnStartSceneSwitch;
    36.         NetworkSceneManager.OnSceneSwitched += OnSceneSwitched;
    37.     }
    38.  
    39.     public void OnDestroy()
    40.     {
    41.  
    42.         //DEBUG
    43.         NetworkSceneManager.OnSceneSwitchStarted -= OnStartSceneSwitch;
    44.     }
    45.  
    46.     public void OnNameChanged()
    47.     {
    48.         playerName = fieldName.text;
    49.         PlayerPrefs.SetString(SPData.PREFPlayerName, playerName);
    50.         UpdateButtonState();
    51.     }
    52.  
    53.     private void UpdateButtonState()
    54.     {
    55.         buttonHost.interactable = !string.IsNullOrEmpty(playerName);
    56.         buttonJoin.interactable = !string.IsNullOrEmpty(playerName);
    57.     }
    58.  
    59.     public void StartGameAsHost()
    60.     {
    61.         Debug.Log("Starting game as host...");
    62.         NetworkingManager.Singleton.StartHost();
    63.         InitializePlayerObject();
    64.  
    65.         //NetworkSceneManager.SwitchScene(SPData.SCENEGameSetup);
    66.     }
    67.  
    68.     public void StartGameAsClient()
    69.     {
    70.         Debug.Log("Joining game as client...");
    71.         NetworkingManager.Singleton.OnClientConnectedCallback += OnClientJoins;
    72.         NetworkingManager.Singleton.StartClient();
    73.  
    74.     }
    75.  
    76.     private void InitializePlayerObject()
    77.     {
    78.         Player p = new Player(playerName); //Generate a player object
    79.         GameObject g = GameObject.Find(SPData.PREFABPlayer + "(Clone)");
    80.  
    81.         try
    82.         {
    83.             g.name = playerName + " Player";
    84.         }
    85.         catch (System.Exception ex)
    86.         {
    87.             Debug.LogError("Player object not found.\n" + ex.Message);
    88.         }
    89.  
    90.         PlayerPrefabManager ppm = g.GetComponent<PlayerPrefabManager>();
    91.         ppm.Init(p);
    92.     }
    93.  
    94.     public void OnStartSceneSwitch(AsyncOperation operation)
    95.     {
    96.         //Debug.Log("The scene should have started switching now.");
    97.     }
    98.  
    99.     public void OnSceneSwitched()
    100.     {
    101.         Debug.Log("The scene has finished switching.");
    102.     }
    103.  
    104.     public void OnClientJoins(ulong id)
    105.     {
    106.         Debug.Log($"Client joined: {id}");
    107.         InitializePlayerObject();
    108.     }
    109. }
    110.  
    SPData is just a class that contains persistent strings and other data like that.
     
  2. luke-unity

    luke-unity

    Joined:
    Sep 30, 2020
    Posts:
    306
    There is a few things which you have to do differently with MLAPI. Right now you are instantiating a player object on everyone when a new client joins. What you should do instead is only instantiate the object on the server and then call the `Spawn` function on NetworkObject instead.

    To synchronize the player name you will need a NetworkVariable<string> because a regular string won't be synchronized automatically over the network. I recommend checking out our Hello World tutorial + the tutorial building on top of it and reading up on object spawning.
    Hello World: https://docs-multiplayer.unity3d.com/docs/tutorials/helloworldintro
    Spawning: https://docs-multiplayer.unity3d.com/docs/mlapi-basics/object-spawning
     
  3. preynolds0521

    preynolds0521

    Joined:
    Mar 25, 2021
    Posts:
    3
    Thank you for the response, but I'm still a little confused.

    I can't declare the GameObject's name to be a NetworkedVariable, that's built-in and I can't modify it. I tried assigning it by a NetworkedVarString, but that didn't work.

    I'll look at changing the spawning system, but I'd still like to figure this out. If this GameObject is a NetworkedObject, it seems like any changes made to the base GameObject should be sent to the network...

    Modified Code:

    LobbyUIHandler:
    Code (CSharp):
    1.  
    2. using MLAPI;
    3. using MLAPI.NetworkedVar;
    4. using MLAPI.SceneManagement;
    5. using System.Collections;
    6. using System.Collections.Generic;
    7. using UnityEngine;
    8. using UnityEngine.UI;
    9.  
    10. public class LobbyUIHandler : NetworkedBehaviour
    11. {
    12.     [Header("UI References")]
    13.     public InputField fieldName;
    14.  
    15.     [Space(10)]
    16.     public Button buttonHost;
    17.     public Button buttonJoin;
    18.  
    19.     private string playerName;
    20.  
    21.     public void Start()
    22.     {
    23.         try
    24.         {
    25.             playerName = PlayerPrefs.GetString(SPData.PREFPlayerName);
    26.         } catch (System.Exception ex)
    27.         {
    28.             Debug.LogError(ex.Message);
    29.             playerName = "";
    30.         }
    31.  
    32.         fieldName.text = playerName;
    33.         UpdateButtonState();
    34.  
    35.         //DEBUG
    36.         NetworkSceneManager.OnSceneSwitchStarted += OnStartSceneSwitch;
    37.         NetworkSceneManager.OnSceneSwitched += OnSceneSwitched;
    38.     }
    39.  
    40.     public void OnDestroy()
    41.     {
    42.  
    43.         //DEBUG
    44.         NetworkSceneManager.OnSceneSwitchStarted -= OnStartSceneSwitch;
    45.     }
    46.  
    47.     public void OnNameChanged()
    48.     {
    49.         playerName = fieldName.text;
    50.         PlayerPrefs.SetString(SPData.PREFPlayerName, playerName);
    51.         UpdateButtonState();
    52.     }
    53.  
    54.     private void UpdateButtonState()
    55.     {
    56.         buttonHost.interactable = !string.IsNullOrEmpty(playerName);
    57.         buttonJoin.interactable = !string.IsNullOrEmpty(playerName);
    58.     }
    59.  
    60.     public void StartGameAsHost()
    61.     {
    62.         Debug.Log("Starting game as host...");
    63.         NetworkingManager.Singleton.StartHost();
    64.         InitializePlayerObject();
    65.  
    66.         //NetworkSceneManager.SwitchScene(SPData.SCENEGameSetup);
    67.     }
    68.  
    69.     public void StartGameAsClient()
    70.     {
    71.         Debug.Log("Joining game as client...");
    72.         NetworkingManager.Singleton.OnClientConnectedCallback += OnClientJoins;
    73.         NetworkingManager.Singleton.StartClient();
    74.  
    75.     }
    76.  
    77.     private void InitializePlayerObject()
    78.     {
    79.         NetworkedVarString pName = new NetworkedVarString(playerName);
    80.         Player p = new Player(pName); //Generate a player object
    81.         GameObject g = GameObject.Find(SPData.PREFABPlayer + "(Clone)");
    82.  
    83.         try
    84.         {
    85.             g.name = pName.Value + " Player";
    86.         }
    87.         catch (System.Exception ex)
    88.         {
    89.             Debug.LogError("Player object not found.\n" + ex.Message);
    90.         }
    91.  
    92.         PlayerPrefabManager ppm = g.GetComponent<PlayerPrefabManager>();
    93.         ppm.Init(p);
    94.     }
    95.  
    96.     public void OnStartSceneSwitch(AsyncOperation operation)
    97.     {
    98.         //Debug.Log("The scene should have started switching now.");
    99.     }
    100.  
    101.     public void OnSceneSwitched()
    102.     {
    103.         Debug.Log("The scene has finished switching.");
    104.     }
    105.  
    106.     public void OnClientJoins(ulong id)
    107.     {
    108.         Debug.Log($"Client joined: {id}");
    109.         InitializePlayerObject();
    110.     }
    111. }
    112.  
    Player:
    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using MLAPI.NetworkedVar;
    6.  
    7. public class Player
    8. {
    9.     private NetworkedVarString playerName;
    10.     public NetworkedVarString Name { get => playerName; private set { } }
    11.  
    12.     public Player(NetworkedVarString n)
    13.     {
    14.         playerName = n;
    15.     }
    16. }
    17.  
    PlayerUIHandler:
    Code (CSharp):
    1.  
    2. using MLAPI;
    3. using MLAPI.NetworkedVar;
    4. using System.Collections;
    5. using System.Collections.Generic;
    6. using UnityEngine;
    7. using UnityEngine.UI;
    8.  
    9. public class PlayerUIHandler : NetworkedBehaviour
    10. {
    11.     [Header("UI References")]
    12.     public Text playerName;
    13.  
    14.     // Start is called before the first frame update
    15.     void Start()
    16.     {
    17.        
    18.     }
    19.  
    20.     // Update is called once per frame
    21.     void Update()
    22.     {
    23.        
    24.     }
    25.  
    26.     public void SetPlayerName(NetworkedVarString n)
    27.     {
    28.         playerName.text = n.Value;
    29.     }
    30. }
    31.  

    PlayerPrefabManager:
    Code (CSharp):
    1.  
    2. using MLAPI;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using UnityEngine;
    6.  
    7. public class PlayerPrefabManager : NetworkedBehaviour
    8. {
    9.     [Header("Player Reference:")]
    10.     public Player player;
    11.     [Header("Component References:")]
    12.     public PlayerUIHandler playerUIHandler;
    13.  
    14.     // Start is called before the first frame update
    15.     void Start()
    16.     {
    17.        
    18.     }
    19.  
    20.     // Update is called once per frame
    21.     void Update()
    22.     {
    23.        
    24.     }
    25.  
    26.     public void Init(Player p)
    27.     {
    28.         player = p;
    29.         playerUIHandler.SetPlayerName(p.Name);
    30.     }
    31. }
    32.  
     
  4. firaui

    firaui

    Joined:
    Nov 14, 2018
    Posts:
    12
    Are you using the new MLAPI 0.1.0? Because the name should be NetworkVariableString. Also from docs you can only use NetworkVariable in the NetworkBehaviour class.

    To demonstrate it should be like this more or less. Assign NetworkVariable.Value in Server, and read the value in client.
    Code (CSharp):
    1. public NetworkVariableString PlayerName = new NetworkVariableString();
    2. public Text PlayerNameText;
    3.  
    4. public void SetName()
    5. {
    6.     if (NetworkManager.Singleton.IsServer)
    7.     {
    8.         PlayerName.Value = "Player";
    9.     }
    10.     PlayerNameText.text = PlayerName.Value;
    11. }
     
  5. mhernandez88

    mhernandez88

    Joined:
    Jul 20, 2016
    Posts:
    38
    Isnt using a network variable for name a huge waste of resources? Would not RPC be a better implementation.