Last connected NetworkClient's PlayerObject is null

I’m not sure if this is a bug or not, but this behavior is not very convenient.

Project has “connection approval” on server side and if connection is approved then I set “approvalResponse.CreatePlayerObject = true”.

On the first-connected player side, this execution order occurs when the local player joins the server.

PlayerObject => OnNetworkSpawn
NetworkManager => OnClientConnectedCallback
NetworkManager => OnConnectionEvent

But when second player joined the server, on first-connected player side events order like:

NetworkManager => OnConnectionEvent
PlayerObject => OnNetworkSpawn

This is the issue point. I try to get new player’s PlayerObjects from “NetworkManager.Singleton.ConnectedClientsList” it returns null. It returns NetworkClient object but NetworkClient.PlayerObject is null.

I could create an asynchronous method on where I try to get PlayersObject or I can trigger a event with PlayerObject parameter.

But I think there should be a better and easier way to get to this object.
Or
Which method should I listen to wait for each NetworkObjects to complete correctly?

Unity : 6000.0.31f1
NFG : 2.2.0

Could you post your code?

The connection event should not be used to get player objects. Perhaps you need to use the new OnPostNetworkSpawn to defer it after spawning? Otherwise a coroutine that yields null and the performs the task should do.

1 Like

Actually, I can’t share all classes because there are more than one classes. But I can share some code about the situation.
Since I need to get the NetworkVariable data of the new connected player, I need to access the Player Object.

public class ClientNetworkObject : NetworkBehaviour
{

       protected override void OnNetworkSpawn()
        {
            if (!IsLocalPlayer)
            {
                NetworkClient client = ClientNetworkManager.GetOpponentNetworkClient(); //The game is a two-players game.
                CustomDebug.Log($"ClientNetworkObject-OnNetworkSpawn-ClientId:{client.ClientId}, PlayerObject:{client.PlayerObject}");
               
               //client.PlayerObject is  null

            }
        }

        protected override void OnNetworkPostSpawn()
        {
            if (!IsLocalPlayer)
            {
                NetworkClient client = ClientNetworkManager.GetOppNetworkClient();
                CustomDebug.Log($"ClientNetworkObject-OnNetworkPostSpawn-ClientId:{client.ClientId}, PlayerObject:{client.PlayerObject}");

               //client.PlayerObject is not null

              ClientNetworkManagerEvents.OnSpawnedOpponentPlayerObject?.Invoke();
            }
        }

The class that listens to “Client NetworkManagerEvents.OnSpawnedOpponentPlayerObject” is trying to get the opponent’s NetworkVariable data from “NetworkManager.Singleton.ConnectedClientsList”

Yes, OnConnectionEvent may not be suitable to receive data of new connected player.

Thanks for the remembered the new OnPostNetworkSpawn event. I checked the documentation page than I decided to use OnPostNetworkSpawn events which are more suitable for this situation.

1 Like

Hi @Mj-Kkaya,

You are correct in your usage of OnNetworkPostSpawn.
Just as a side note:
Since it looks like your script is within a NetworkBehaviour component on the player network prefab and it is a 2 player game only, you already have the information you need within the OnNetworkSpawn method without having to grab the NetworkClient:

public class PlayerNetworkBehaviour : NetworkBehaviour
{
    public NetworkObject Opponent { get; private set; }

    public override void OnNetworkSpawn()
    {
        if (!IsLocalPlayer) 
        {
            Opponent = NetworkObject;
            CustomDebug.Log($"[Opponent] Client-{Opponent.OwnerClientId} | PlayerObject:{Opponent.name}-{Opponent.NetworkObjectId}.");
        }
        base.OnNetworkSpawn();
    }
}

Figured it was worth providing a different perspective to accomplish the same thing.

1 Like