-
Notifications
You must be signed in to change notification settings - Fork 455
fix: NetworkSceneManager exception when DontDestroyOnLoad NetworkObjects are being synchronized #1090
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: NetworkSceneManager exception when DontDestroyOnLoad NetworkObjects are being synchronized #1090
Changes from 6 commits
7e1435c
bf8eed9
ed6fb3c
cf396ba
6a69408
dab508c
ad98f1a
41a4440
91832b3
b89b8c1
f0b4654
2cefbfc
e44b814
5b46060
8012218
44fe231
4e74837
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -245,13 +245,41 @@ internal void SetTheSceneBeingSynchronized(int serverSceneHandle) | |
// If the scene was not found (invalid) or was not loaded then throw an exception | ||
if (!SceneBeingSynchronized.IsValid() || !SceneBeingSynchronized.isLoaded) | ||
{ | ||
throw new Exception($"[{nameof(NetworkSceneManager)}- {nameof(ScenesLoaded)}] Could not find the appropriate scene to set as being synchronized!"); | ||
// Let's go ahead and use the currently active scene under the scenario where a NetworkObject is determined to exist in a scene that the NetworkSceneManager is not aware of | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So in the older code, we halted and caught fire if 1) the scene being sync'd was invalid or 2) it was not loaded. Case 1) Seems like we want to still halt and catch fire for situation 1). Changing to some other scene would seem to mask a problem that needs to be dealt with. I mean, why would we think we would want to pop back to the active scene if the scene we're going to is invalid. Case 2) same kind of thing; if the scene is valid but not loaded yet, perhaps there is another handling - I'm just not sure why we'd just pick whatever scene happens to be loaded now There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is specific to in-scene placed NetworkObjects during the client side deserialization phase for:
The only time the offending method (SetTheSceneBeingSynchronized) is truly pertinent is when you have the same additive scene loaded multiple times and there are in-scene NetworkObjects in each instance that need to be synchronized. We use scene handlers to distinguish between "duplicate in-scene NetworkObjects" in order to "find the right NetworkObject" so we can apply the appropriate NetworkObjectId to that specific instance. It is one of those chicken or the egg scenarios: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I may just need to trust you on this one, not sure I can parse this out / come to understand all the related systems as quickly as we need There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was refactored a bit and might make more sense at this point. But yeah.., there are a lot of different possible scenarios to consider for sure. |
||
SceneBeingSynchronized = SceneManager.GetActiveScene(); | ||
|
||
// Otherwise, there is some other scenario we are not handling. | ||
Debug.LogWarning($"[{nameof(NetworkSceneManager)}- {nameof(ScenesLoaded)}] Could not find the appropriate scene to set as being synchronized! Using the currently active scene."); | ||
} | ||
} | ||
else | ||
{ | ||
// This should never happen, but in the event it does... | ||
throw new Exception($"[{nameof(SceneEventData)}- Scene Handle Mismatch] {nameof(serverSceneHandle)} could not be found in {nameof(ServerSceneHandleToClientSceneHandle)}!"); | ||
// Most common scenario for DontDestroyOnLoad is when NetworkManager is set to not be destroyed | ||
LukeStampfli marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (m_NetworkManager.DontDestroy) | ||
{ | ||
if (serverSceneHandle == m_NetworkManager.gameObject.scene.handle) | ||
{ | ||
SceneBeingSynchronized = m_NetworkManager.gameObject.scene; | ||
return; | ||
} | ||
} | ||
else | ||
{ | ||
// The next scenario is if a user intentionally moves NetworkObjects into a DontDestroyOnLoad scene | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When we say "user intentionally moves NO into a DDOL", is this like the user is manipulating objects manually in the editor while things are running? I guess I didn't think of this as something we needed to explicitly support. Or is this if code moves a NO in the DDOL scene? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is if the user's code intentionally moves it into the DDOL scene.
Then it would get moved into the DDOL Scene when it was instantiated... and that would apply to both dynamically spawned and in-scene placed NetworkObjects. |
||
var dontDestroyOnLoadScene = SceneManager.GetSceneByName("DontDestroyOnLoad"); | ||
if (dontDestroyOnLoadScene.IsValid() && dontDestroyOnLoadScene.isLoaded && dontDestroyOnLoadScene.handle == serverSceneHandle) | ||
{ | ||
SceneBeingSynchronized = dontDestroyOnLoadScene; | ||
return; | ||
} | ||
|
||
// Let's go ahead and use the currently active scene under the scenario where a NetworkObject is determined to exist in a scene that the NetworkSceneManager is not aware of | ||
// or the NetworkObject has yet to be moved to that specific scene (i.e. no DontDestroyOnLoad scene exists yet). | ||
SceneBeingSynchronized = SceneManager.GetActiveScene(); | ||
LukeStampfli marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Otherwise, there is some other scenario we are not handling. | ||
Debug.LogWarning($"[{nameof(SceneEventData)}- Scene Handle Mismatch] {nameof(serverSceneHandle)} could not be found in {nameof(ServerSceneHandleToClientSceneHandle)}. Using the currently active scene."); | ||
} | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
%YAML 1.1 | ||
%TAG !u! tag:unity3d.com,2011: | ||
--- !u!114 &11400000 | ||
MonoBehaviour: | ||
m_ObjectHideFlags: 0 | ||
m_CorrespondingSourceObject: {fileID: 0} | ||
m_PrefabInstance: {fileID: 0} | ||
m_PrefabAsset: {fileID: 0} | ||
m_GameObject: {fileID: 0} | ||
m_Enabled: 1 | ||
m_EditorHideFlags: 0 | ||
m_Script: {fileID: 11500000, guid: 39a16938ffb5cd846a9f6df7a686a9c4, type: 3} | ||
m_Name: DestroyNetworkManager_DontDestroyOnLoadSceneReference | ||
m_EditorClassIdentifier: | ||
SceneToReference: {fileID: 102900000, guid: 7dc1ab12373402546befc7d54e447258, type: 3} | ||
m_IncludedScenes: [] | ||
m_DisplayName: DestroyNetworkManager DontDestroyOnLoad Test | ||
m_ReferencedScenes: | ||
- DontDestroyOnLoad_DestroyNetworkManagerTest |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
%YAML 1.1 | ||
%TAG !u! tag:unity3d.com,2011: | ||
--- !u!114 &11400000 | ||
MonoBehaviour: | ||
m_ObjectHideFlags: 0 | ||
m_CorrespondingSourceObject: {fileID: 0} | ||
m_PrefabInstance: {fileID: 0} | ||
m_PrefabAsset: {fileID: 0} | ||
m_GameObject: {fileID: 0} | ||
m_Enabled: 1 | ||
m_EditorHideFlags: 0 | ||
m_Script: {fileID: 11500000, guid: 39a16938ffb5cd846a9f6df7a686a9c4, type: 3} | ||
m_Name: DontDestroyOnLoadSceneReference | ||
m_EditorClassIdentifier: | ||
SceneToReference: {fileID: 102900000, guid: ff98b91da4ee7ff44bc3aa8a57ad5c12, type: 3} | ||
m_IncludedScenes: [] | ||
m_DisplayName: DontDestroyOnLoad Test | ||
m_ReferencedScenes: | ||
- DontDestroyOnLoadTest |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using UnityEngine; | ||
using Unity.Netcode; | ||
|
||
namespace TestProject.ManualTests | ||
{ | ||
/// <summary> | ||
/// Spawns a single NetworkPrefab | ||
/// </summary> | ||
public class DontDestroyOnLoadSpawnHandler : NetworkBehaviour | ||
LukeStampfli marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
public GameObject NetworkPrefabToCreate; | ||
|
||
public override void OnNetworkSpawn() | ||
{ | ||
if (NetworkPrefabToCreate != null && IsServer) | ||
{ | ||
var newGameObject = Instantiate(NetworkPrefabToCreate); | ||
var networkObject = newGameObject.GetComponent<NetworkObject>(); | ||
networkObject.Spawn(); | ||
} | ||
|
||
base.OnNetworkSpawn(); | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe removing this comment since we are not throwing anymore