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