Description
The PlayerObject of the host appears to be nulled out when a different object (of the same type) gets despawned and has is also owned by the host.
Reproduce Steps
Have a network object that gets marked with
GetComponent<NetworkObject>().DontDestroyWithOwner = true;
In my setup, my player object was not set as the default player object. Instead I explicitly spawned with SpawnAsPlayerObject
When the client disconnects - set a delayedDespawn coroutine, then despawn that object. After which, the hosts PlayerObject becomes null
private IEnumerator DelayDespawnCoroutine(PlayerController pc, PlayerController hostPc) {
// Host is always ID 0
Debug.Log("Host player number: " + NetworkManager.Singleton.ConnectedClients[0].PlayerObject?.GetComponent<PlayerController>().PlayerNumber);
yield return new WaitForSeconds(5);
var obj = pc.GetComponent<NetworkObject>();
if (obj != null && obj.IsSpawned) {
// Orphaned Network Object now as the same OwnerClientId as the host
Debug.Log($"Despawning object with OwnerClientId: {obj.OwnerClientId}");
// We see this print out the hosts PlayerNumber (1 in this scenario)
Debug.Log("Host player number: " + NetworkManager.Singleton.ConnectedClients[0].PlayerObject?.GetComponent<PlayerController>().PlayerNumber);
// We see this print out the playerNumber of the disconnected client (3 in this scenario - these are different object)
Debug.Log("Despawning Player Number: " + pc.PlayerNumber);
//Despawn and destroy the NetworkObject
obj.Despawn(true);
// No Longer prints out 1 as PlayerObject has now become null.
Debug.Log("Host player number: " + NetworkManager.Singleton.ConnectedClients[0].PlayerObject?.GetComponent<PlayerController>().PlayerNumber);
}
else {
Debug.Log("No despawn: ");
Debug.Log(obj);
}
}
Actual Outcome
Host loses a reference to its PlayerObject
Expected Outcome
The NetworkObject succesfully despawns and the Host's PlayerObject remains the same
Environment
- OS: Windows 11
- Unity Version: 6000.3.8f1
- Netcode Version: 2.11.0
- Netcode Topology: Client-Server
Additional Context
Can work around by reassigning the PlayerObject
obj.Despawn(true);
if (NetworkManager.Singleton.ConnectedClients.TryGetValue(0, out var hostClient) &&
hostClient.PlayerObject == null) {
hostClient.PlayerObject = hostPc.GetComponent<NetworkObject>();
Debug.Log("Restored host PlayerObject after despawn");
}
I believe the issue is here in NetworkSpawnManager inside OnDespawnObject.
if (networkObject.IsPlayerObject)
{
RemovePlayerObject(networkObject, destroyGameObject);
}
or inside RemovePlayerObject
if (m_PlayerObjectsTable.ContainsKey(playerObject.OwnerClientId))
{
m_PlayerObjectsTable[playerObject.OwnerClientId].Remove(playerObject);
if (m_PlayerObjectsTable[playerObject.OwnerClientId].Count == 0)
{
m_PlayerObjectsTable.Remove(playerObject.OwnerClientId);
}
}
Should check to make sure that m_PlayerObjectsTable[playerObject.OwnerClientId] == playerObject
Description
The PlayerObject of the host appears to be nulled out when a different object (of the same type) gets despawned and has is also owned by the host.
Reproduce Steps
Have a network object that gets marked with
GetComponent<NetworkObject>().DontDestroyWithOwner = true;In my setup, my player object was not set as the default player object. Instead I explicitly spawned with
SpawnAsPlayerObjectWhen the client disconnects - set a delayedDespawn coroutine, then despawn that object. After which, the hosts PlayerObject becomes null
Actual Outcome
Host loses a reference to its PlayerObject
Expected Outcome
The NetworkObject succesfully despawns and the Host's PlayerObject remains the same
Environment
Additional Context
Can work around by reassigning the PlayerObject
I believe the issue is here in
NetworkSpawnManagerinsideOnDespawnObject.or inside
RemovePlayerObjectShould check to make sure that
m_PlayerObjectsTable[playerObject.OwnerClientId] == playerObject