Skip to content

Commit 9d0f50e

Browse files
feat: client scene synchronization mode (#1171)
* refactor This allows for two different types of client synchronization modes (ClientSynchronizationMode): LoadSceneMode.Single: All currently loaded scenes on the client will be unloaded and the server's currently active scene will be loaded in single mode on the client unless it was already loaded. LoadSceneMode.Additive: All currently loaded scenes are left as they are and any newly loaded scenes will be loaded additively. Uses need to determine which scenes are valid to load via the VerifySceneBeforeLoading method. * refactor and style Added the ability to squelch the validation warning messages for ClientSynchronizationMode additive as it will throw warnings for every loaded scene you don't want to have the client synchronize. Updated the comments. * style fixing spelling typo. * test added Values to the scene loading test that will run the scene loading tests with client synchronization set to both LoadSceneMode.Single and LoadSceneMode.Additive. * test Adding verification that the client synchronization mode used by the server when building the client synchronization SceneEventData message is the same value on the client side. * style fixing whitespace issue
1 parent 6a032b1 commit 9d0f50e

File tree

2 files changed

+59
-8
lines changed

2 files changed

+59
-8
lines changed

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

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,22 @@ public class NetworkSceneManager : IDisposable
205205

206206
internal Scene DontDestroyOnLoadScene;
207207

208+
/// <summary>
209+
/// LoadSceneMode.Single: All currently loaded scenes on the client will be unloaded and
210+
/// the server's currently active scene will be loaded in single mode on the client
211+
/// unless it was already loaded.
212+
///
213+
/// LoadSceneMode.Additive: All currently loaded scenes are left as they are and any newly loaded
214+
/// scenes will be loaded additively. Users need to determine which scenes are valid to load via the
215+
/// <see cref="VerifySceneBeforeLoading"/> method.
216+
/// </summary>
217+
public LoadSceneMode ClientSynchronizationMode { get; internal set; }
218+
219+
/// <summary>
220+
/// When true, the <see cref="Debug.LogWarning(object)"/> messages will be turned off
221+
/// </summary>
222+
private bool m_DisableValidationWarningMessages;
223+
208224
/// <summary>
209225
/// Handle NetworkSeneManager clean up
210226
/// </summary>
@@ -239,6 +255,32 @@ internal void GenerateScenesInBuild()
239255
}
240256
}
241257

258+
/// <summary>
259+
/// When set to true, this will disable the console warnings about
260+
/// a scene being invalidated.
261+
/// </summary>
262+
/// <param name="disabled"></param>
263+
public void DisableValidationWarnings(bool disabled)
264+
{
265+
m_DisableValidationWarningMessages = disabled;
266+
}
267+
268+
/// <summary>
269+
/// This will change how clients are initially synchronized.
270+
/// LoadSceneMode.Single: All currently loaded scenes on the client will be unloaded and
271+
/// the server's currently active scene will be loaded in single mode on the client
272+
/// unless it was already loaded.
273+
///
274+
/// LoadSceneMode.Additive: All currently loaded scenes are left as they are and any newly loaded
275+
/// scenes will be loaded additively. Users need to determine which scenes are valid to load via the
276+
/// <see cref="VerifySceneBeforeLoading"/> method.
277+
/// </summary>
278+
/// <param name="mode"><see cref="LoadSceneMode"/> for initial client synchronization</param>
279+
public void SetClientSynchronizationMode(LoadSceneMode mode)
280+
{
281+
ClientSynchronizationMode = mode;
282+
}
283+
242284
/// <summary>
243285
/// Constructor
244286
/// </summary>
@@ -299,7 +341,7 @@ internal bool ValidateSceneBeforeLoading(uint sceneIndex, LoadSceneMode loadScen
299341
{
300342
validated = VerifySceneBeforeLoading.Invoke((int)sceneIndex, sceneName, loadSceneMode);
301343
}
302-
if (!validated)
344+
if (!validated && !m_DisableValidationWarningMessages)
303345
{
304346
var serverHostorClient = "Client";
305347
if (m_NetworkManager.IsServer)
@@ -1139,7 +1181,7 @@ internal void SynchronizeNetworkObjects(ulong clientId)
11391181

11401182
ClientSynchEventData.InitializeForSynch();
11411183
ClientSynchEventData.TargetClientId = clientId;
1142-
ClientSynchEventData.LoadSceneMode = LoadSceneMode.Single;
1184+
ClientSynchEventData.LoadSceneMode = ClientSynchronizationMode;
11431185
var activeScene = SceneManager.GetActiveScene();
11441186
ClientSynchEventData.SceneEventType = SceneEventData.SceneEventTypes.S2C_Sync;
11451187

@@ -1158,7 +1200,7 @@ internal void SynchronizeNetworkObjects(ulong clientId)
11581200
// If we are the base scene, then we set the root scene index;
11591201
if (activeScene == scene)
11601202
{
1161-
if (!ValidateSceneBeforeLoading(sceneIndex, LoadSceneMode.Single))
1203+
if (!ValidateSceneBeforeLoading(sceneIndex, ClientSynchEventData.LoadSceneMode))
11621204
{
11631205
continue;
11641206
}

testproject/Assets/Tests/Runtime/NetworkSceneManagerTests.cs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ private class SceneTestInfo
4343

4444

4545
[UnityTest]
46-
public IEnumerator SceneLoadingAndNotifications()
46+
public IEnumerator SceneLoadingAndNotifications([Values(LoadSceneMode.Single, LoadSceneMode.Additive)] LoadSceneMode clientSynchronizationMode)
4747
{
4848
m_ServerNetworkManager.SceneManager.OnSceneEvent += SceneManager_OnSceneEvent;
4949
m_CurrentSceneName = "AdditiveScene1";
@@ -85,7 +85,7 @@ public IEnumerator SceneLoadingAndNotifications()
8585

8686

8787
// Now prepare for the loading and unloading additive scene testing
88-
InitializeSceneTestInfo();
88+
InitializeSceneTestInfo(clientSynchronizationMode);
8989

9090
// Test loading additive scenes and the associated event messaging and notification pipelines
9191
ResetWait();
@@ -139,12 +139,13 @@ public IEnumerator SceneLoadingAndNotifications()
139139
/// <summary>
140140
/// Initializes the m_ShouldWaitList
141141
/// </summary>
142-
private void InitializeSceneTestInfo(bool enableSceneVerification = false)
142+
private void InitializeSceneTestInfo(LoadSceneMode clientSynchronizationMode, bool enableSceneVerification = false)
143143
{
144144
m_ShouldWaitList.Add(new SceneTestInfo() { ClientId = m_ServerNetworkManager.ServerClientId, ShouldWait = false });
145145
if (enableSceneVerification)
146146
{
147147
m_ServerNetworkManager.SceneManager.VerifySceneBeforeLoading = ServerVerifySceneBeforeLoading;
148+
m_ServerNetworkManager.SceneManager.SetClientSynchronizationMode(clientSynchronizationMode);
148149
}
149150

150151
foreach (var manager in m_ClientNetworkManagers)
@@ -153,6 +154,7 @@ private void InitializeSceneTestInfo(bool enableSceneVerification = false)
153154
if (enableSceneVerification)
154155
{
155156
manager.SceneManager.VerifySceneBeforeLoading = ClientVerifySceneBeforeLoading;
157+
manager.SceneManager.SetClientSynchronizationMode(clientSynchronizationMode);
156158
}
157159
}
158160
}
@@ -256,9 +258,16 @@ private void SceneManager_OnSceneEvent(SceneEvent sceneEvent)
256258
{
257259
switch (sceneEvent.SceneEventType)
258260
{
261+
case SceneEventData.SceneEventTypes.S2C_Sync:
262+
{
263+
// Verify that the Client Synchronization Mode set by the server is being received by the client (which means it is applied when loading the first scene)
264+
Assert.AreEqual(m_ClientNetworkManagers.ToArray().Where(c => c.LocalClientId == sceneEvent.ClientId).First().SceneManager.ClientSynchronizationMode, sceneEvent.LoadSceneMode);
265+
break;
266+
}
259267
case SceneEventData.SceneEventTypes.S2C_Load:
260268
case SceneEventData.SceneEventTypes.S2C_Unload:
261269
{
270+
262271
Assert.AreEqual(sceneEvent.SceneName, m_CurrentSceneName);
263272
Assert.IsTrue(ContainsClient(sceneEvent.ClientId));
264273
Assert.IsNotNull(sceneEvent.AsyncOperation);
@@ -342,13 +351,13 @@ private bool ClientVerifySceneBeforeLoading(int sceneIndex, string sceneName, Lo
342351
/// </summary>
343352
/// <returns></returns>
344353
[UnityTest]
345-
public IEnumerator SceneVerifyBeforeLoadTest()
354+
public IEnumerator SceneVerifyBeforeLoadTest([Values(LoadSceneMode.Single, LoadSceneMode.Additive)] LoadSceneMode clientSynchronizationMode)
346355
{
347356
m_ServerNetworkManager.SceneManager.OnSceneEvent += SceneManager_OnSceneEvent;
348357
m_CurrentSceneName = "AdditiveScene1";
349358

350359
// Now prepare for the loading and unloading additive scene testing
351-
InitializeSceneTestInfo(true);
360+
InitializeSceneTestInfo(clientSynchronizationMode, true);
352361

353362
// Test VerifySceneBeforeLoading with both server and client set to true
354363
ResetWait();

0 commit comments

Comments
 (0)