Skip to content

Commit 0ba6837

Browse files
fix: server scene exclusion during synchronization for runtime generated scenes (#2550)
* fix Breaking apart the ValidateSceneBeforeLoading so synchronization can exclude runtime generated scenes. * style Added comment * test Test to validate the fix for the server being able to use NetworkSceneManager.VerifySceneBeforeLoading in order to exclude scenes created at runtime. * update Updating the changelog file to reflect the fix
1 parent 2b92028 commit 0ba6837

File tree

3 files changed

+67
-8
lines changed

3 files changed

+67
-8
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

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

1515
- Fixed issue where some temporary debug console logging was left in a merged PR. (#2562)
1616
- Fixed the "Generate Default Network Prefabs List" setting not loading correctly and always reverting to being checked. (#2545)
17+
- Fixed issue where users could not use NetworkSceneManager.VerifySceneBeforeLoading to exclude runtime generated scenes from client synchronization. (#2550)
1718
- Fixed missing value on `NetworkListEvent` for `EventType.RemoveAt` events. (#2542,#2543)
1819
- 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)
1920
- Fixed issue where a server would include scene migrated and then despawned NetworkObjects to a client that was being synchronized. (#2532)

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

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -786,9 +786,18 @@ private void SceneManager_ActiveSceneChanged(Scene current, Scene next)
786786
/// <returns>true (Valid) or false (Invalid)</returns>
787787
internal bool ValidateSceneBeforeLoading(uint sceneHash, LoadSceneMode loadSceneMode)
788788
{
789-
var validated = true;
790789
var sceneName = SceneNameFromHash(sceneHash);
791790
var sceneIndex = SceneUtility.GetBuildIndexByScenePath(sceneName);
791+
return ValidateSceneBeforeLoading(sceneIndex, sceneName, loadSceneMode);
792+
}
793+
794+
/// <summary>
795+
/// Overloaded version that is invoked by <see cref="ValidateSceneBeforeLoading"/> and <see cref="SynchronizeNetworkObjects"/>.
796+
/// This specifically is to allow runtime generated scenes to be excluded by the server during synchronization.
797+
/// </summary>
798+
internal bool ValidateSceneBeforeLoading(int sceneIndex, string sceneName, LoadSceneMode loadSceneMode)
799+
{
800+
var validated = true;
792801
if (VerifySceneBeforeLoading != null)
793802
{
794803
validated = VerifySceneBeforeLoading.Invoke(sceneIndex, sceneName, loadSceneMode);
@@ -1744,24 +1753,22 @@ internal void SynchronizeNetworkObjects(ulong clientId)
17441753
continue;
17451754
}
17461755

1747-
var sceneHash = SceneHashFromNameOrPath(scene.path);
1748-
17491756
// This would depend upon whether we are additive or not
17501757
// If we are the base scene, then we set the root scene index;
17511758
if (activeScene == scene)
17521759
{
1753-
if (!ValidateSceneBeforeLoading(sceneHash, sceneEventData.LoadSceneMode))
1760+
if (!ValidateSceneBeforeLoading(scene.buildIndex, scene.name, sceneEventData.LoadSceneMode))
17541761
{
17551762
continue;
17561763
}
1757-
sceneEventData.SceneHash = sceneHash;
1764+
sceneEventData.SceneHash = SceneHashFromNameOrPath(scene.path);
17581765
sceneEventData.SceneHandle = scene.handle;
17591766
}
1760-
else if (!ValidateSceneBeforeLoading(sceneHash, LoadSceneMode.Additive))
1767+
else if (!ValidateSceneBeforeLoading(scene.buildIndex, scene.name, LoadSceneMode.Additive))
17611768
{
17621769
continue;
17631770
}
1764-
sceneEventData.AddSceneToSynchronize(sceneHash, scene.handle);
1771+
sceneEventData.AddSceneToSynchronize(SceneHashFromNameOrPath(scene.path), scene.handle);
17651772
}
17661773

17671774
sceneEventData.AddSpawnedNetworkObjects();

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

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,69 @@ public class ClientSynchronizationValidationTest : NetcodeIntegrationTest
1515
private const string k_FirstSceneToLoad = "UnitTestBaseScene";
1616
private const string k_SecondSceneToLoad = "InSceneNetworkObject";
1717
private const string k_ThirdSceneToSkip = "EmptyScene";
18+
private Scene m_RuntimeGeneratedScene;
19+
private bool m_IncludeSceneVerificationHandler;
20+
private bool m_RuntimeSceneWasExcludedFromSynch;
1821

1922
private List<ClientSceneVerificationHandler> m_ClientSceneVerifiers = new List<ClientSceneVerificationHandler>();
2023

2124
protected override void OnNewClientStarted(NetworkManager networkManager)
2225
{
23-
m_ClientSceneVerifiers.Add(new ClientSceneVerificationHandler(networkManager));
26+
if (m_IncludeSceneVerificationHandler)
27+
{
28+
m_ClientSceneVerifiers.Add(new ClientSceneVerificationHandler(networkManager));
29+
}
2430
base.OnNewClientStarted(networkManager);
2531
}
2632

33+
/// <summary>
34+
/// Handle excluding runtime scene from synchronization
35+
/// </summary>
36+
private bool OnServerVerifySceneBeforeLoading(int sceneIndex, string sceneName, LoadSceneMode loadSceneMode)
37+
{
38+
// exclude test runner scene
39+
if (sceneName.StartsWith(NetcodeIntegrationTestHelpers.FirstPartOfTestRunnerSceneName))
40+
{
41+
return false;
42+
}
43+
44+
// Exclude the runtime generated scene
45+
if (sceneIndex == m_RuntimeGeneratedScene.buildIndex && m_RuntimeGeneratedScene.name == sceneName)
46+
{
47+
m_RuntimeSceneWasExcludedFromSynch = true;
48+
return false;
49+
}
50+
51+
return true;
52+
}
53+
54+
/// <summary>
55+
/// Test that validates users can exclude runtime generated scenes from the initial client synchronization
56+
/// process using <see cref="NetworkSceneManager.VerifySceneBeforeLoading"/>
57+
/// </summary>
58+
[UnityTest]
59+
public IEnumerator ClientSynchWithServerSideRuntimeGeneratedScene()
60+
{
61+
m_IncludeSceneVerificationHandler = false;
62+
m_ServerNetworkManager.SceneManager.VerifySceneBeforeLoading = OnServerVerifySceneBeforeLoading;
63+
m_ServerNetworkManager.SceneManager.DisableValidationWarnings(true);
64+
// For this test we want to disable the check for scenes in build list
65+
m_ServerNetworkManager.SceneManager.ExcludeSceneFromSychronization = null;
66+
// Create a runtime scene in the server side
67+
m_RuntimeGeneratedScene = SceneManager.CreateScene("RuntimeGeneratedScene");
68+
yield return s_DefaultWaitForTick;
69+
yield return CreateAndStartNewClient();
70+
71+
Assert.True(m_RuntimeSceneWasExcludedFromSynch, $"Server did not exclude the runtime generated scene when creating synchronization message data!");
72+
}
73+
74+
/// <summary>
75+
/// Validates that connecting clients will exclude scenes using <see cref="NetworkSceneManager.VerifySceneBeforeLoading"/>
76+
/// </summary>
2777
[UnityTest]
2878
public IEnumerator ClientVerifySceneBeforeLoading()
2979
{
80+
m_IncludeSceneVerificationHandler = true;
3081
var scenesToLoad = new List<string>() { k_FirstSceneToLoad, k_SecondSceneToLoad, k_ThirdSceneToSkip };
3182
m_ServerNetworkManager.SceneManager.OnLoadComplete += OnLoadComplete;
3283
foreach (var sceneToLoad in scenesToLoad)

0 commit comments

Comments
 (0)