Replacing existing prefab with asset id...

I’m looking at guides from DipperDino ([DipperDino guide][1]) on Mirror multiplayer and during development there was an error that it doesn’t have. I rechecked everything many times and couldn’t fix it. The error sounds like “replacing existing prefab with asset id”, referring to objects in Rosouces.SpawnablePrefabs. I left the NetworkManagerLobby class code below.

using Mirror;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;

public class NetworkManagerLobby : NetworkManager
{
    [SerializeField] private int minPlayers = 2;
    [Scene] [SerializeField] private string menuScene = string.Empty;

    [Header("Room")]
    [SerializeField] private NetworkRoomPlayerLobby roomPlayerPrefab = null;

    [Header("Game")]
    [SerializeField] private NetworkGamePlayerLobby gamePlayerPrefab = null;
    [SerializeField] private GameObject playerSpawnSystem = null;

    public static event Action OnClientConnected;
    public static event Action OnClientDisconnected;
    public static event Action<NetworkConnection> OnServerReadied;

    public List<NetworkRoomPlayerLobby> RoomPlayers { get; } = new List<NetworkRoomPlayerLobby>();
    public List<NetworkGamePlayerLobby> GamePlayers { get; } = new List<NetworkGamePlayerLobby>();
    // HERE CAN BE SPECTATOR PLAYERS LIST FOR OWN SPECTATOR LOGIC (LIKE RoomPlayer -> GamePlayers BUT SpectatorPlayers -> GamePlayers

    public override void OnStartServer() => spawnPrefabs = Resources.LoadAll<GameObject>("SpawnablePrefabs").ToList();

    public override void OnStopServer()
    {
        RoomPlayers.Clear();
    }

    public override void OnStartClient()
    {
        var spawnablePrefabs = Resources.LoadAll<GameObject>("SpawnablePrefabs");

        foreach (var prefab in spawnablePrefabs)
        {
            ClientScene.RegisterPrefab(prefab);
        }
    }

    public override void OnClientConnect(NetworkConnection conn)
    {
        base.OnClientConnect(conn);

        OnClientConnected?.Invoke();
    }

    public override void OnClientDisconnect(NetworkConnection conn)
    {
        base.OnClientDisconnect(conn);

        OnClientDisconnected?.Invoke();
    }

    public override void OnServerConnect(NetworkConnection conn)
    {
        if (numPlayers >= maxConnections)
        {
            conn.Disconnect();
            return;
            //TODO; show err lobby is full message
        }

        if (SceneManager.GetActiveScene().path != menuScene)
        {
            conn.Disconnect();
            return;
            //TODO; show err scene message
        }
    }

    public override void OnServerDisconnect(NetworkConnection conn)
    {
        if (conn.identity != null)
        {
            var player = conn.identity.GetComponent<NetworkRoomPlayerLobby>();

            RoomPlayers.Remove(player);

            NotifyPlayersOfReadyState();
        }

        base.OnServerDisconnect(conn);
    }

    public override void OnServerAddPlayer(NetworkConnection conn)
    {
        if (SceneManager.GetActiveScene().path == menuScene)
        {
            bool isLeader = RoomPlayers.Count == 0;

            NetworkRoomPlayerLobby roomPlayerInstance = Instantiate(roomPlayerPrefab);

            roomPlayerInstance.IsLeader = isLeader;

            NetworkServer.AddPlayerForConnection(conn, roomPlayerInstance.gameObject);
        }
    }

    public void NotifyPlayersOfReadyState()
    {
        foreach (var player in RoomPlayers)
        {
            player.HandleReadyToStart(IsReadyToStart());
        }
    }

    private bool IsReadyToStart()
    {
        if (numPlayers < minPlayers) { return false; }

        foreach (var player in RoomPlayers) //Loop every player in the lobby
        {
            if (!player.IsReady) { return false; }
        }

        //########Loop every player in the lobby########
        //foreach (var player in RoomPlayers) 
        //{
        //    CODE HERE;
        //}

        return true;
    }

    public void StartGame()
    {
        if(SceneManager.GetActiveScene().path == menuScene)
        {
            if(!IsReadyToStart()) { return; }

            ServerChangeScene("Scene_Tests_01");
        }
    }

    public override void ServerChangeScene(string newSceneName)
    {
        // From menu to scene
        if (SceneManager.GetActiveScene().path == menuScene && newSceneName.StartsWith("Scene_Tests"))
        {
            for (int i = RoomPlayers.Count - 1; i >= 0; i--)
            {
                var conn = RoomPlayers*.connectionToClient;*

var gameplayerInstance = Instantiate(gamePlayerPrefab);
gameplayerInstance.SetDisplayName(RoomPlayers*.DisplayName);*

NetworkServer.Destroy(conn.identity.gameObject);

NetworkServer.ReplacePlayerForConnection(conn, gameplayerInstance.gameObject, true);
}
}

base.ServerChangeScene(newSceneName);
}

public override void OnServerSceneChanged(string sceneName)
{
if (sceneName.StartsWith(“Scene_Tests”))
{
GameObject playerSpawnSystemInstance = Instantiate(playerSpawnSystem);
NetworkServer.Spawn(playerSpawnSystemInstance);
}
}

public override void OnServerReady(NetworkConnection conn)
{
base.OnServerReady(conn);

OnServerReadied?.Invoke(conn);
}
}
_*[1]: How To Make A Multiplayer Game In Unity - Lobby - Readying Up - YouTube

@reseeman , @AnasHussain and @Kachimov . I’m no expert on Mirror but I also followed the same tutorial and got a bunch of warnings when going back to the lobby after a round. What I did to remove all those was basically try to clear the list whenever we start the client or server. Also I’m using the same spawnPrefabs list for both:

        ...
        public override void OnStartServer()
        {
            spawnPrefabs.Clear();
            spawnPrefabs = Resources.LoadAll<GameObject>("SpawnablePrefabs").ToList();
        }

        public override void OnStartClient()
        {
            spawnPrefabs.Clear();
            spawnPrefabs = Resources.LoadAll<GameObject>("SpawnablePrefabs").ToList();

            ClientScene.ClearSpawners();

            foreach (var prefab in spawnPrefabs)
            {
                ClientScene.RegisterPrefab(prefab);
            }
        }
        ...

If one hosts the game, it will call OnStartServer and also OnStartClient… I know it’s not the best but at least now I don’t have that problem of replacing prefabs

I really hope this helps and if anyone has a better approach please let us know :smiley: