How do I make the cameras spawn correctly in both players with Netcode? (Beginner)

public override void OnNetworkSpawn()
{
    base.OnNetworkSpawn();

    playerScript = GetComponent<PlayerScript>();
    inventoryScript = GameObject.FindWithTag("Inventory").GetComponent<Inventory>();

    if (IsOwner)
    {
        AskForSpawnServerRpc();
    }
}

[ServerRpc]
private void AskForSpawnServerRpc()
{
    ulong clientId = OwnerClientId;

    Transform instantiateCam = Instantiate(camPrefab).transform;
    NetworkObject camNetObj = instantiateCam.GetComponent<NetworkObject>();
    camNetObj.SpawnWithOwnership(clientId);

    Transform instantiateHand = Instantiate(handPrefab).transform;
    NetworkObject handNetObj = instantiateHand.GetComponent<NetworkObject>();
    handNetObj.SpawnWithOwnership(clientId);

    StartCoroutine(ReparentAfterSpawn(camNetObj.transform, player.transform));
    StartCoroutine(ReparentAfterSpawn(handNetObj.transform, camNetObj.transform));
}

private IEnumerator ReparentAfterSpawn(Transform child, Transform newParent)
{
    yield return null;
    child.SetParent(newParent);
}

Hello, I’m pretty new to unity and I am trying to understand why does my script doesn’t work. It is working perfectly fine when I instantiate only the host, but when a client join, the host camera goes to the client and the client can’t turn his own. (Btw the camera is linked to the player so when it can’t turn that means the player can’t turn).
Hope that this is a small problem, thank you!

Best not to parent the camera at all. This isn’t necessary, and with Cinemachine it’s not even necessary to write a script that targets an object. Just assign a tracking target to the Cinemachine virtual camera.

In any case you do NOT want to make the camera a networked object. What’s the point? Nobody else sees the camera (or the first person objects like hand, weapon, etc) other than the local player.

The old-school way of doing things would be to create a player prefab with camera and so forth already parented. Then you only need to do this in OnNetworkSpawn:

localOnlyChildObjects.SetActive(IsOwner);

Then just parent anything that only the local player sees to the localOnlyChildObjects child. If any of these child objects need to do something with networking (*), they just route it through the player prefab’s script (on the root object) that handles networking. And the other way around is registering for C# events raised by the root network script.

(*) This is required because any object with a NetworkObject on it cannot be SetActive(false). You can however enable/disable components as you see fit but it’s a bit more cumbersome because you’ll want those components to start off disabled, so they don’t run Awake etc.

1 Like

I haven’t released this to our v2.x examples branch yet, but it has enough to provide an example of how you can parent a single main camera under the local player object instance.
PlayerControlAndSpawning.zip (149.2 KB)

In the event you wanted to do that as opposed to using Cinemachine.

1 Like