Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Third Party (Mirror) NetworkServer.Spawn() not spawning gameobjects on other clients

Discussion in 'Multiplayer' started by samlaserbeam, Mar 25, 2021.

  1. samlaserbeam

    samlaserbeam

    Joined:
    Oct 2, 2019
    Posts:
    11
    I read somewhere that NetworkServer.Spawn() needs to be called only on the server, so I tried doing that by adding the server tag above the PrepMap() function, but the map is only being generated on the host. Here's the GameManager script that starts the map generation once all players connect to the server:

    Code (CSharp):
    1.     public class GameManager : NetworkManager
    2.     {
    3.         [Header("Lobby")]
    4.         [SerializeField] private LobbyPlayer lobbyPlayerPrefab;
    5.         [Scene] [SerializeField] private string menuScene;
    6.         [SerializeField] private Text playerCountText;
    7.         public bool hosting;
    8.  
    9.         [Header("Game")]
    10.         [SerializeField] private Player gamePlayerPrefab;
    11.         [Scene] [SerializeField] private string gameScene;
    12.         [SerializeField] private MapGenerator mapGeneratorPrefab;
    13.  
    14.         public List<Player> players = new List<Player>();
    15.         public List<LobbyPlayer> lobbyPlayers = new List<LobbyPlayer>();
    16.  
    17.         public static int PlayerCount { get => ((GameManager)singleton).players.Count; }
    18.  
    19.         private MapGenerator mapGenerator;
    20.         private int readiedPlayers;
    21.  
    22.  
    23.         [Server]
    24.         private void PrepMap()
    25.         {
    26.             StartCoroutine(PrepareMapGeneration());
    27.         }
    28.         private IEnumerator PrepareMapGeneration()
    29.         {
    30.             while (true)
    31.             {
    32.                 if (readiedPlayers == players.Count && networkSceneName == gameScene)
    33.                 {
    34.                     NetworkServer.Spawn(mapGenerator.gameObject);
    35.                     mapGenerator.StartGeneration();
    36.                     break;
    37.                 }
    38.                 yield return null;
    39.             }
    40.         }
    41.         public override void OnStartClient()
    42.         {
    43.             //var spawnablePrefabs = Resources.LoadAll<GameObject>("Prefabs");
    44.  
    45.             //foreach (var prefab in spawnablePrefabs)
    46.             //{
    47.             //    if (prefab.GetComponent<NetworkIdentity>() == null)
    48.             //    {
    49.             //        prefab.AddComponent<NetworkIdentity>();
    50.             //    }
    51.             //    ClientScene.RegisterPrefab(prefab);
    52.             //    Debug.Log(prefab.name);
    53.             //}
    54.         }
    55.  
    56.         public override void OnServerReady(NetworkConnection conn)
    57.         {
    58.             readiedPlayers++;
    59.         }
    60.  
    61.         public override void OnClientConnect(NetworkConnection conn)
    62.         {
    63.             if (!ClientScene.ready) ClientScene.Ready(conn);
    64.             ClientScene.AddPlayer(conn);
    65.         }
    66.  
    67.         public override void OnServerDisconnect(NetworkConnection conn)
    68.         {
    69.             base.OnClientDisconnect(conn);
    70.  
    71.             if (networkSceneName == menuScene)
    72.                 UpdateLobbyPlayerCount();
    73.         }
    74.  
    75.         public override void OnServerAddPlayer(NetworkConnection conn)
    76.         {
    77.             if (networkSceneName != menuScene)
    78.             {
    79.                 //don't join if we're already in game
    80.                 conn.Disconnect();
    81.             }
    82.             LobbyPlayer lobbyPlayer = Instantiate(lobbyPlayerPrefab);
    83.             NetworkServer.AddPlayerForConnection(conn, lobbyPlayer.gameObject);
    84.             lobbyPlayers.Add(lobbyPlayer);
    85.  
    86.             UpdateLobbyPlayerCount();
    87.         }
    88.  
    89.         public void Play()
    90.         {
    91.             ServerChangeScene(gameScene);
    92.         }
    93.  
    94.         public override void ServerChangeScene(string newSceneName)
    95.         {
    96.             readiedPlayers = 0;
    97.             mapGenerator = Instantiate(mapGeneratorPrefab);
    98.             PrepMap();
    99.             if (newSceneName == gameScene)
    100.             {
    101.                 foreach (LobbyPlayer lobbyPlayer in lobbyPlayers)
    102.                 {
    103.                     NetworkConnection conn = lobbyPlayer.connectionToClient;
    104.                     Player player = Instantiate(gamePlayerPrefab);
    105.                     NetworkServer.ReplacePlayerForConnection(conn, player.gameObject);
    106.                     NetworkServer.Destroy(lobbyPlayer.gameObject);
    107.                     players.Add(player);
    108.                 }
    109.             }
    110.             base.ServerChangeScene(newSceneName);
    111.         }
    112.  
    113.         //public bool AllPlayersReady()
    114.         //{
    115.         //    foreach (LobbyPlayer lobbyPlayer in lobbyPlayers)
    116.         //    {
    117.         //        if (!lobbyPlayer.isReady)
    118.         //            return false;
    119.         //    }
    120.  
    121.         //    return true;
    122.         //}
    123.  
    124.         public void UpdateLobbyPlayerCount()
    125.         {
    126.             playerCountText.text = lobbyPlayers.Count.ToString();
    127.         }
    128.  
    129.         public override void Awake()
    130.         {
    131.             base.Awake();
    132.             networkSceneName = menuScene;
    133.         }
    134.  
    135.         public static Player GetRandomPlayer()
    136.         {
    137.             return ((GameManager)singleton).players[Randall.Next(((GameManager)singleton).players.Count)];
    138.         }
    139.  
    140.         public static List<Player> GetPlayerList()
    141.         {
    142.             return ((GameManager)singleton).players;
    143.         }
    144.  
    145.     }
    Here's the actual generation code. It definitely needs some cleaning up, but the function that actually calls NetworkServer.Spawn() is in DrawMap():

    Code (CSharp):
    1. #region generatorevents
    2.        
    3.         private void MapGeneratorComplete()
    4.         {
    5.             foreach (MapGeneratorComponent mapGeneratorComponent in mapGeneratorCompletePrefabs)
    6.             {
    7.                 if (!mapGeneratorComponent.MultiplayerOnly || (mapGeneratorComponent.MultiplayerOnly && GameManager.PlayerCount > 1))
    8.                 {
    9.                     GameObject component = Instantiate(mapGeneratorComponent.gameObject);
    10.                     NetworkServer.Spawn(component);
    11.                     component.GetComponent<MapGeneratorComponent>().Generate();
    12.                 }
    13.             }
    14.         }
    15.        
    16.         private void PostDraw()
    17.         {
    18.             foreach (MapGeneratorComponent mapGeneratorComponent in postDrawComponentPrefabs)
    19.             {
    20.                 if (!mapGeneratorComponent.MultiplayerOnly || (mapGeneratorComponent.MultiplayerOnly && GameManager.PlayerCount > 1))
    21.                 {
    22.                     GameObject component = Instantiate(mapGeneratorComponent.gameObject);
    23.                     NetworkServer.Spawn(component);
    24.                     component.GetComponent<MapGeneratorComponent>().Generate();
    25.                 }
    26.             }
    27.         }
    28.         #endregion
    29.  
    30.         private void Awake()
    31.         {
    32.             Randall.InitRandall(seed);
    33.             if (Instance == null)
    34.             {
    35.                 Instance = this;
    36.                 DontDestroyOnLoad(gameObject);
    37.             }
    38.             else
    39.                 Destroy(gameObject);
    40.  
    41.             networkManager = GameObject.Find("Network Manager").GetComponent<GameManager>();
    42.             //networkManager.RegisterMapToServer(this);
    43.         }
    44.  
    45.         [Server]
    46.         public void StartGeneration()
    47.         {
    48.             Init();
    49.             GenerateMap();
    50.             FindCellOpenNeighbors();
    51.             MapGeneratorComplete();
    52.             DrawMap();
    53.             PostDraw();
    54.             Debug.LogWarning(test);
    55.         }
    56.         private void DrawMap()
    57.         {
    58.             for (int y = 0; y < height; y++)
    59.             {
    60.                 for (int x = 0; x < width; x++)
    61.                 {
    62.                     for (int z = 0; z < length; z++)
    63.                     {
    64.                         Cell cell = map[x, y, z];
    65.                         if (cell.isVisited)
    66.                         {
    67.                             if (cell.hasUpWall)
    68.                             {
    69.                                 var w = Instantiate(cell.biome.Wall, cell.coordinate + new Vector3(0, 0, 0.45f), Quaternion.Euler(new Vector3(0, 0, 0)), transform);
    70.                                 NetworkServer.Spawn(w);
    71.                             }
    72.                             if (cell.hasDownWall)
    73.                             {
    74.                                 var w = Instantiate(cell.biome.Wall, cell.coordinate - new Vector3(0, 0, 0.45f), Quaternion.Euler(new Vector3(0, 180, 0)), transform);
    75.                                 NetworkServer.Spawn(w);
    76.                             }
    77.                             if (cell.hasLeftWall)
    78.                             {
    79.                                 var w = Instantiate(cell.biome.Wall, cell.coordinate - new Vector3(0.45f, 0, 0), Quaternion.Euler(new Vector3(0, -90, 0)), transform);
    80.                                 NetworkServer.Spawn(w);
    81.                             }
    82.                             if (cell.hasRightWall)
    83.                             {
    84.                                 var w = Instantiate(cell.biome.Wall, cell.coordinate + new Vector3(0.45f, 0, 0), Quaternion.Euler(new Vector3(0, 90, 0)), transform);
    85.                                 NetworkServer.Spawn(w);
    86.                             }
    87.  
    88.                             var f = Instantiate(cell.biome.Wall, cell.coordinate - new Vector3(0, 0.5f, 0), Quaternion.Euler(new Vector3(90, 0, 0)), transform);
    89.                             NetworkServer.Spawn(f);
    90.                             if (ceilingEnabled)
    91.                             {
    92.                                 var c = Instantiate(cell.biome.Wall, cell.coordinate + new Vector3(0, 0.5f, 0), Quaternion.Euler(new Vector3(-90, 0, 0)), transform);
    93.                                 NetworkServer.Spawn(c);
    94.                             }
    95.                         }
    96.                     }
    97.                 }
    98.             }
    99.         }
    100.  
    I tried adding the [Server] tag to all the functions instead of just the one at the start of the function chain, but that didn't solve anything. Whenever I click play, both players will load in just fine, but the map will only appear for the host and the other client will just be endlessly falling through the void. I've only been working with mirror for a couple of weeks now, so any help is very much appreciated.
     
  2. samlaserbeam

    samlaserbeam

    Joined:
    Oct 2, 2019
    Posts:
    11
    To anyone looking at this in the future, the problem was that I wasn't calling the base function of OnServerReady in the network manager after I had overridden it.