Skip to content

Commit b2bbc5e

Browse files
Merge develop-3.x.x into chore/unified-hybrid-tests-enabled-environment-var
2 parents 130ee8d + 846065a commit b2bbc5e

4 files changed

Lines changed: 35 additions & 2 deletions

File tree

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
2929

3030
### Fixed
3131

32+
- Fixed issue where scenes additively loaded before a session started were tracked as loaded on the server but had no scene handle entries, which caused `NetworkSceneManager.UnloadScene` to log an error and leave the scene registered as loaded even though it unloaded on all peers. (#4146)
3233
- Issue with not being able to spawn initially disabled in-scene placed objects. (#4093)
3334
- Issue with pre-instantiated network prefab instances being marked as in-scene placed. Now pre-instantiated network prefabs are dynamically spawned. (#4093)
3435
- Issue where a user could spawn runtime created `NetworkObject` that has a GlobalObjectIdHash of zero. These are not valid instances and will no longer be allowed to spawn. (#4093)

com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -847,7 +847,7 @@ internal NetworkSceneManager(NetworkManager networkManager)
847847
for (int i = 0; i < SceneManager.sceneCount; i++)
848848
{
849849
var loadedScene = SceneManager.GetSceneAt(i);
850-
ScenesLoaded.Add(loadedScene.handle, loadedScene);
850+
UpdateServerClientSceneHandle(loadedScene.handle, loadedScene.handle, loadedScene);
851851
}
852852
SceneManagerHandler.PopulateLoadedScenes(ref ScenesLoaded, NetworkManager);
853853
}

com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTestHelpers.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,9 @@ private static void SceneManagerValidationAndTestRunnerInitialization(NetworkMan
586586
}
587587
return;
588588
}
589-
networkManager.SceneManager.ServerSceneHandleToClientSceneHandle.Add(scene.handle, scene.handle);
589+
590+
// The server already registers every scene loaded prior to startup, so only add the test runner scene if it is not already there.
591+
networkManager.SceneManager.ServerSceneHandleToClientSceneHandle.TryAdd(scene.handle, scene.handle);
590592
}
591593
}
592594

testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerStartupTests.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ internal class NetworkSceneManagerStartupTests : NetcodeIntegrationTest
2121
{
2222
private const string k_ActiveScene = "SessionSynchronize";
2323
private const string k_AdditionalScene = "InSceneNetworkObjectMovesToDDOL";
24+
private const string k_PreLoadedScene = "EmptyScene1";
2425

2526
private readonly List<NetworkObject> m_ObjectsInScenes = new List<NetworkObject>();
2627
private Scene m_OriginalActiveScene;
@@ -141,6 +142,35 @@ public IEnumerator AllExistingObjectsAreSpawnedAtStartup([Values] LoadSceneMode
141142
AssertOnTimeout("Timed out waiting for objects to spawn on all clients!");
142143
}
143144

145+
/// <summary>
146+
/// Validates that a scene additively loaded before the session started is tracked well enough
147+
/// to be unloaded through <see cref="NetworkSceneManager"/> without error.
148+
/// </summary>
149+
[UnityTest]
150+
public IEnumerator UnloadPreLoadedScene()
151+
{
152+
yield return PreLoadScene(k_PreLoadedScene);
153+
var preLoadedScene = m_SceneLoaded;
154+
155+
m_CanStart = true;
156+
yield return StartServerAndClients();
157+
158+
// Scenes loaded before the session started are registered in both the loaded scenes and the
159+
// scene handle tables, otherwise unloading them fails part way through and leaks the entry.
160+
var sceneManager = GetAuthorityNetworkManager().SceneManager;
161+
Assert.IsTrue(sceneManager.ScenesLoaded.ContainsKey(preLoadedScene.handle), $"{k_PreLoadedScene} is not in {nameof(NetworkSceneManager.ScenesLoaded)}!");
162+
Assert.IsTrue(sceneManager.ServerSceneHandleToClientSceneHandle.ContainsKey(preLoadedScene.handle), $"{k_PreLoadedScene} is not in {nameof(NetworkSceneManager.ServerSceneHandleToClientSceneHandle)}!");
163+
164+
var status = sceneManager.UnloadScene(preLoadedScene);
165+
Assert.AreEqual(SceneEventProgressStatus.Started, status, $"{nameof(NetworkSceneManager.UnloadScene)} returned {status}!");
166+
167+
yield return WaitForConditionOrTimeOut(() => !preLoadedScene.isLoaded);
168+
AssertOnTimeout($"Timed out waiting for {k_PreLoadedScene} to unload!");
169+
170+
Assert.IsFalse(sceneManager.ScenesLoaded.ContainsKey(preLoadedScene.handle), $"{k_PreLoadedScene} was unloaded but is still in {nameof(NetworkSceneManager.ScenesLoaded)}!");
171+
Assert.IsFalse(sceneManager.ServerSceneHandleToClientSceneHandle.ContainsKey(preLoadedScene.handle), $"{k_PreLoadedScene} was unloaded but is still in {nameof(NetworkSceneManager.ServerSceneHandleToClientSceneHandle)}!");
172+
}
173+
144174
#region Scene loading and related methods
145175

146176
/// <summary>

0 commit comments

Comments
 (0)