unity-game-enginemultiplayerunity-networking

UNet: Failed to spawn server object (NOT using NetworkManager)


I'm playing around with Unity 5's Networking HLAPI. I don't want to use the NetworkManager, because I don't want to pay for Unity's Multiplayer services (Matchmaker and Relay servers).

I'm trying to spawn a Player on the Client when the Client connects to the Server. I can get the Client to correctly connect to the Server, but the spawning fails on the Client with the following error:

Failed to spawn server object, assetId=b861a662c70615a40971e7bab10e4e14 netId=1
UnityEngine.Networking.NetworkIdentity:UNetStaticUpdate()

Note that on the Server, the player object correctly spawns.

Minimal repro:

I'm in a Unity 2D project and I've attached the following script to my Main Camera:

using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Networking.NetworkSystem;

public class MenuMinimalRepro : MonoBehaviour
{
    private NetworkClient networkClient;

    void OnGUI()
    {
        if (this.networkClient != null && this.networkClient.isConnected)
        {
            GUI.Label(new Rect(100, 25, 150, 25), "Running as Client");
        }
        else if (NetworkServer.active)
        {
            GUI.Label(new Rect(100, 25, 150, 25), "Running as Server");
        }
        else
        {
            if (GUI.Button(new Rect(100, 25, 150, 25), "Start as Client"))
            {
                this.StartClient();
            }
            if (GUI.Button(new Rect(100, 50, 150, 25), "Start as Server"))
            {
                this.StartServer();
            }
        }
    }

    public void StartServer()
    {
        NetworkServer.Listen(54321);
        NetworkServer.RegisterHandler(MsgType.AddPlayer, OnAddPlayerServer);
    }

    public void StartClient()
    {
        this.networkClient = new NetworkClient();
        this.networkClient.RegisterHandler(MsgType.Connect, OnConnectedClient);
        this.networkClient.Connect("localhost", 54321);
    }

    // Connected handler for the client side
    public void OnConnectedClient(NetworkMessage netMsg)
    {
        ClientScene.AddPlayer(this.networkClient.connection, 0);
    }

    // AddPlayer handler for the server side
    public void OnAddPlayerServer(NetworkMessage netMsg)
    {
        AddPlayerMessage msg = netMsg.ReadMessage<AddPlayerMessage>();
        GameObject newPlayer = (GameObject)Instantiate(Resources.Load("Prefabs/Player"));
        NetworkServer.AddPlayerForConnection(netMsg.conn, newPlayer, msg.playerControllerId);
    }
}

My Player object is a simple sprite that I've made into a Prefab with the NetworkIdentity component (see my Prefab in the Inspector). My Player Prefab is in a Resources folder so that I can load it easily from code (see my Prefab in the Project View).

I launch a background instance of the game (using Ctrl+B) and I start it as the Server, and then I click the Play button in Unity Editor and start that instance as the Client. Unity then reports the error I mentioned earlier.

Does anyone know what I might be doing wrong?


Solution

  • I've figured it out. What happens is that the Server tells the client which Prefab to instantiate by giving it a hash (as seen in the error message). The problem is, that hash means nothing to the Client until you've registered your Prefab with the UNet system.

    So, all I needed to do was call ClientScene.RegisterPrefab(Resources.Load("Prefabs/Player")) just before the call to ClientScene.AddPlayer(...) in the example in my question.

    Hope this helps someone!