Search Unity

Sync name of spawned GameObject with clients

Discussion in 'Netcode for GameObjects' started by Nyxaras, Jun 14, 2022.

  1. Nyxaras

    Nyxaras

    Joined:
    May 14, 2022
    Posts:
    7
    Hi! I'm new to NetCode and having an issue with syncing between host and client.
    Here I've made this script to spawn some PlayerObject and name them straight away (I don't want to use the NetworkManager.PlayerPrefab fields). But the freshly made names appear only on Host side... Clients still have those "playerPrefab(Clone)" names in hierarchy.
    Would like to have some help on this one...
    Thanks in advance

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using UnityEngine;
    5. using Unity.Netcode;
    6. using UnityEngine.SceneManagement;
    7.  
    8. public class Spawner : NetworkBehaviour
    9. {
    10.     public string champName;
    11.  
    12.     private GameObject playerPrefab;
    13.     public GameObject[] champList;
    14.  
    15.     public Transform[] SpawnPositions;
    16.  
    17.     private void Awake()
    18.     {
    19.         int i = 0;
    20.         if (NetworkManager.Singleton.IsServer)
    21.         {
    22.             foreach (NetworkClient client in NetworkManager.Singleton.ConnectedClientsList)
    23.             {
    24.                 SetPlayerChamp();
    25.                 playerPrefab = champList.Single(d => d.name == champName);
    26.  
    27.                 GameObject player = Instantiate(playerPrefab, SpawnPositions[i].position, SpawnPositions[i].rotation);
    28.                 player.GetComponent<NetworkObject>().SpawnAsPlayerObject(client.ClientId);
    29.  
    30.                 // Can't make this next line sync with client :
    31.                 player.name = "Player " + (i + 1);
    32.  
    33.                 // Tried in addition with this rpc but it doesn't work either...
    34.                 SetNameClientRpc();
    35.  
    36.                 i++;
    37.                
    38.  
    39.                 [ClientRpc]
    40.                 void SetNameClientRpc()
    41.                 {
    42.                     player.name = "Player " + (i + 1);
    43.                 }
    44.             }
    45.         }
    46.     }
    47.  
    48.     void SetPlayerChamp()
    49.     {
    50.         champName = ChampSelect.ChampionName;
    51.     }
    52. }
    53.  
     
  2. CosmoM

    CosmoM

    Joined:
    Oct 31, 2015
    Posts:
    204
    Don't use Awake since the object will not be network-initialized yet. Instead, set the name in OnNetworkSpawn().
     
  3. Nyxaras

    Nyxaras

    Joined:
    May 14, 2022
    Posts:
    7
    Thank you for the response, but it doesn't work even with OnNetworkSpawn()... Still have those Prefab(Clones)...
     
  4. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    660
    I would avoid having the RPC as a local function. I'm trying to get my head around how it would work as the player reference is only on the server and I'm not sure how it would match up on the client. Unfortunately I can't test it as I'm on Unity 2020 and it doesn't support local function attributes.

    Check the RPC is actually run client-side and that the player reference is correct.
     
    Last edited: Jun 16, 2022
  5. Nyxaras

    Nyxaras

    Joined:
    May 14, 2022
    Posts:
    7
    It seems that the RPC doesn't make any difference... but the player reference is correct since it works on host side.
     
  6. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    660
    Try this RPC call, you'll need to move the RPC out of the foreach loop and just call it from there instead. I'm assuming all clients have connected at this point.

    Code (CSharp):
    1.     [ClientRpc]
    2.     private void SetNameClientRpc(NetworkObjectReference player, string newName)
    3.     {
    4.         Debug.Log("Spawner SetNameClientRpc: " + newName);
    5.  
    6.         ((GameObject)player).name = newName;
    7.     }
     
  7. Nyxaras

    Nyxaras

    Joined:
    May 14, 2022
    Posts:
    7
    Works like charm! Thank you guys <3
    Here's the new working code for those in need :
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using UnityEngine;
    5. using Unity.Netcode;
    6. using UnityEngine.SceneManagement;
    7.  
    8. public class Spawner : NetworkBehaviour
    9. {
    10.     public string champName;
    11.  
    12.     public GameObject playerPrefab;
    13.     public GameObject[] champList;
    14.  
    15.     public Transform[] SpawnPositions;
    16.  
    17.     override public void OnNetworkSpawn()
    18.     {
    19.         int i = 0;
    20.         if (NetworkManager.Singleton.IsServer)
    21.         {
    22.             foreach (NetworkClient client in NetworkManager.Singleton.ConnectedClientsList)
    23.             {
    24.  
    25.                 GameObject player = Instantiate(playerPrefab, SpawnPositions[i].position, SpawnPositions[i].rotation);
    26.                 player.GetComponent<NetworkObject>().SpawnAsPlayerObject(client.ClientId);
    27.                 i++;
    28.                 SetNameClientRpc(player, "Player " + i);
    29.             }
    30.         }
    31.     }
    32.  
    33.     [ClientRpc]
    34.     private void SetNameClientRpc(NetworkObjectReference player, string newName)
    35.     {
    36.         Debug.Log("Spawner SetNameClientRpc: " + newName);
    37.  
    38.         ((GameObject)player).name = newName;
    39.     }
    40. }