Skip to content

Commit 2956fcf

Browse files
fix - synchronizing clients should always load active scene first
This fixes the issue where the active scene could end up not being the 1st scene loaded which upon loading the active scene and previously SceneEventData relative loaded scenes would get unloaded when loading the active scene since this will can end up being loaded in SingleMode.
1 parent d8d2da2 commit 2956fcf

1 file changed

Lines changed: 50 additions & 40 deletions

File tree

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

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,6 +1952,21 @@ private void OnClientLoadedScene(uint sceneEventId, Scene scene)
19521952
/// </summary>
19531953
internal List<ulong> ClientConnectionQueue = new List<ulong>();
19541954

1955+
1956+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1957+
private void AddSceneToClientSynchronization(ref SceneEventData sceneEventData, ref Scene scene)
1958+
{
1959+
// If we are just a normal client and in distributed authority mode, then always use the known server scene handle
1960+
if (NetworkManager.DistributedAuthorityMode && NetworkManager.CMBServiceConnection)
1961+
{
1962+
sceneEventData.AddSceneToSynchronize(SceneHashFromNameOrPath(scene.path), ClientSceneHandleToServerSceneHandle[scene.handle]);
1963+
}
1964+
else
1965+
{
1966+
sceneEventData.AddSceneToSynchronize(SceneHashFromNameOrPath(scene.path), scene.handle);
1967+
}
1968+
}
1969+
19551970
/// <summary>
19561971
/// Server Side:
19571972
/// This is used for players that have just had their connection approved and will assure they are synchronized
@@ -2002,61 +2017,53 @@ internal void SynchronizeNetworkObjects(ulong clientId, bool synchronizingServic
20022017

20032018
// Organize how (and when) we serialize our NetworkObjects
20042019
var hasSynchronizedActive = false;
2005-
for (int i = 0; i < SceneManager.sceneCount; i++)
2006-
{
2007-
var scene = SceneManager.GetSceneAt(i);
20082020

2009-
// NetworkSceneManager does not synchronize scenes that are not loaded by NetworkSceneManager
2010-
// unless the scene in question is the currently active scene.
2011-
if (ExcludeSceneFromSychronization != null && !ExcludeSceneFromSychronization(scene))
2021+
// It is possible a user might not want to synchronize the active scene, so we will check to see if it is valid before adding it to the synchronization list.
2022+
// !! Important !!
2023+
// The active scene MUST always be the first scene in the synchronization list.
2024+
if (ValidateSceneBeforeLoading(activeScene.buildIndex, activeScene.name, sceneEventData.LoadSceneMode))
2025+
{
2026+
sceneEventData.SceneHash = SceneHashFromNameOrPath(activeScene.path);
2027+
if (sceneEventData.SceneHash == sceneEventData.ActiveSceneHash)
20122028
{
2013-
continue;
2029+
hasSynchronizedActive = true;
20142030
}
20152031

2016-
if (scene == DontDestroyOnLoadScene)
2032+
// If we are just a normal client, then always use the server scene handle
2033+
if (NetworkManager.DistributedAuthorityMode)
20172034
{
2018-
continue;
2035+
sceneEventData.SenderClientId = NetworkManager.LocalClientId;
2036+
sceneEventData.SceneHandle = ClientSceneHandleToServerSceneHandle[activeScene.handle];
20192037
}
2020-
2021-
// This would depend upon whether we are additive or not
2022-
// If we are the base scene, then we set the root scene index;
2023-
if (activeScene == scene)
2038+
else
20242039
{
2025-
if (!ValidateSceneBeforeLoading(scene.buildIndex, scene.name, sceneEventData.LoadSceneMode))
2026-
{
2027-
continue;
2028-
}
2029-
sceneEventData.SceneHash = SceneHashFromNameOrPath(scene.path);
2030-
if (sceneEventData.SceneHash == sceneEventData.ActiveSceneHash)
2031-
{
2032-
hasSynchronizedActive = true;
2033-
}
2034-
2035-
// If we are just a normal client, then always use the server scene handle
2036-
if (NetworkManager.DistributedAuthorityMode)
2037-
{
2038-
sceneEventData.SenderClientId = NetworkManager.LocalClientId;
2039-
sceneEventData.SceneHandle = ClientSceneHandleToServerSceneHandle[scene.handle];
2040-
}
2041-
else
2042-
{
2043-
sceneEventData.SceneHandle = scene.handle;
2044-
}
2040+
sceneEventData.SceneHandle = activeScene.handle;
20452041
}
2046-
else if (!ValidateSceneBeforeLoading(scene.buildIndex, scene.name, LoadSceneMode.Additive))
2042+
AddSceneToClientSynchronization(ref sceneEventData, ref activeScene);
2043+
}
2044+
2045+
for (int i = 0; i < SceneManager.sceneCount; i++)
2046+
{
2047+
var scene = SceneManager.GetSceneAt(i);
2048+
// Skip adding the active scene at this point as we are just adding all other additively loaded scenes to the synchronization list.
2049+
// Skip adding the dont destroy on load scene as that is never synchronized.
2050+
if ((scene.handle == activeScene.handle) || (scene == DontDestroyOnLoadScene))
20472051
{
20482052
continue;
20492053
}
20502054

2051-
// If we are just a normal client and in distributed authority mode, then always use the known server scene handle
2052-
if (NetworkManager.DistributedAuthorityMode && NetworkManager.CMBServiceConnection)
2055+
// NetworkSceneManager does not synchronize scenes that are not loaded by NetworkSceneManager
2056+
// unless the scene in question is the currently active scene.
2057+
if (ExcludeSceneFromSychronization != null && !ExcludeSceneFromSychronization(scene))
20532058
{
2054-
sceneEventData.AddSceneToSynchronize(SceneHashFromNameOrPath(scene.path), ClientSceneHandleToServerSceneHandle[scene.handle]);
2059+
continue;
20552060
}
2056-
else
2061+
2062+
if (!ValidateSceneBeforeLoading(scene.buildIndex, scene.name, LoadSceneMode.Additive))
20572063
{
2058-
sceneEventData.AddSceneToSynchronize(SceneHashFromNameOrPath(scene.path), scene.handle);
2064+
continue;
20592065
}
2066+
AddSceneToClientSynchronization(ref sceneEventData, ref scene);
20602067
}
20612068

20622069
if (!hasSynchronizedActive && NetworkManager.CMBServiceConnection && synchronizingService)
@@ -2109,9 +2116,12 @@ private void OnClientBeginSync(uint sceneEventId)
21092116
var sceneHash = sceneEventData.GetNextSceneSynchronizationHash();
21102117
var sceneHandle = sceneEventData.GetNextSceneSynchronizationHandle();
21112118
var sceneName = SceneNameFromHash(sceneHash);
2119+
var activeSceneName = SceneNameFromHash(sceneEventData.ActiveSceneHash);
21122120
var activeScene = SceneManager.GetActiveScene();
21132121

2114-
var loadSceneMode = sceneHash == sceneEventData.SceneHash ? sceneEventData.LoadSceneMode : LoadSceneMode.Additive;
2122+
var activeSceneLoaded = activeSceneName == activeScene.name;
2123+
2124+
var loadSceneMode = sceneHash == sceneEventData.SceneHash && !activeSceneLoaded ? sceneEventData.LoadSceneMode : LoadSceneMode.Additive;
21152125

21162126
// Store the sceneHandle and hash
21172127
sceneEventData.NetworkSceneHandle = sceneHandle;

0 commit comments

Comments
 (0)