NetworkServer.SendToAll Unknown message ID

Alright, I’ve been wracking my brain on this and it’s time to just reach out for help…

I’ve been trying to set up multiplayer for a small project I’m working on. I have a server and 2 clients, with the 2 clients connecting to the server. I then attempt to send a message from the server to the clients and always get an error:

Unknown message ID 100 connId:1
UnityEngine.Networking.NetworkIdentity:UNetStaticUpdate()

I’m not given a callstack in that error, and NetworkServer.SendToAll() returns true surprisingly, though the message doesn’t reach the clients.

I’ve paired down the code to as small of an example as I can think of and still see the issue. I’m guessing there is some step I’m missing. If someone can help explain the gap in my knowledge I’d gladly buy you a beer.

Here is my annotated test example which I’ve also attached:

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class ServerMain : MonoBehaviour
{
    private int numConnections = 0;
    public static ServerMain Create(GameObject parent)
    {
        GameObject obj = new GameObject();
        obj.name = "ServerMain";
        ServerMain sm = obj.AddComponent<ServerMain>();
        obj.transform.SetParent(parent.transform);

        NetworkServer.Listen(4444);
        NetworkServer.RegisterHandler(MsgType.Connect, sm.OnServerConnect);

        return sm;
    }

    public void OnServerConnect(NetworkMessage netMsg)
    {
        Debug.Log("Connected to client " + netMsg.conn.connectionId);
        numConnections++;
        if (numConnections == 2 )
        {
            // This generates the following error but returns true, and the message does not appear to be sent:
            // "Unknown message ID 100 connId:1
            // UnityEngine.Networking.NetworkIdentity:UNetStaticUpdate()"
            bool success = NetworkServer.SendToAll(100, new TestMessage());
            Debug.Assert(success);

            // ... as does this
            StartCoroutine(SendMessageToClients());
        }
    }

    IEnumerator SendMessageToClients()
    {
        yield return null;

        bool success = NetworkServer.SendToAll(100, new TestMessage());
        Debug.Assert(success);
    }
}

public class ClientMain : MonoBehaviour
{
    NetworkClient networkClient;

    public static ClientMain Create(GameObject parent )
    {
        GameObject obj = new GameObject();
        obj.name = "ClientMain";
        ClientMain cm = obj.AddComponent<ClientMain>();
        obj.transform.SetParent(parent.transform);

        cm.networkClient = new NetworkClient();
        cm.networkClient.RegisterHandler(MsgType.Connect, cm.OnConnected);
        cm.networkClient.Connect("127.0.0.1", 4444);

        return cm;
    }

    public void OnConnected(NetworkMessage netMsg)
    {
        Debug.Log("Client connected to server");
    }
}

public class TestMessage : MessageBase
{
    public TestMessage() { alwaysTrue = true; }
    public bool alwaysTrue;
}

public class main : MonoBehaviour
{
    ServerMain server;
    ClientMain client;
    ClientMain ai;

    void Start()
    {
        server = ServerMain.Create( gameObject );
        client = ClientMain.Create( gameObject );
        ai = ClientMain.Create( gameObject );
        StartCoroutine(SendMessageToClients());
    }

   
    IEnumerator SendMessageToClients()
    {
        // This however does NOT cause the error above.
        bool success = NetworkServer.SendToAll(100, new TestMessage());
        Debug.Assert(success);

        // ... But this does however, again, the same error as above...
        yield return new WaitForSeconds(0.25f);
        success = NetworkServer.SendToAll(100, new TestMessage());
        Debug.Assert(success);

        yield break;
    }
}

3007431–224310–main.cs (2.6 KB)

And of course that’s all I needed to figure out the problem. My toy problem above does not have the corresponding message handler on the NetworkClient, so of course the failure doesn’t result in the SendAll returning false, or a callstack. It’s from a response from the client back to the server. The problem in my real project is that because the handler was being registered after Connect call, which I didn’t think would be a problem, but the execution order wasn’t what I expected.

Sorry for taking up space.