Skip to content

Host's PlayerObject becomes null after Despawning a transferred client PlayerObject (DontDestroyWithOwner) #3938

@T-Huckle

Description

@T-Huckle

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

Image

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    stat:awaiting-triageStatus - Awaiting triage from the Netcode team.stat:importStatus - Issue is going to be saved internallystat:reply-neededAwaiting reply from Unity accounttype:bugBug Report

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions