Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Question Player prefab not spawning (Networking)

Discussion in 'Multiplayer' started by nachowasteland, May 27, 2022.

  1. nachowasteland

    nachowasteland

    Joined:
    Dec 10, 2020
    Posts:
    1
    Hi! I have an issue where even though the game is running an instance (one is hosting and then another player joins), the player prefab is not spawning. I'm can't get it to work but I'm unsure as to why, though I'm wondering if it might have something to do with either the ServerNetPortal script or the Tank (which is the script for the player prefab) script? As you can see below I have an approval check - could it maybe have something to do with the code there? Hope these two scripts provide enough context, otherwise I can post more if needed :) Thanks.

    ServerGameNetPortal:

    Code (CSharp):
    1. public class ServerGameNetPortal : MonoBehaviour
    2. {
    3.     [Header("Settings")]
    4.     public int maxPlayers = 4;
    5.  
    6.     private static ServerGameNetPortal instance;
    7.     public static ServerGameNetPortal Instance => instance;
    8.  
    9.     private Dictionary<string, PlayerData> clientData;
    10.     private Dictionary<ulong, string> clientIDToGuid;
    11.     private Dictionary<ulong, int> clientSceneMap;
    12.     private bool gameIsInProgress;
    13.  
    14.     private const int MaxConnectionPayload = 1024;
    15.  
    16.     private GameNetPortal gameNetPortal;
    17.  
    18.     private void Awake()
    19.     {
    20.         if(instance != null && instance != this)
    21.         {
    22.             Destroy(gameObject);
    23.             return;
    24.         }
    25.        
    26.         instance = this;
    27.         DontDestroyOnLoad(gameObject);
    28.     }
    29.  
    30.     private void Start()
    31.     {
    32.         gameNetPortal = GetComponent<GameNetPortal>();
    33.         gameNetPortal.OnNetworkReadied += HandleNetworkReadied;
    34.  
    35.         NetworkManager.Singleton.ConnectionApprovalCallback += ApprovalCheck;
    36.  
    37.         NetworkManager.Singleton.OnServerStarted += HandleServerStarted;
    38.  
    39.         clientData = new Dictionary<string, PlayerData>();
    40.         clientIDToGuid = new Dictionary<ulong, string>();
    41.         clientSceneMap = new Dictionary<ulong, int>();
    42.     }
    43.  
    44.     private void OnDestroy()
    45.     {
    46.         if (gameNetPortal == null)
    47.             return;
    48.  
    49.         gameNetPortal.OnNetworkReadied -= HandleNetworkReadied;
    50.  
    51.         if (NetworkManager.Singleton == null)
    52.             return;
    53.  
    54.         NetworkManager.Singleton.ConnectionApprovalCallback -= ApprovalCheck;
    55.  
    56.         NetworkManager.Singleton.OnServerStarted -= HandleServerStarted;
    57.     }
    58.  
    59.     public PlayerData? GetPlayerData(ulong clientID)
    60.     {
    61.         if (clientIDToGuid.TryGetValue(clientID, out string clientGuid))
    62.         {
    63.             if (clientData.TryGetValue(clientGuid, out PlayerData playerData))
    64.                 return playerData;
    65.             else
    66.                 Debug.Log("No player data found for client ID: {clientID}");
    67.         }
    68.         else
    69.             Debug.Log("No client guid found for client ID: {clientID}");
    70.  
    71.         return null;
    72.     }
    73.  
    74.     public void StartGame()
    75.     {
    76.         gameIsInProgress = true;
    77.  
    78.         NetworkManager.Singleton.SceneManager.LoadScene("GameScene", LoadSceneMode.Single);
    79.     }
    80.  
    81.     public void EndGame()
    82.     {
    83.         gameIsInProgress = false;
    84.  
    85.         NetworkManager.Singleton.SceneManager.LoadScene("LobbyScene", LoadSceneMode.Single);
    86.     }
    87.  
    88.     private void HandleNetworkReadied()
    89.     {
    90.         if (!NetworkManager.Singleton.IsServer)
    91.             return;
    92.  
    93.         gameNetPortal.OnUserDisconnectRequested += HandleUserDisconnectRequested;
    94.         NetworkManager.Singleton.OnClientDisconnectCallback += HandleClientDisconnect;
    95.         gameNetPortal.OnClientSceneChanged += HandleClientSceneChanged;
    96.  
    97.         NetworkManager.Singleton.SceneManager.LoadScene("LobbyScene", LoadSceneMode.Single);
    98.  
    99.         if (NetworkManager.Singleton.IsHost)
    100.             clientSceneMap[NetworkManager.Singleton.LocalClientId] = SceneManager.GetActiveScene().buildIndex;
    101.     }
    102.     private void HandleClientDisconnect(ulong clientID)
    103.     {
    104.         clientSceneMap.Remove(clientID);
    105.  
    106.         if (clientIDToGuid.TryGetValue(clientID, out string guid))
    107.         {
    108.             clientIDToGuid.Remove(clientID);
    109.  
    110.             if (clientData[guid].ClientID == clientID)
    111.                 clientData.Remove(guid);
    112.         }
    113.  
    114.         if(clientID == NetworkManager.Singleton.LocalClientId)
    115.         {
    116.             gameNetPortal.OnUserDisconnectRequested -= HandleUserDisconnectRequested;
    117.             NetworkManager.Singleton.OnClientDisconnectCallback -= HandleClientDisconnect;
    118.             gameNetPortal.OnClientSceneChanged -= HandleClientSceneChanged;
    119.         }
    120.     }
    121.  
    122.     private void HandleClientSceneChanged(ulong clientID, int sceneIndex)
    123.     {
    124.         clientSceneMap[clientID] = sceneIndex;
    125.     }
    126.  
    127.     private void HandleUserDisconnectRequested()
    128.     {
    129.         HandleClientDisconnect(NetworkManager.Singleton.LocalClientId);
    130.  
    131.         NetworkManager.Singleton.Shutdown();
    132.  
    133.         ClearData();
    134.  
    135.         SceneManager.LoadScene("MenuScene");
    136.     }
    137.  
    138.     private void HandleServerStarted()
    139.     {
    140.         if (!NetworkManager.Singleton.IsHost)
    141.             return;
    142.  
    143.         string clientGuid = Guid.NewGuid().ToString();
    144.         string playerName = PlayerPrefs.GetString("PlayerName", "Missing Name");
    145.  
    146.         clientData.Add(clientGuid, new PlayerData(playerName, NetworkManager.Singleton.LocalClientId));
    147.         clientIDToGuid.Add(NetworkManager.Singleton.LocalClientId, clientGuid);
    148.     }
    149.  
    150.     private void ClearData()
    151.     {
    152.         clientData.Clear();
    153.         clientIDToGuid.Clear();
    154.         clientSceneMap.Clear();
    155.  
    156.         gameIsInProgress = false;
    157.     }
    158.  
    159.     private void ApprovalCheck(byte[] connectionData, ulong clientID, NetworkManager.ConnectionApprovedDelegate callback)
    160.     {
    161.         if(connectionData.Length > MaxConnectionPayload)
    162.         {
    163.             callback(false, 0, false, null, null);
    164.             return;
    165.         }
    166.  
    167.         if(clientID == NetworkManager.Singleton.LocalClientId)
    168.         {
    169.             callback(false, null, true, null, null);
    170.             return;
    171.         }
    172.  
    173.         string payload = Encoding.UTF8.GetString(connectionData);
    174.         var connectionPayload = JsonUtility.FromJson<ConnectionPayload>(payload);
    175.  
    176.         ConnectStatus gameReturnStatus = ConnectStatus.Success;
    177.  
    178.         // Checks if an instance is already running.
    179.         if (clientData.ContainsKey(connectionPayload.clientGuid))
    180.         {
    181.             ulong oldClientID = clientData[connectionPayload.clientGuid].ClientID;
    182.             StartCoroutine(WaitToDisconnectClient(oldClientID, ConnectStatus.LoggedInAgain));
    183.         }
    184.  
    185.         if (gameIsInProgress)
    186.             gameReturnStatus = ConnectStatus.GameInProgress;
    187.  
    188.         else if (clientData.Count >= maxPlayers)
    189.             gameReturnStatus = ConnectStatus.ServerIsFull;
    190.  
    191.         if(gameReturnStatus == ConnectStatus.Success)
    192.         {
    193.             clientSceneMap[clientID] = connectionPayload.clientScene;
    194.             clientIDToGuid[clientID] = connectionPayload.clientGuid;
    195.             clientData[connectionPayload.clientGuid] = new PlayerData(connectionPayload.playerName, clientID);
    196.         }
    197.  
    198.         callback(false, 0, true, null, null);
    199.  
    200.         gameNetPortal.ServerToClientSetDisconnectReason(clientID, gameReturnStatus);
    201.  
    202.         if (gameReturnStatus != ConnectStatus.Success)
    203.             StartCoroutine(WaitToDisconnectClient(clientID, gameReturnStatus));
    204.     }
    205.  
    206.     private IEnumerator WaitToDisconnectClient(ulong clientID, ConnectStatus reason)
    207.     {
    208.         gameNetPortal.ServerToClientSetDisconnectReason(clientID, reason);
    209.  
    210.         yield return new WaitForSeconds(0);
    211.  
    212.         DisconnectThisClient(clientID);
    213.     }
    214.  
    215.     private void DisconnectThisClient(ulong clientID)
    216.     {
    217.         NetworkObject networkObject = NetworkManager.Singleton.SpawnManager.GetPlayerNetworkObject(clientID);
    218.        
    219.         if (networkObject != null)
    220.             networkObject.Despawn(true);
    221.  
    222.         NetworkManager.Singleton.DisconnectClient(clientID);
    223.     }
    224. }
    and Tank (player):

    Code (CSharp):
    1. public class Tank : NetworkBehaviour
    2. {
    3.     public GameObject bullet;
    4.     public Material enemyMaterial;
    5.  
    6.     private HealthBar localHealthBar;
    7.     private ShieldBar shieldBar;
    8.     private int localHealth = 5;
    9.     private TMP_Text healthTxt;
    10.     private int localShield = 0;
    11.     private Rigidbody rb;
    12.  
    13.     public NetworkVariable<int> Health = new NetworkVariable<int>(5);
    14.  
    15.     void Start()
    16.     {
    17.         if (IsLocalPlayer)
    18.         {
    19.             // Set random start position for local player.
    20.             transform.position = GetRandomPosition();
    21.  
    22.             // Get components of local player.
    23.             healthTxt = GameObject.Find("healthTxt").GetComponent<TMP_Text>();
    24.             localHealthBar = GameObject.Find("healthBar").GetComponent<HealthBar>();
    25.             rb = GetComponent<Rigidbody>();
    26.  
    27.             // Set text to local health.
    28.             healthTxt.text = localHealth.ToString();
    29.  
    30.             localHealthBar.SetMaxHealth(localHealth);
    31.             localHealthBar.SetHealth(localHealth);
    32.         }
    33.         else
    34.         {
    35.             // Changes the colour of opponents' tanks.
    36.             GetComponent<MeshRenderer>().material = enemyMaterial;
    37.         }
    38.     }
    39.  
    40.     void Update()
    41.     {
    42.         if (IsLocalPlayer)
    43.             UpdateClient();
    44.     }
    45.  
    46.     private void OnCollisionEnter(Collision collision)
    47.     {
    48.         if (collision.transform.CompareTag("Bullet"))
    49.         {
    50.             if(IsClient)
    51.             {
    52.                 // Update local health.
    53.                 localHealth--;
    54.                 healthTxt.text = localHealth.ToString();
    55.                 localHealthBar.SetHealth(localHealth);
    56.  
    57.                 // Sync global health.
    58.                 SetHealthServerRpc();
    59.  
    60.                 // If dead.
    61.                 if(localHealth <= 0)
    62.                 {
    63.                     GetComponent<BoxCollider>().enabled = false;
    64.                     Invoke("Respawn", 5);
    65.                 }
    66.             }
    67.             // Removes bullet on hit.
    68.             Destroy(collision.gameObject);
    69.         }
    70.     }
    71.  
    72.     [ServerRpc]
    73.     void SetHealthServerRpc()
    74.     {
    75.         Health.Value = localHealth;
    76.     }
    77.  
    78.     private void Respawn()
    79.     {
    80.         localHealth = 5;
    81.         healthTxt.text = localHealth.ToString();
    82.         localHealthBar.SetHealth(localHealth);
    83.  
    84.         SetHealthServerRpc();
    85.  
    86.         rb.velocity = Vector3.zero;
    87.         transform.position = GetRandomPosition();
    88.         GetComponent<BoxCollider>().enabled = true;
    89.     }
    90.  
    91.     public void UpdateClient()
    92.     {
    93.         // Moves local player.
    94.         Vector3 movement = Vector3.ClampMagnitude(new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")), 1);
    95.         transform.position += movement * Time.deltaTime * 5;
    96.  
    97.         // Rotates local player.
    98.         Quaternion newRotation = Quaternion.LookRotation(movement, Vector3.up);
    99.         if(movement.magnitude > 0)
    100.             transform.rotation = Quaternion.Lerp(transform.rotation, newRotation, Time.deltaTime * 5);
    101.  
    102.         // Allows local player to shoot.
    103.         if (Input.GetButtonDown("Shoot"))
    104.             SpawnBulletServerRpc();
    105.     }
    106.  
    107.     public Vector3 GetRandomPosition()
    108.     {
    109.         return new Vector3(Random.Range(1, 5), 2, Random.Range(-20, -25));
    110.     }
    111.  
    112.     // Spawns bullet on server.
    113.     [ServerRpc]
    114.     private void SpawnBulletServerRpc()
    115.     {
    116.         GameObject localBullet = Instantiate(bullet, transform.position + transform.forward * 3, transform.rotation);
    117.         localBullet.GetComponent<NetworkObject>().Spawn();
    118.     }
    119. }