Hello,
If I try to create a lobby, and join it from another device, Then from the other device to leave and join again It doesn’t work and I get the following error on the server and nothing on the client:
MissingReferenceException: The object of type 'NetworkObject' has been destroyed but you are still trying to access it.
No network object spawns and the host doen’t get a clientConnected callback.
This worked before and I don’t know what causes this bug.
Can someone help me?
Sounds like the typical issue of manually destroying the NetworkManager (don’t do that!) or otherwise improperly shutting down networking, at least more than what should be done.
Typical setup for networking should include a loading or launch scene that contains nothing but the NetworkManager and other stuff that needs to be initialized first, and that scene loads the next scene from Update() of a script (I think you cannot load a scene earlier). This prevents NetworkManager from being duplicated when you reload the scene, which is why some devs started to destroy the NetworkManager to kill the duplicate.
But if you don’t destroy it then the moment you go back to the loading scene it is duplicated isn’t it?
Instead of destroying it I can put it in a scene that I never go back to but in my game the network manager must be on the play scene unless I make some big changes. Is there any other solution? Can I remove the don’t destroy on load from the NetworkManager?
You’re free to destroy the network manager yourself, DontDestroyOnLoad just prevents it from being destroyed on a scene load. As CodeSmile said though, it’s preferable to have the network manager in an earlier scene rather than having to destroy it.
If you want to go the destroy route take a look at the network manager’s OnServerStopped/OnClientStopped callbacks, keep in mind they’re called before shutdown so you’ll have to experiment with them to make sure you give the network manager enough time to shutdown and clean up.
The callbacks were introduced in 1.4.0 so now might be a good time to update.
No one ever goes back to the loading scene.
I mean the loading scene that appears for a split second as the app launches, not the “level is loading” scene. That may be confusing, so let’s call it the “launch scene”. You never ever go back to that one!
The new versions use a prefab list outside the network manager and I can’t put my prefabs there because of how I implemented it. I will try to wait until shutdownInProgress becomes false and then destroy it and see if it makes a difference.
Didn’t the prefab list changes make it more flexible? It’s up to you but I wouldn’t want to be tied to an older version and not be able to take advantage of improvements and more importantly the fixes, unless your project is nearing completion.
I implemented the networkobjects when I wasn’t so good with netcode and it seems like somehow I am spawning in-scene placed object dinamically. This means the prefabs on the manager’s list must be the in scene placed objects, and the new system doesn’t allow me to put them on the list. Also, I have to put the network manager in the same scene so I can drag the objects to it.
My project is near completion and this problem with connection is the only thing that isn’t working now.
Destroying the network manager after it finished shutting off doesn’t fix the problem and I still can’t reconnect.
It’s hard to say what the problem is, compare the network manager’s configuration on connection and reconnection. Is StartClient returning true? It could be a timing issue but I’m just guessing really.
Okay so couple of things I found:
- The problem is in the server, if a client leaves then no client can join anymore
- This isn’t related to destroying the networkManager because even if I don’t destroy it on the leaving client no client can join.
This is my disconnection code:
public async void comeHome()
{
try
{
wantToComeHome = true;
if (NetworkManager.Singleton.IsServer)
{
await LobbyService.Instance.DeleteLobbyAsync(lobbyId);
}
else
{
await LobbyService.Instance.RemovePlayerAsync(lobbyId, playerId);
}
Debug.Log("sucssefully dissconected from lobby");
}
catch (LobbyServiceException e)
{
Debug.Log(e);
}
//shutdown
try
{
NetworkManager.Shutdown();
//StartCoroutine(waitToShutdown());
}
catch
{
Debug.Log("Network manager already shut down");
wantToComeHome = false;
}
}
Then after that I wait to the shutdown to complete (destroy the network manager) and switch scenes.
Going back to the original error on the server:
MissingReferenceException: The object of type 'NetworkObject' has been destroyed but you are still trying to access it.
What object is this, is it the Player of the disconnecting client, can you see what’s accessing it in the stacktrace?
This is the full error message:
MissingReferenceException: The object of type 'NetworkObject' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
Unity.Netcode.SceneEventData.SortParentedNetworkObjects (Unity.Netcode.NetworkObject first, Unity.Netcode.NetworkObject second) (at Library/PackageCache/com.unity.netcode.gameobjects@1.2.0/Runtime/SceneManagement/SceneEventData.cs:364)
System.Collections.Generic.ArraySortHelper`1[T].InsertionSort (T[] keys, System.Int32 lo, System.Int32 hi, System.Comparison`1[T] comparer) (at <890d6fe26e8c408ea64b353e791fafce>:0)
System.Collections.Generic.ArraySortHelper`1[T].IntroSort (T[] keys, System.Int32 lo, System.Int32 hi, System.Int32 depthLimit, System.Comparison`1[T] comparer) (at <890d6fe26e8c408ea64b353e791fafce>:0)
System.Collections.Generic.ArraySortHelper`1[T].IntrospectiveSort (T[] keys, System.Int32 left, System.Int32 length, System.Comparison`1[T] comparer) (at <890d6fe26e8c408ea64b353e791fafce>:0)
System.Collections.Generic.ArraySortHelper`1[T].Sort (T[] keys, System.Int32 index, System.Int32 length, System.Comparison`1[T] comparer) (at <890d6fe26e8c408ea64b353e791fafce>:0)
Rethrow as InvalidOperationException: Failed to compare two elements in the array.
System.Collections.Generic.ArraySortHelper`1[T].Sort (T[] keys, System.Int32 index, System.Int32 length, System.Comparison`1[T] comparer) (at <890d6fe26e8c408ea64b353e791fafce>:0)
System.Collections.Generic.List`1[T].Sort (System.Comparison`1[T] comparison) (at <890d6fe26e8c408ea64b353e791fafce>:0)
Unity.Netcode.SceneEventData.AddSpawnedNetworkObjects () (at Library/PackageCache/com.unity.netcode.gameobjects@1.2.0/Runtime/SceneManagement/SceneEventData.cs:248)
Unity.Netcode.NetworkSceneManager.SynchronizeNetworkObjects (System.UInt64 clientId) (at Library/PackageCache/com.unity.netcode.gameobjects@1.2.0/Runtime/SceneManagement/NetworkSceneManager.cs:1575)
Unity.Netcode.NetworkManager.HandleConnectionApproval (System.UInt64 ownerClientId, Unity.Netcode.NetworkManager+ConnectionApprovalResponse response) (at Library/PackageCache/com.unity.netcode.gameobjects@1.2.0/Runtime/Core/NetworkManager.cs:2274)
Unity.Netcode.ConnectionRequestMessage.Handle (Unity.Netcode.NetworkContext& context) (at Library/PackageCache/com.unity.netcode.gameobjects@1.2.0/Runtime/Messaging/Messages/ConnectionRequestMessage.cs:165)
Unity.Netcode.MessagingSystem.ReceiveMessage[T] (Unity.Netcode.FastBufferReader reader, Unity.Netcode.NetworkContext& context, Unity.Netcode.MessagingSystem system) (at Library/PackageCache/com.unity.netcode.gameobjects@1.2.0/Runtime/Messaging/MessagingSystem.cs:511)
Unity.Netcode.MessagingSystem.HandleMessage (Unity.Netcode.MessageHeader& header, Unity.Netcode.FastBufferReader reader, System.UInt64 senderId, System.Single timestamp, System.Int32 serializedHeaderSize) (at Library/PackageCache/com.unity.netcode.gameobjects@1.2.0/Runtime/Messaging/MessagingSystem.cs:384)
UnityEngine.Debug:LogException(Exception)
Unity.Netcode.MessagingSystem:HandleMessage(MessageHeader&, FastBufferReader, UInt64, Single, Int32) (at Library/PackageCache/com.unity.netcode.gameobjects@1.2.0/Runtime/Messaging/MessagingSystem.cs:388)
Unity.Netcode.MessagingSystem:ProcessIncomingMessageQueue() (at Library/PackageCache/com.unity.netcode.gameobjects@1.2.0/Runtime/Messaging/MessagingSystem.cs:404)
Unity.Netcode.NetworkManager:OnNetworkEarlyUpdate() (at Library/PackageCache/com.unity.netcode.gameobjects@1.2.0/Runtime/Core/NetworkManager.cs:1600)
Unity.Netcode.NetworkManager:NetworkUpdate(NetworkUpdateStage) (at Library/PackageCache/com.unity.netcode.gameobjects@1.2.0/Runtime/Core/NetworkManager.cs:1532)
Unity.Netcode.NetworkUpdateLoop:RunNetworkUpdateStage(NetworkUpdateStage) (at Library/PackageCache/com.unity.netcode.gameobjects@1.2.0/Runtime/Core/NetworkUpdateLoop.cs:185)
Unity.Netcode.<>c:<CreateLoopSystem>b__0_0() (at Library/PackageCache/com.unity.netcode.gameobjects@1.2.0/Runtime/Core/NetworkUpdateLoop.cs:208)
I am not sure which object causes the issue but it’s in this code:
/// <summary>
/// Sorts the synchronization order of the NetworkObjects to be serialized
/// by parents before children.
/// </summary>
/// <remarks>
/// This only handles late joining players. Spawning and nesting several children
/// dynamically is still handled by the orphaned child list when deserialized out of
/// hierarchical order (i.e. Spawn parent and child dynamically, parent message is
/// dropped and re-sent but child object is received and processed)
/// </remarks>
private int SortParentedNetworkObjects(NetworkObject first, NetworkObject second)
{
// If the first has a parent, move the first down
if (first.transform.parent != null)
{
return 1;
}
else // If the second has a parent and the first does not, then move the first up
if (second.transform.parent != null)
{
return -1;
}
return 0;
}
Yeah, it’s possible either first or second is null. I compared the HandleConnectionApproval code for 1.5.1 and 1.2.0, it’s been moved around a bit but looks essentially the same but I can’t say for sure.
The only issue similar to yours I’ve found is this one , it might be worth messaging him to see if he found a fix for the problem.
According to the line number, fist is null.
I also found this similar but it is a bit old. I will try anyway.
If I upgrade to netcode 1.5.1 the client is able to rejoin but I am not sure this is optimal because I get the following message on my network prefab list
and if I migrate it nothing works.
The old prefab list in the network manager has been changed to support scriptable objects containing their own list. There should be a scriptable object called NetworkPrefabs somewhere in your project with a reference to it in the network manager, click on the object list in the network manager to find where it is and check it’s populated.
If you’re using ParrelSync you might have to do the same in the clones if it allows it, if it doesn’t delete and recreate the clones.
Yes but if I do that it says missing refrence on all my in-scene placed networkObjects and I can’t assign them to the list.
Why do you need to add them to the prefab list, shouldn’t in-scene objects be spawned automatically? I vaguely remember trying to tie in-scene and prefab list objects together and I couldn’t get it to work outside the network manager scene.
I really don’t know. All I know is I get errors if the objects aren’t on the network prefab list. I am not switching scenes so that’s okay