NetworkManager.OnServerAddPlayer() to add two GameObjects

Hello, everyone! I’m trying to build a very clean platform game in order to prototype multiplayer for a larger project. In my game, each player is represented by two GameObjects: ActorControlInterface and Actor.

The intended network architecture is as follows:

  • ActorControlInterface: Captures keyboard/mouse/joystick input and synchronizes the input state with the server.
  • Actor: The player’s character, with sounds, graphics and world position. This object reads from the ActorControlInterface’s input state and actually drives the player.
  • The game is deterministic enough that if we assume that the server’s view of the ActorControlInterface updates consistently some X latency behind the client and that no other player interferes with that Actor, that the Actor for that ActorControlInterface should move exactly the same on both client and server.

**Flowchart: http://i.imgur.com/PkOb2PK.png **

My plan here is to have both the ActorControlInterface and Actor exist on both the Client and Server and simulate independently, so without synchronizing the Actors’ states over the network. The intention is that the server’s simulation should be exactly “X” ms behind each player’s local view of their own player, where X = latency for that player’s connection.

As can be seen in the green text on that flowchart, the client Actor records it’s movement history and compares it to what the server reports from time to time (about 2 * ping ms behind what the client sees).

The newbie problem:

Ultimately, I want to create both an ActorControlInterface and an Actor as separate GameObjects when a client connects to my server. I’m using a custom implementation of NetworkManager, where I spawn ActorControlInterface in as the player object. I’m trying to overload OnServerAddPlayer to also Network.Instantiate() in the Actor for that player which should be owned by the server.

public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId, NetworkReader extraMessageReader) {
    GameObject playerObj = (GameObject)Network.Instantiate(playerActorPrefab, Vector3.zero, Quaternion.identity, 0) as GameObject;
    Debug.Log("This line never gets called.");
    OnServerAddPlayer(conn, playerControllerId, extraMessageReader);
}

However, as Debug.Log() mentions above, that line never shows up in the console. Should I be doing this some other way? Does NetworkManager.OnServerAddPlayer() not get called in this manner?

I appreciate any attention this might get, as anything I produce seems hackish at best and I haven’t been able to get the behaviour that I want. As an added note, all my ActorControlInterface and Actor interaction works on either the client or server if I run it in the editor and hook up an Actor in manually through the inspector.

My thanks in advance to anyone who reads this.

It seems that you are using the old networking API instantiate instead of the UNET way of spawning objects over the network.

// The old networking API:
Network.Instantiate(prefab)


// In UNET:
GameObject obj = GameObject.Instantiate(prefab) as GameObject;
NetworkServer.Spawn(obj);

// or (for actual player objects)
GameObject obj = GameObject.Instantiate(prefab) as GameObject;
NetworkServer.AddPlayerForConnection( connection, obj, playerControllerId );

Also, just under the Debug.Log(…) you have line:

OnServerAddPlayer(conn, playerControllerId, extraMessageReader);

I can’t say for sure, but to me it seems that this is a recursive call to method itself, leading to an infinite loop. You probably are trying to use the base implemetation here, which would be:

base.OnServerAddPlayer(conn, playerControllerId, extraMessageReader);

Additionally, you should make sure that the GameObject which has ActorControllerInterface on it has the “Local player authority” checked in its NetworkIdentity and that the Actor has it set to false. And, lastly, make sure you have added the prefab you are trying to spawn to the “Registered spawnable prefabs” list via inspector (or code) in NetworkManager.

In my project I have implementation that creates the player like this:

// Create the player "controller" object which has the client authority
GameObject playerController = (GameObject)GameObject.Instantiate(controllerPrefab);
NetworkServer.AddPlayerForConnection( connection, playerController, playerControllerId );

// Spawn the actual visible player character
GameObject playerCharacter = (GameObject)GameObject.Instantiate(characterPrefab);
NetworkServer.Spawn(playerCharacter);

// Set the appropriate controller on clients (client can use controller.isLocalPlayer 
// to determine if it is initializing its own character or the character of an another client)
playerCharacter.RpcSetController(playerController);

@Omi, you have to override one more method and call ClientScene.AddPlayer:

public override void OnClientConnect(NetworkConnection conn)
{
  ClientScene.AddPlayer(conn, 0);
}

This will eventually call OnServerAddPlayer, but Debug.Log() won’t work unfortunately.