Skip to content

Commit

Permalink
fix: this fixes issues with multi scene loading on server and client (#…
Browse files Browse the repository at this point in the history
…965)

* fix: This fixes issues with multi scene loading on server and client. We never checked for when clients would unload from one scene and load to another scene and do it again over and over. This causes spawned list to null itself out because of lost references. This now allows ServerObjectManager and ClientObjectManager to check for it after scene changes.

* fix: stupid me did undo a test.

* fix: created a new test for the method we created. Also created a new removalCollection list we can keep reusing because constantly reallocating and deallocating during scene load might be bad. Not sure if this is better or worse.

* fix: james caught few gotchas. This is fix.
  • Loading branch information
dragonslaya84 committed Oct 10, 2021
1 parent f215cef commit e725a41
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 1 deletion.
3 changes: 3 additions & 0 deletions Assets/Mirage/Runtime/ClientObjectManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ void OnClientDisconnected(ClientStoppedReason reason)

void OnFinishedSceneChange(string scenePath, SceneOperation sceneOperation)
{
Client.World.RemoveDestroyedObjects();

PrepareToSpawnSceneObjects();
}

Expand Down Expand Up @@ -314,6 +316,7 @@ public void DestroyAllClientObjects()
// create copy so they can be removed inside loop
// allocation here are fine because is part of clean up
NetworkIdentity[] all = Client.World.SpawnedIdentities.ToArray();

foreach (NetworkIdentity identity in all)
{
if (identity != null && identity.gameObject != null)
Expand Down
11 changes: 11 additions & 0 deletions Assets/Mirage/Runtime/NetworkWorld.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ internal void RemoveIdentity(NetworkIdentity identity)
onUnspawn?.Invoke(identity);
}

internal void RemoveDestroyedObjects()
{
var removalCollection = new List<NetworkIdentity>(SpawnedIdentities);

foreach (NetworkIdentity identity in removalCollection)
{
if (identity == null)
SpawnedObjects.Remove(identity.NetId);
}
}

internal void RemoveIdentity(uint netId)
{
if (netId == 0) throw new ArgumentException("id can not be zero", nameof(netId));
Expand Down
2 changes: 2 additions & 0 deletions Assets/Mirage/Runtime/ServerObjectManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ void OnServerStopped()

void OnFinishedSceneChange(string scenePath, SceneOperation sceneOperation)
{
Server.World.RemoveDestroyedObjects();

SpawnOrActivate();
}

Expand Down
23 changes: 22 additions & 1 deletion Assets/Tests/Editor/NetworkWorldTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Collections.Generic;
using NSubstitute;
using NUnit.Framework;
using NUnit.Framework.Internal;
using UnityEngine;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;
Expand Down Expand Up @@ -299,5 +298,27 @@ public void ClearDoesNotInvokeEvent()
world.ClearSpawnedObjects();
unspawnListener.DidNotReceiveWithAnyArgs().Invoke(default);
}

[Test]
public void ClearDestoryedObjects()
{
AddValidIdentity(out uint id1, out NetworkIdentity identity1);
AddValidIdentity(out uint id2, out NetworkIdentity identity2);
AddValidIdentity(out uint id3, out NetworkIdentity identity3);
AddValidIdentity(out uint id4, out NetworkIdentity nullIdentity);

Object.DestroyImmediate(nullIdentity);

Assert.That(world.SpawnedIdentities.Count, Is.EqualTo(4));

world.RemoveDestroyedObjects();

foreach (NetworkIdentity identity in world.SpawnedIdentities)
{
Assert.That(identity != null);
}

Assert.That(world.SpawnedIdentities.Count, Is.EqualTo(3));
}
}
}

0 comments on commit e725a41

Please sign in to comment.