[UNet] Spawning The Player

I’m having issues trying to spawn the player with UNet. I don’t want to go through the NetworkManager since I have to set some variables once the player is spawned, but once I spawn the player “IsLocalPlayer” and “HasAuthority” are false (and yes, LocalPlayerAuthority is checked on the NetworkIdentity), so the object is not controllable. Here’s the script.

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

public class PlayerSpawn : NetworkBehaviour {

	public GameObject MainTrainer;
	public GameObject MainCam;
	public MonsterInfo monInfo;

	void Start(){
		CreatePlayer ();
	}

	public void CreatePlayer(){
		GameObject Trainer = null;
		Trainer = (GameObject)GameObject.Instantiate (MainTrainer, transform.position, Quaternion.identity);

		GameObject Cam = (GameObject)GameObject.Instantiate (MainCam, transform.position, Quaternion.identity);
		Trainer.GetComponent<TPBattle> ().mainCam = Cam.GetComponent<FreeLookCam>();
		Trainer.GetComponent<TPBattle> ().monInfo = monInfo;
		Cam.GetComponent<FreeLookCam> ().SetTarget (Trainer.transform);

        NetworkServer.Spawn(Trainer);
	}
}

This script is attached to an object on the server side, right? If not, it should be!

The NetworkServer.Spawn is useful when you want to spawn a server-controlled object. However, there is the NetworkServer.AddPlayerForConnection function which can be used to spawn an object and set the target connection as the owner.

The add player functionality can be requested on client-side, by calling ClientScene.AddPlayer.

[Edit]

And you should rethink the system. The camera should be spawned on the client, and only one, shouldn’t it? When you add a player for a client, the instantiated object’s isLocalPlayer will be true. Besides that you can use the OnStartLocalPlayer function override from NetworkBehaviour. When this function is called, you should spawn your camera object.

Here is a little example:

// shared class, this can be used by the client and the server as well

public class Player : NetworkBehaviour
{
    [SerializeField]
    private GameObject _cameraPrefab = null; // camera prefab
    
    public override void OnStartLocalPlayer() // this is our player
    {
        base.OnStartLocalPlayer();

        GameObject cameraObj = GameObject.Instantiate(_cameraPrefab); // add camera
        cameraObj.GetComponent<MyCameraScript>().SetTarget(transform); // setup camera
        
        // add input handler component OR (see Update)
    }
    
    private void Update()
    {
        if (!base.isLocalPlayer)
            return;
            
        // update your input here
    }
}

// server side

public class PlayerSpawner : MonoBehaviour
{
    [SerializeField]
    private GameObject _playerPrefab = null;

    private void SpawnPlayer(NetworkConnection conn) // spawn a new player for the desired connection
    {
        GameObject playerObj = GameObject.Instantiate(_playerPrefab); // instantiate on server side
        NetworkServer.AddPlayerForConnection(conn, playerObj, 0); // spawn on the clients and set owner
    }
}

NOTE: you can use MsgType.AddPlayer typed message to actually add the player. Something like this:

// server side

private void Setup()
{
    // ...

    NetworkServer.RegisterHandler(MsgType.AddPlayer, OnClientAddPlayer);
    // ...
}

private void OnClientAddPlayer(NetworkMessage netMsg)
{
    AddPlayerMessage msg = netMsg.ReadMessage<AddPlayerMessage>();
    if (msg.playerControllerId == 0) // if you wanna check this
    {
        Debug.Log("Spawning player...");
        SpawnPlayer(netMsg.conn); // the above function
    }
}

Try look in to NetworkManager how they spawn a player