diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md
index c4dabd9c37..8d9fda7706 100644
--- a/com.unity.netcode.gameobjects/CHANGELOG.md
+++ b/com.unity.netcode.gameobjects/CHANGELOG.md
@@ -14,6 +14,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
- Fixed issue where some temporary debug console logging was left in a merged PR. (#2562)
- Fixed the "Generate Default Network Prefabs List" setting not loading correctly and always reverting to being checked. (#2545)
+- Fixed issue where users could not use NetworkSceneManager.VerifySceneBeforeLoading to exclude runtime generated scenes from client synchronization. (#2550)
- Fixed missing value on `NetworkListEvent` for `EventType.RemoveAt` events. (#2542,#2543)
- Fixed issue where parenting a NetworkTransform under a transform with a scale other than Vector3.one would result in incorrect values on non-authoritative instances. (#2538)
- Fixed issue where a server would include scene migrated and then despawned NetworkObjects to a client that was being synchronized. (#2532)
diff --git a/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs b/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs
index 1443e334cf..91fd876187 100644
--- a/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs
+++ b/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs
@@ -786,9 +786,18 @@ private void SceneManager_ActiveSceneChanged(Scene current, Scene next)
/// true (Valid) or false (Invalid)
internal bool ValidateSceneBeforeLoading(uint sceneHash, LoadSceneMode loadSceneMode)
{
- var validated = true;
var sceneName = SceneNameFromHash(sceneHash);
var sceneIndex = SceneUtility.GetBuildIndexByScenePath(sceneName);
+ return ValidateSceneBeforeLoading(sceneIndex, sceneName, loadSceneMode);
+ }
+
+ ///
+ /// Overloaded version that is invoked by and .
+ /// This specifically is to allow runtime generated scenes to be excluded by the server during synchronization.
+ ///
+ internal bool ValidateSceneBeforeLoading(int sceneIndex, string sceneName, LoadSceneMode loadSceneMode)
+ {
+ var validated = true;
if (VerifySceneBeforeLoading != null)
{
validated = VerifySceneBeforeLoading.Invoke(sceneIndex, sceneName, loadSceneMode);
@@ -1744,24 +1753,22 @@ internal void SynchronizeNetworkObjects(ulong clientId)
continue;
}
- var sceneHash = SceneHashFromNameOrPath(scene.path);
-
// This would depend upon whether we are additive or not
// If we are the base scene, then we set the root scene index;
if (activeScene == scene)
{
- if (!ValidateSceneBeforeLoading(sceneHash, sceneEventData.LoadSceneMode))
+ if (!ValidateSceneBeforeLoading(scene.buildIndex, scene.name, sceneEventData.LoadSceneMode))
{
continue;
}
- sceneEventData.SceneHash = sceneHash;
+ sceneEventData.SceneHash = SceneHashFromNameOrPath(scene.path);
sceneEventData.SceneHandle = scene.handle;
}
- else if (!ValidateSceneBeforeLoading(sceneHash, LoadSceneMode.Additive))
+ else if (!ValidateSceneBeforeLoading(scene.buildIndex, scene.name, LoadSceneMode.Additive))
{
continue;
}
- sceneEventData.AddSceneToSynchronize(sceneHash, scene.handle);
+ sceneEventData.AddSceneToSynchronize(SceneHashFromNameOrPath(scene.path), scene.handle);
}
sceneEventData.AddSpawnedNetworkObjects();
diff --git a/testproject/Assets/Tests/Runtime/NetworkSceneManager/ClientSynchronizationValidationTest.cs b/testproject/Assets/Tests/Runtime/NetworkSceneManager/ClientSynchronizationValidationTest.cs
index 845a83bbbb..7ee9a4ecef 100644
--- a/testproject/Assets/Tests/Runtime/NetworkSceneManager/ClientSynchronizationValidationTest.cs
+++ b/testproject/Assets/Tests/Runtime/NetworkSceneManager/ClientSynchronizationValidationTest.cs
@@ -15,18 +15,69 @@ public class ClientSynchronizationValidationTest : NetcodeIntegrationTest
private const string k_FirstSceneToLoad = "UnitTestBaseScene";
private const string k_SecondSceneToLoad = "InSceneNetworkObject";
private const string k_ThirdSceneToSkip = "EmptyScene";
+ private Scene m_RuntimeGeneratedScene;
+ private bool m_IncludeSceneVerificationHandler;
+ private bool m_RuntimeSceneWasExcludedFromSynch;
private List m_ClientSceneVerifiers = new List();
protected override void OnNewClientStarted(NetworkManager networkManager)
{
- m_ClientSceneVerifiers.Add(new ClientSceneVerificationHandler(networkManager));
+ if (m_IncludeSceneVerificationHandler)
+ {
+ m_ClientSceneVerifiers.Add(new ClientSceneVerificationHandler(networkManager));
+ }
base.OnNewClientStarted(networkManager);
}
+ ///
+ /// Handle excluding runtime scene from synchronization
+ ///
+ private bool OnServerVerifySceneBeforeLoading(int sceneIndex, string sceneName, LoadSceneMode loadSceneMode)
+ {
+ // exclude test runner scene
+ if (sceneName.StartsWith(NetcodeIntegrationTestHelpers.FirstPartOfTestRunnerSceneName))
+ {
+ return false;
+ }
+
+ // Exclude the runtime generated scene
+ if (sceneIndex == m_RuntimeGeneratedScene.buildIndex && m_RuntimeGeneratedScene.name == sceneName)
+ {
+ m_RuntimeSceneWasExcludedFromSynch = true;
+ return false;
+ }
+
+ return true;
+ }
+
+ ///
+ /// Test that validates users can exclude runtime generated scenes from the initial client synchronization
+ /// process using
+ ///
+ [UnityTest]
+ public IEnumerator ClientSynchWithServerSideRuntimeGeneratedScene()
+ {
+ m_IncludeSceneVerificationHandler = false;
+ m_ServerNetworkManager.SceneManager.VerifySceneBeforeLoading = OnServerVerifySceneBeforeLoading;
+ m_ServerNetworkManager.SceneManager.DisableValidationWarnings(true);
+ // For this test we want to disable the check for scenes in build list
+ m_ServerNetworkManager.SceneManager.ExcludeSceneFromSychronization = null;
+ // Create a runtime scene in the server side
+ m_RuntimeGeneratedScene = SceneManager.CreateScene("RuntimeGeneratedScene");
+ yield return s_DefaultWaitForTick;
+ yield return CreateAndStartNewClient();
+
+ Assert.True(m_RuntimeSceneWasExcludedFromSynch, $"Server did not exclude the runtime generated scene when creating synchronization message data!");
+ }
+
+ ///
+ /// Validates that connecting clients will exclude scenes using
+ ///
[UnityTest]
public IEnumerator ClientVerifySceneBeforeLoading()
{
+ m_IncludeSceneVerificationHandler = true;
var scenesToLoad = new List() { k_FirstSceneToLoad, k_SecondSceneToLoad, k_ThirdSceneToSkip };
m_ServerNetworkManager.SceneManager.OnLoadComplete += OnLoadComplete;
foreach (var sceneToLoad in scenesToLoad)