NetworkManager.Singleton.LocalClient.PlayerObject returns null in client side

Hi,
I am trying to get the PlayerObject. It works in Server side, but in client side it returns null.

I have tried:

NetworkManager.Singleton.LocalClient.PlayerObject
NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject()

with the same result.

I am using netcode for gameobjects 1.11.0

I’ve seen that this bug was reported years ago and seemed to be fixed, I don’t know if it has come back or maybe I should get the PlayerObject in other way

It supposed to be fixed here:

Other threads talking about the same

Thank you

The issue may be down to when/where you’re trying to access it. If you subscribe to

NetworkManager.Singleton.OnClientConnectedCallback it’s available on and after that call.

2 Likes

You are right, you can get the LocalClient.PlayerObject in the callback. I am not sure why is behaving differently in Server and Client, but it is.

This is the full code I’ve used to check the behaviour

using Unity.Netcode;
using UnityEngine;

public class LocalClientTest : NetworkBehaviour
{
    public override void OnNetworkSpawn()
    {
        AssertNotNull(NetworkManager.Singleton.LocalClient.PlayerObject, "OnNetworkSpawn"); //Client => Null. Server => Not Null
        AssertNotNull(NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject(), "OnNetworkSpawn"); //Client => Null. Server => Not Null
    }

    protected override void OnNetworkPostSpawn()
    {
        AssertNotNull(NetworkManager.Singleton.LocalClient.PlayerObject, "OnNetworkPostSpawn");//Client => Null. Server => Not Null
        AssertNotNull(NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject(), "OnNetworkPostSpawn");//Client => Null. Server => Not Null
    }

    protected override void OnNetworkPreSpawn(ref NetworkManager networkManager)
    {
        AssertNotNull(NetworkManager.Singleton.LocalClient.PlayerObject, "OnNetworkPreSpawn"); //Client => Null. Server => Not Null
        AssertNotNull(NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject(), "OnNetworkPreSpawn"); //Client => Null. Server => Not Null
    }

    private void OnClientConnected(ulong obj)
    {
        AssertNotNull(NetworkManager.Singleton.LocalClient.PlayerObject, "OnClientConnected");//Client => Not Null. Server => Not Null
        AssertNotNull(NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject(), "OnClientConnected");//Client => Not Null. Server => Not Null
    }

    private void AssertNotNull(Object obj, string message)
    {
        string prefix = $"Is Server: {IsServer}";
        if(obj != null)
        {
            Debug.Log($"{prefix} {message} is not null");
        }
        else
        {
            Debug.LogError($"{prefix} {message} is null");
        }
    }

    private void Start() => AddNetworkManagerCallbacks();

    public override void OnDestroy()
    {
        RemoveNetworkManagerCallbacks();
        base.OnDestroy();
    }


    private void AddNetworkManagerCallbacks()
    {
        var netMan = NetworkManager.Singleton;
        if (netMan != null)
        {
            // ensure we never register callbacks twice
            RemoveNetworkManagerCallbacks();

            netMan.OnClientConnectedCallback += OnClientConnected;
        }
    }

    private void RemoveNetworkManagerCallbacks()
    {
        var netMan = NetworkManager.Singleton;
        if (netMan != null)
        {
            netMan.OnClientConnectedCallback -= OnClientConnected;
        }
    }
}

Is LocalClientTest an in-scene object as there are timing differences between server and client. On the server Player is spawned before LocalClientTest, on the client it’s spawned afterwards (but the server’s Player is spawned before both). If you’re spawning objects yourself that order is maintained, or it was last time I checked. I don’t know where the Player and in-scene objects fit into this though.

This test was done with a in-scene object. It may be worth testing in a spawned prefab too.

I didn’t think that could be a different because the PlayerObject is your own PlayerObject, so I though that the PlayerObject instantiation would be the first in the execution order when the client connects to the server, no matter if you are host-client or simple-client