Okay, so I am working on slightly different spawning system - using Non-NetworkManager to spawn player objects. Been pulling my hair out for few hours now cause NetworkServer.AddPlayerForConnection and NetworkServer.ReplacePlayerForConnection are both giving me this exception:
Local invoke: Failed to find message handler for message ID 4
UnityEngine.Networking.NetworkServer:ReplacePlayerForConnection(NetworkConnection, GameObject, Int16)
Managers.GameManager:SpawnPlayerShip(NetworkMessage) (at Assets/Code/Managers/GameManager.cs:89)
UnityEngine.Networking.NetworkClient:Send(Int16, MessageBase)
Managers.GameModes.GameTest:AllowRespawn(NetworkMessage) (at Assets/Code/Managers/GameModes/GameTest.cs:17)
UnityEngine.Networking.NetworkIdentity:UNetStaticUpdate()
So, I started narrowing the issue, and found out that while this works just fine:
// Inside NetworkManager
public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId)
{
GameObject obj = Instantiate(playerPrefab);
NetworkServer.AddPlayerForConnection(conn, obj, 0);
}
While doing it this way throws local invoke exception:
// Inside GameManager
[Server]
public virtual void SpawnPlayerShip(NetworkMessage netMsg)
{
SpaceshipMessage message = netMsg.ReadMessage<SpaceshipMessage>();
Player player = players.Find(message.PlayerID);
GameObject ship = Instantiate(CustomNetworkManager.Manager.playerPrefab);
NetworkServer.AddPlayerForConnection(player.Connection, ship, 0);
}
Perhaps I’ll reprogram it to run inside custom NetworkManager, but I wanted a separate GameManager, so I can have many game modes (by inheriting it), while keeping NetworkManager the same for all, and as for now, this error just gives me headaches. Tried a lot of ways to fix it, but none helped.
Well, that does make sense, I’ve spent some time trying to see what sets up those handlers, but I couldn’t. Now I know, thanks. But I still don’t understand why does this happen. PlayerPrefab does have NetworkIdentity, NetworkServer.AddPlayerForConnection is invoked on the server in both cases, and both methods are executed after player is connected - SpawnPlayerShip is called upon user respawn request after connecting.
You could be passing the wrong kind of connection object. You need to pass a server-to-client connection object to NetworkServer.AddPlayerForConnection() , not a client-to-server connection object. Those are different on the host.
Yes, after several tweaks and workarounds, it turned to be true. Seems making game manager so independant of NetworkManager as I imagined is not really possible. Will have to re-plan it.
Perhaps Unity should have a way to differentiate if NetworkConnection is client->server or vice versa? it’d help a lot.
Oh, and also a way to send NetworkConnection. Seems it’s not possible even through raw messages.
Oh, and almost forgot: thanks for fast feedback. I’d spend ages trying to figure it out on my own.
Oh yeah, I’ve been looking at it few times, read the description and was like “well, so that won’t be useful in my case”. Now that you pointed it out, I’ve thought about it, tested, and it makes sense. I’ll keep it mind. Thanks again.