diff --git a/com.unity.netcode.gameobjects/Editor/NetworkManagerEditor.cs b/com.unity.netcode.gameobjects/Editor/NetworkManagerEditor.cs
index 563a2eeabd..0f6f162c70 100644
--- a/com.unity.netcode.gameobjects/Editor/NetworkManagerEditor.cs
+++ b/com.unity.netcode.gameobjects/Editor/NetworkManagerEditor.cs
@@ -21,7 +21,6 @@ public class NetworkManagerEditor : UnityEditor.Editor
// NetworkConfig fields
private SerializedProperty m_PlayerPrefabProperty;
private SerializedProperty m_ProtocolVersionProperty;
- private SerializedProperty m_AllowRuntimeSceneChangesProperty;
private SerializedProperty m_NetworkTransportProperty;
private SerializedProperty m_TickRateProperty;
private SerializedProperty m_MaxObjectUpdatesPerTickProperty;
@@ -37,7 +36,6 @@ public class NetworkManagerEditor : UnityEditor.Editor
private SerializedProperty m_LoadSceneTimeOutProperty;
private ReorderableList m_NetworkPrefabsList;
- private ReorderableList m_RegisteredSceneAssetsList;
private NetworkManager m_NetworkManager;
private bool m_Initialized;
@@ -91,8 +89,7 @@ private void Initialize()
// NetworkConfig properties
m_PlayerPrefabProperty = m_NetworkConfigProperty.FindPropertyRelative(nameof(NetworkConfig.PlayerPrefab));
- m_ProtocolVersionProperty = m_NetworkConfigProperty.FindPropertyRelative("ProtocolVersion");
- m_AllowRuntimeSceneChangesProperty = m_NetworkConfigProperty.FindPropertyRelative("AllowRuntimeSceneChanges");
+ m_ProtocolVersionProperty = m_NetworkConfigProperty.FindPropertyRelative("ProtocolVersion");
m_NetworkTransportProperty = m_NetworkConfigProperty.FindPropertyRelative("NetworkTransport");
m_TickRateProperty = m_NetworkConfigProperty.FindPropertyRelative("TickRate");
m_ClientConnectionBufferTimeoutProperty = m_NetworkConfigProperty.FindPropertyRelative("ClientConnectionBufferTimeout");
@@ -121,7 +118,6 @@ private void CheckNullProperties()
// NetworkConfig properties
m_PlayerPrefabProperty = m_NetworkConfigProperty.FindPropertyRelative(nameof(NetworkConfig.PlayerPrefab));
m_ProtocolVersionProperty = m_NetworkConfigProperty.FindPropertyRelative("ProtocolVersion");
- m_AllowRuntimeSceneChangesProperty = m_NetworkConfigProperty.FindPropertyRelative("AllowRuntimeSceneChanges");
m_NetworkTransportProperty = m_NetworkConfigProperty.FindPropertyRelative("NetworkTransport");
m_TickRateProperty = m_NetworkConfigProperty.FindPropertyRelative("TickRate");
m_ClientConnectionBufferTimeoutProperty = m_NetworkConfigProperty.FindPropertyRelative("ClientConnectionBufferTimeout");
@@ -200,30 +196,6 @@ private void OnEnable()
}
};
m_NetworkPrefabsList.drawHeaderCallback = rect => EditorGUI.LabelField(rect, "NetworkPrefabs");
-
- m_RegisteredSceneAssetsList = new ReorderableList(serializedObject, serializedObject.FindProperty(nameof(NetworkManager.NetworkConfig)).FindPropertyRelative(nameof(NetworkConfig.RegisteredSceneAssets)), true, true, true, true);
- m_RegisteredSceneAssetsList.elementHeightCallback = index =>
- {
- return EditorGUIUtility.singleLineHeight + 8;
- };
- m_RegisteredSceneAssetsList.drawElementCallback = (rect, index, isActive, isFocused) =>
- {
- rect.y += 5;
-
- var sceneAsset = m_RegisteredSceneAssetsList.serializedProperty.GetArrayElementAtIndex(index);
- int firstLabelWidth = 24;
- int padding = 2;
-
- EditorGUI.LabelField(new Rect(rect.x, rect.y, firstLabelWidth, EditorGUIUtility.singleLineHeight), index.ToString());
- EditorGUI.PropertyField(new Rect(rect.x + firstLabelWidth, rect.y, rect.width - firstLabelWidth - padding, EditorGUIUtility.singleLineHeight), sceneAsset, GUIContent.none);
- };
-
- m_RegisteredSceneAssetsList.drawHeaderCallback = rect => EditorGUI.LabelField(rect, "NetworkScenes");
-
- m_RegisteredSceneAssetsList.onAddCallback = (registeredList) =>
- {
- m_NetworkManager.NetworkConfig.RegisteredSceneAssets.Add(null);
- };
}
public override void OnInspectorGUI()
@@ -257,13 +229,6 @@ public override void OnInspectorGUI()
m_NetworkPrefabsList.DoLayoutList();
EditorGUILayout.Space();
- using (new EditorGUI.DisabledScope(!m_NetworkManager.NetworkConfig.EnableSceneManagement))
- {
- m_RegisteredSceneAssetsList.DoLayoutList();
- EditorGUILayout.Space();
- }
-
-
EditorGUILayout.LabelField("General", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(m_ProtocolVersionProperty);
@@ -330,7 +295,6 @@ public override void OnInspectorGUI()
using (new EditorGUI.DisabledScope(!m_NetworkManager.NetworkConfig.EnableSceneManagement))
{
EditorGUILayout.PropertyField(m_LoadSceneTimeOutProperty);
- EditorGUILayout.PropertyField(m_AllowRuntimeSceneChangesProperty);
}
serializedObject.ApplyModifiedProperties();
diff --git a/com.unity.netcode.gameobjects/Runtime/Configuration/NetworkConfig.cs b/com.unity.netcode.gameobjects/Runtime/Configuration/NetworkConfig.cs
index a123f16064..750c7ce77d 100644
--- a/com.unity.netcode.gameobjects/Runtime/Configuration/NetworkConfig.cs
+++ b/com.unity.netcode.gameobjects/Runtime/Configuration/NetworkConfig.cs
@@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using UnityEngine;
-#if UNITY_EDITOR
-using UnityEditor;
-#endif
using System.Linq;
namespace Unity.Netcode
@@ -26,25 +23,6 @@ public class NetworkConfig
[Tooltip("The NetworkTransport to use")]
public NetworkTransport NetworkTransport = null;
- ///
- /// The list of SceneNames built from the RegisteredSceneAssets list
- ///
- [HideInInspector]
- public List RegisteredScenes = new List();
-
-#if UNITY_EDITOR
- [Tooltip("The Scenes that can be switched to by the server")]
- public List RegisteredSceneAssets = new List();
-#endif
-
- ///
- /// Whether or not runtime scene changes should be allowed and expected.
- /// If this is true, clients with different initial configurations will not work together.
- ///
- [Tooltip("Whether or not runtime scene changes should be allowed and expected.\n " +
- "If this is true, clients with different initial configurations will not work together.")]
- public bool AllowRuntimeSceneChanges = false;
-
///
/// The default player prefab
///
@@ -173,12 +151,6 @@ public class NetworkConfig
public const int RttAverageSamples = 5; // number of RTT to keep an average of (plus one)
public const int RttWindowSize = 64; // number of slots to use for RTT computations (max number of in-flight packets)
-
- private void Sort()
- {
- RegisteredScenes.Sort(StringComparer.Ordinal);
- }
-
///
/// Returns a base64 encoded version of the configuration
///
@@ -189,13 +161,6 @@ public string ToBase64()
using var buffer = PooledNetworkBuffer.Get();
using var writer = PooledNetworkWriter.Get(buffer);
writer.WriteUInt16Packed(config.ProtocolVersion);
- writer.WriteUInt16Packed((ushort)config.RegisteredScenes.Count);
-
- for (int i = 0; i < config.RegisteredScenes.Count; i++)
- {
- writer.WriteString(config.RegisteredScenes[i]);
- }
-
writer.WriteInt32Packed(config.TickRate);
writer.WriteInt32Packed(config.ClientConnectionBufferTimeout);
writer.WriteBool(config.ConnectionApproval);
@@ -208,7 +173,6 @@ public string ToBase64()
writer.WriteBool(RecycleNetworkIds);
writer.WriteSinglePacked(NetworkIdRecycleDelay);
writer.WriteBool(EnableNetworkVariable);
- writer.WriteBool(AllowRuntimeSceneChanges);
writer.WriteBool(EnableNetworkLogs);
buffer.PadBuffer();
@@ -225,16 +189,9 @@ public void FromBase64(string base64)
byte[] binary = Convert.FromBase64String(base64);
using var buffer = new NetworkBuffer(binary);
using var reader = PooledNetworkReader.Get(buffer);
- config.ProtocolVersion = reader.ReadUInt16Packed();
+ config.ProtocolVersion = reader.ReadUInt16Packed();
ushort sceneCount = reader.ReadUInt16Packed();
- config.RegisteredScenes.Clear();
-
- for (int i = 0; i < sceneCount; i++)
- {
- config.RegisteredScenes.Add(reader.ReadString().ToString());
- }
-
config.TickRate = reader.ReadInt32Packed();
config.ClientConnectionBufferTimeout = reader.ReadInt32Packed();
config.ConnectionApproval = reader.ReadBool();
@@ -247,7 +204,6 @@ public void FromBase64(string base64)
config.RecycleNetworkIds = reader.ReadBool();
config.NetworkIdRecycleDelay = reader.ReadSinglePacked();
config.EnableNetworkVariable = reader.ReadBool();
- config.AllowRuntimeSceneChanges = reader.ReadBool();
config.EnableNetworkLogs = reader.ReadBool();
}
@@ -266,25 +222,17 @@ public ulong GetConfig(bool cache = true)
return m_ConfigHash.Value;
}
- Sort();
-
using var buffer = PooledNetworkBuffer.Get();
using var writer = PooledNetworkWriter.Get(buffer);
+
writer.WriteUInt16Packed(ProtocolVersion);
writer.WriteString(NetworkConstants.PROTOCOL_VERSION);
- if (EnableSceneManagement && !AllowRuntimeSceneChanges)
- {
- for (int i = 0; i < RegisteredScenes.Count; i++)
- {
- writer.WriteString(RegisteredScenes[i]);
- }
- }
-
if (ForceSamePrefabs)
{
var sortedDictionary = NetworkPrefabOverrideLinks.OrderBy(x => x.Key);
foreach (var sortedEntry in sortedDictionary)
+
{
writer.WriteUInt32Packed(sortedEntry.Key);
}
diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs
index 0d3aa78b0b..4348809bb4 100644
--- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs
+++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs
@@ -266,17 +266,6 @@ private void OnValidate()
}
}
- if (NetworkConfig.EnableSceneManagement)
- {
- foreach (var sceneAsset in NetworkConfig.RegisteredSceneAssets)
- {
- if (!NetworkConfig.RegisteredScenes.Contains(sceneAsset.name))
- {
- NetworkConfig.RegisteredScenes.Add(sceneAsset.name);
- }
- }
- }
-
var activeScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene();
// If the scene is not dirty or the asset database is currently updating then we can skip updating the NetworkPrefab information
@@ -453,25 +442,12 @@ private void Initialize(bool server)
// Register INetworkUpdateSystem (always register this after messageQueueContainer has been instantiated)
this.RegisterNetworkUpdate(NetworkUpdateStage.PreUpdate);
- if (NetworkConfig.EnableSceneManagement)
- {
- NetworkConfig.RegisteredScenes.Sort(StringComparer.Ordinal);
-
- for (int i = 0; i < NetworkConfig.RegisteredScenes.Count; i++)
- {
- SceneManager.RegisteredSceneNames.Add(NetworkConfig.RegisteredScenes[i]);
- SceneManager.SceneIndexToString.Add((uint)i, NetworkConfig.RegisteredScenes[i]);
- SceneManager.SceneNameToIndex.Add(NetworkConfig.RegisteredScenes[i], (uint)i);
- }
- }
-
// This is used to remove entries not needed or invalid
var removeEmptyPrefabs = new List();
// Always clear our prefab override links before building
NetworkConfig.NetworkPrefabOverrideLinks.Clear();
- // Build the NetworkPrefabOverrideLinks dictionary
// Build the NetworkPrefabOverrideLinks dictionary
for (int i = 0; i < NetworkConfig.NetworkPrefabs.Count; i++)
{
@@ -1536,8 +1512,6 @@ internal void HandleApproval(ulong ownerClientId, bool createPlayerObject, uint?
}
}
-
-
///
/// Spawns the newly approved player
///
diff --git a/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs b/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs
index 17061d854e..5e99d222a6 100644
--- a/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs
+++ b/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs
@@ -115,9 +115,25 @@ public class NetworkSceneManager
///
public event SceneEventDelegate OnSceneEvent;
- internal readonly HashSet RegisteredSceneNames = new HashSet();
- internal readonly Dictionary SceneNameToIndex = new Dictionary();
- internal readonly Dictionary SceneIndexToString = new Dictionary();
+ /// Delegate declaration for the handler that provides
+ /// an additional level of scene loading security and/or validation to assure the scene being loaded
+ /// is valid scene to be loaded in the LoadSceneMode specified.
+ ///
+ /// Build Settings Scenes in Build List index of the scene
+ /// Name of the scene
+ /// LoadSceneMode the scene is going to be loaded
+ /// true (valid) or false (not valid)
+ public delegate bool VerifySceneBeforeLoadingDelegateHandler(int sceneIndex, string sceneName, LoadSceneMode loadSceneMode);
+
+ ///
+ /// Delegate handler defined by that is invoked before the
+ /// server or client loads a scene during an active netcode game session.
+ /// Client Side: In order for clients to be notified of this condition you must subscribe to the event.
+ /// Server Side: will return .
+ ///
+ public VerifySceneBeforeLoadingDelegateHandler VerifySceneBeforeLoading;
+
+
internal readonly Dictionary SceneEventProgressTracking = new Dictionary();
///
@@ -151,6 +167,11 @@ public class NetworkSceneManager
///
internal Dictionary ServerSceneHandleToClientSceneHandle = new Dictionary();
+ ///
+ /// The scenes in the build without their path
+ ///
+ internal List ScenesInBuild = new List();
+
///
/// The Condition: While a scene is asynchronously loaded in single loading scene mode, if any new NetworkObjects are spawned
/// they need to be moved into the do not destroy temporary scene
@@ -181,6 +202,29 @@ public class NetworkSceneManager
internal Scene DontDestroyOnLoadScene;
+ ///
+ /// Gets the scene name from full path to the scene
+ ///
+ ///
+ internal string GetSceneNameFromPath(string scenePath)
+ {
+ var begin = scenePath.LastIndexOf("/", StringComparison.Ordinal) + 1;
+ var end = scenePath.LastIndexOf(".", StringComparison.Ordinal);
+ return scenePath.Substring(begin, end - begin);
+ }
+
+ ///
+ /// Generates the scenes in build list
+ ///
+ internal void GenerateScenesInBuild()
+ {
+ ScenesInBuild.Clear();
+ for (int i = 0; i < SceneManager.sceneCountInBuildSettings; i++)
+ {
+ ScenesInBuild.Add(GetSceneNameFromPath(SceneUtility.GetScenePathByBuildIndex(i)));
+ }
+ }
+
///
/// Constructor
///
@@ -191,6 +235,8 @@ internal NetworkSceneManager(NetworkManager networkManager)
SceneEventData = new SceneEventData(networkManager);
ClientSynchEventData = new SceneEventData(networkManager);
+ GenerateScenesInBuild();
+
// If NetworkManager has this set to true, then we can get the DDOL (DontDestroyOnLoad) from its GaemObject
if (networkManager.DontDestroy)
{
@@ -222,6 +268,35 @@ internal NetworkSceneManager(NetworkManager networkManager)
ScenesLoaded.Add(DontDestroyOnLoadScene.handle, DontDestroyOnLoadScene);
}
+ ///
+ /// If the VerifySceneBeforeLoading delegate handler has been set by the user, this will provide
+ /// an additional level of security and/or validation that the scene being loaded in the specified
+ /// loading mode is "a valid scene to be loaded in the LoadSceneMode specified".
+ ///
+ /// index into ScenesInBuild
+ /// Name of the scene
+ /// LoadSceneMode the scene is going to be loaded
+ /// true (Valid) or false (Invalid)
+ internal bool ValidateSceneBeforeLoading(uint sceneIndex, LoadSceneMode loadSceneMode)
+ {
+ var validated = true;
+ var sceneName = ScenesInBuild[(int)sceneIndex];
+ if (VerifySceneBeforeLoading != null)
+ {
+ validated = VerifySceneBeforeLoading.Invoke((int)sceneIndex, sceneName, loadSceneMode);
+ }
+ if (!validated)
+ {
+ var serverHostorClient = "Client";
+ if (m_NetworkManager.IsServer)
+ {
+ serverHostorClient = m_NetworkManager.IsHost ? "Host" : "Server";
+ }
+ Debug.LogWarning($"Scene {sceneName} of Scenes in Build Index {SceneEventData.SceneIndex} being loaded in {loadSceneMode.ToString()} mode failed validation on the {serverHostorClient}!");
+ }
+ return validated;
+ }
+
///
/// Since SceneManager.GetSceneByName only returns the first scene that matches the name
/// we must "find" a newly added scene by looking through all loaded scenes and determining
@@ -354,75 +429,84 @@ private void SendSceneEventData(ulong[] targetClientIds)
}
///
- /// Returns the Netcode scene index from a scene
+ /// Verifies the scene name is valid relative to the scenes in build list
///
- ///
- /// Netcode Scene Index
- private uint GetNetcodeSceneIndexFromScene(Scene scene)
+ ///
+ /// true (Valid) or false (Invalid)
+ internal bool IsSceneNameValid(string sceneName)
{
- uint index = 0;
- if (!SceneNameToIndex.TryGetValue(scene.name, out index))
+ if (ScenesInBuild.Contains(sceneName))
{
- if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
- {
- NetworkLog.LogWarning($"The current scene ({scene.name}) is not registered as a network scene.");
- }
- //MaxValue denotes an error
- return uint.MaxValue;
+ return true;
}
- return index;
+ return false;
+ }
+
+ ///
+ /// Used to determine if the index value is within the range of valid
+ /// build indices.
+ ///
+ /// index value to check
+ /// true (Valid) or false (Invalid)
+ internal bool IsSceneIndexValid(uint index)
+ {
+ return (index >= 0 && index < ScenesInBuild.Count);
}
///
- /// Returns the scene name from the Netcode scene index
- /// Note: This is not the same as the Build Settings Scenes in Build index
+ /// Gets the build Index value for the scene name
///
- /// Netcode Scene Index
- /// scene name
- private string GetSceneNameFromNetcodeSceneIndex(uint sceneIndex)
+ /// scene name
+ /// build index
+ internal uint GetBuildIndexFromSceneName(string sceneName)
{
- var sceneName = string.Empty;
- if (!SceneIndexToString.TryGetValue(sceneIndex, out sceneName))
+ if (IsSceneNameValid(sceneName))
{
- if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
- {
- NetworkLog.LogWarning($"The current scene index ({sceneIndex}) is not registered as a network scene.");
- }
+ return (uint)ScenesInBuild.IndexOf(sceneName);
}
- return sceneName;
+ return uint.MaxValue;
}
///
- /// Adds a scene during runtime.
- /// The index is REQUIRED to be unique AND the same across all instances.
+ /// Entry method for scene unloading validation
///
- /// Scene name.
- /// Index.
- public void AddRuntimeSceneName(string sceneName, uint index)
+ /// the scene to be unloaded
+ ///
+ private SceneEventProgress ValidateSceneEventUnLoading(Scene scene)
{
- if (!m_NetworkManager.NetworkConfig.AllowRuntimeSceneChanges)
+ if (!m_NetworkManager.IsServer)
{
- throw new NetworkConfigurationException($"Cannot change the scene configuration when {nameof(NetworkConfig.AllowRuntimeSceneChanges)} is false");
+ throw new NotServerException("Only server can start a scene event!");
}
- RegisteredSceneNames.Add(sceneName);
- SceneIndexToString.Add(index, sceneName);
- SceneNameToIndex.Add(sceneName, index);
+ if (!m_NetworkManager.NetworkConfig.EnableSceneManagement)
+ {
+ //Log message about enabling SceneManagement
+ throw new Exception($"{nameof(NetworkConfig.EnableSceneManagement)} flag is not enabled in the {nameof(NetworkManager)}'s {nameof(NetworkConfig)}. " +
+ $"Please set {nameof(NetworkConfig.EnableSceneManagement)} flag to true before calling " +
+ $"{nameof(NetworkSceneManager.LoadScene)} or {nameof(NetworkSceneManager.UnloadScene)}.");
+ }
+
+ if (!scene.isLoaded)
+ {
+ Debug.LogWarning($"{nameof(UnloadScene)} was called, but the scene {scene.name} is not currently loaded!");
+ return new SceneEventProgress(null, SceneEventProgressStatus.SceneNotLoaded);
+ }
+
+ return ValidateSceneEvent(scene.name, true);
}
///
- /// Validates the new scene event request by the server-side code.
- /// This also initializes some commonly shared values as well as SceneEventProgress
+ /// Entry method for scene loading validation
///
- ///
- /// that should have a of otherwise it failed.
- private SceneEventProgress ValidateServerSceneEvent(string sceneName, bool isUnloading = false)
+ /// scene name to load
+ ///
+ private SceneEventProgress ValidateSceneEventLoading(string sceneName)
{
if (!m_NetworkManager.IsServer)
{
throw new NotServerException("Only server can start a scene event!");
}
-
if (!m_NetworkManager.NetworkConfig.EnableSceneManagement)
{
//Log message about enabling SceneManagement
@@ -431,6 +515,17 @@ private SceneEventProgress ValidateServerSceneEvent(string sceneName, bool isUnl
$"{nameof(NetworkSceneManager.LoadScene)} or {nameof(NetworkSceneManager.UnloadScene)}.");
}
+ return ValidateSceneEvent(sceneName);
+ }
+
+ ///
+ /// Validates the new scene event request by the server-side code.
+ /// This also initializes some commonly shared values as well as SceneEventProgress
+ ///
+ ///
+ /// that should have a of otherwise it failed.
+ private SceneEventProgress ValidateSceneEvent(string sceneName, bool isUnloading = false)
+ {
// Return scene event already in progress if one is already in progress... :)
if (s_IsSceneEventActive)
{
@@ -438,13 +533,13 @@ private SceneEventProgress ValidateServerSceneEvent(string sceneName, bool isUnl
}
// Return invalid scene name status if the scene name is invalid... :)
- if (!RegisteredSceneNames.Contains(sceneName))
+ if (!IsSceneNameValid(sceneName))
{
return new SceneEventProgress(null, SceneEventProgressStatus.InvalidSceneName);
}
var sceneEventProgress = new SceneEventProgress(m_NetworkManager);
- sceneEventProgress.SceneName = sceneName;
+ sceneEventProgress.SceneIndex = GetBuildIndexFromSceneName(sceneName);
SceneEventProgressTracking.Add(sceneEventProgress.Guid, sceneEventProgress);
if (!isUnloading)
@@ -478,7 +573,7 @@ private bool OnSceneEventProgressCompleted(SceneEventProgress sceneEventProgress
{
using var nonNullContext = (InternalCommandContext)context;
ClientSynchEventData.SceneEventGuid = sceneEventProgress.Guid;
- ClientSynchEventData.SceneIndex = SceneNameToIndex[sceneEventProgress.SceneName];
+ ClientSynchEventData.SceneIndex = sceneEventProgress.SceneIndex;
ClientSynchEventData.SceneEventType = sceneEventProgress.SceneEventType;
ClientSynchEventData.ClientsCompleted = sceneEventProgress.DoneClients;
ClientSynchEventData.ClientsTimedOut = m_NetworkManager.ConnectedClients.Keys.Except(sceneEventProgress.DoneClients).ToList();
@@ -489,7 +584,7 @@ private bool OnSceneEventProgressCompleted(SceneEventProgress sceneEventProgress
OnSceneEvent?.Invoke(new SceneEvent()
{
SceneEventType = sceneEventProgress.SceneEventType,
- SceneName = sceneEventProgress.SceneName,
+ SceneName = ScenesInBuild[(int)sceneEventProgress.SceneIndex],
ClientId = m_NetworkManager.ServerClientId,
LoadSceneMode = sceneEventProgress.LoadSceneMode,
ClientsThatCompleted = sceneEventProgress.DoneClients,
@@ -518,7 +613,7 @@ public SceneEventProgressStatus UnloadScene(Scene scene)
return SceneEventProgressStatus.SceneNotLoaded;
}
- var sceneEventProgress = ValidateServerSceneEvent(sceneName, true);
+ var sceneEventProgress = ValidateSceneEventUnLoading(scene);
if (sceneEventProgress.Status != SceneEventProgressStatus.Started)
{
return sceneEventProgress.Status;
@@ -532,7 +627,7 @@ public SceneEventProgressStatus UnloadScene(Scene scene)
SceneEventData.SceneEventGuid = sceneEventProgress.Guid;
SceneEventData.SceneEventType = SceneEventData.SceneEventTypes.S2C_Unload;
- SceneEventData.SceneIndex = SceneNameToIndex[sceneName];
+ SceneEventData.SceneIndex = GetBuildIndexFromSceneName(sceneName);
SceneEventData.SceneHandle = sceneHandle;
// This will be the message we send to everyone when this scene event sceneEventProgress is complete
@@ -564,8 +659,7 @@ public SceneEventProgressStatus UnloadScene(Scene scene)
///
private void OnClientUnloadScene()
{
- var sceneName = GetSceneNameFromNetcodeSceneIndex(SceneEventData.SceneIndex);
- if (sceneName == string.Empty)
+ if (!IsSceneIndexValid(SceneEventData.SceneIndex))
{
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
{
@@ -575,9 +669,11 @@ private void OnClientUnloadScene()
return;
}
+ var sceneName = ScenesInBuild[(int)SceneEventData.SceneIndex];
+
if (!ServerSceneHandleToClientSceneHandle.ContainsKey(SceneEventData.SceneHandle))
{
- throw new Exception($"Client failed to unload scene {GetSceneNameFromNetcodeSceneIndex(SceneEventData.SceneIndex)} " +
+ throw new Exception($"Client failed to unload scene {sceneName} " +
$"because we are missing the client scene handle due to the server scene handle {SceneEventData.SceneHandle} not being found!");
}
@@ -586,7 +682,7 @@ private void OnClientUnloadScene()
if (!ScenesLoaded.ContainsKey(sceneHandle))
{
// Error scene handle not found!
- throw new Exception($"Client failed to unload scene {GetSceneNameFromNetcodeSceneIndex(SceneEventData.SceneIndex)} " +
+ throw new Exception($"Client failed to unload scene {sceneName} " +
$"because the client scene handle {sceneHandle} was not found in ScenesLoaded!");
}
s_IsSceneEventActive = true;
@@ -658,7 +754,7 @@ private void OnSceneUnloaded()
{
SceneEventType = SceneEventData.SceneEventType,
LoadSceneMode = SceneEventData.LoadSceneMode,
- SceneName = GetSceneNameFromNetcodeSceneIndex(SceneEventData.SceneIndex),
+ SceneName = ScenesInBuild[(int)SceneEventData.SceneIndex],
ClientId = m_NetworkManager.IsServer ? m_NetworkManager.ServerClientId : m_NetworkManager.LocalClientId
});
@@ -708,7 +804,7 @@ internal void UnloadAdditivelyLoadedScenes()
/// ( means it was successful)
public SceneEventProgressStatus LoadScene(string sceneName, LoadSceneMode loadSceneMode)
{
- var sceneEventProgress = ValidateServerSceneEvent(sceneName);
+ var sceneEventProgress = ValidateSceneEventLoading(sceneName);
if (sceneEventProgress.Status != SceneEventProgressStatus.Started)
{
return sceneEventProgress.Status;
@@ -721,9 +817,16 @@ public SceneEventProgressStatus LoadScene(string sceneName, LoadSceneMode loadSc
// Now set up the current scene event
SceneEventData.SceneEventGuid = sceneEventProgress.Guid;
SceneEventData.SceneEventType = SceneEventData.SceneEventTypes.S2C_Load;
- SceneEventData.SceneIndex = SceneNameToIndex[sceneName];
+ SceneEventData.SceneIndex = GetBuildIndexFromSceneName(sceneName);
SceneEventData.LoadSceneMode = loadSceneMode;
+ // This both checks to make sure the scene is valid and if not resets the active scene event
+ s_IsSceneEventActive = ValidateSceneBeforeLoading(SceneEventData.SceneIndex, loadSceneMode);
+ if (!s_IsSceneEventActive)
+ {
+ return SceneEventProgressStatus.SceneFailedVerification;
+ }
+
if (SceneEventData.LoadSceneMode == LoadSceneMode.Single)
{
// Destroy current scene objects before switching.
@@ -762,13 +865,20 @@ public SceneEventProgressStatus LoadScene(string sceneName, LoadSceneMode loadSc
/// Stream data associated with the event
private void OnClientSceneLoadingEvent(Stream objectStream)
{
- if (!SceneIndexToString.TryGetValue(SceneEventData.SceneIndex, out string sceneName) || !RegisteredSceneNames.Contains(sceneName))
+ if (!IsSceneIndexValid(SceneEventData.SceneIndex))
{
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
{
NetworkLog.LogWarning("Server requested a scene switch to a non-registered scene");
}
+ return;
+ }
+
+ var sceneName = ScenesInBuild[(int)SceneEventData.SceneIndex];
+ // Run scene validation before loading a scene
+ if (!ValidateSceneBeforeLoading(SceneEventData.SceneIndex, SceneEventData.LoadSceneMode))
+ {
return;
}
@@ -792,7 +902,7 @@ private void OnClientSceneLoadingEvent(Stream objectStream)
}
else
{
- throw new Exception($"Could not find the scene handle {SceneEventData.SceneHandle} for scene {GetSceneNameFromNetcodeSceneIndex(SceneEventData.SceneIndex)} " +
+ throw new Exception($"Could not find the scene handle {SceneEventData.SceneHandle} for scene {sceneName} " +
$"during unit test. Did you forget to register this in the unit test?");
}
return;
@@ -930,13 +1040,12 @@ private void OnServerLoadedScene(Scene scene)
}
s_IsSceneEventActive = false;
-
//First, notify local server that the scene was loaded
OnSceneEvent?.Invoke(new SceneEvent()
{
SceneEventType = SceneEventData.SceneEventTypes.C2S_LoadComplete,
LoadSceneMode = SceneEventData.LoadSceneMode,
- SceneName = GetSceneNameFromNetcodeSceneIndex(SceneEventData.SceneIndex),
+ SceneName = ScenesInBuild[(int)SceneEventData.SceneIndex],
ClientId = m_NetworkManager.ServerClientId,
Scene = scene,
});
@@ -965,7 +1074,7 @@ private void OnClientLoadedScene(Scene scene)
{
SceneEventType = SceneEventData.SceneEventTypes.C2S_LoadComplete,
LoadSceneMode = SceneEventData.LoadSceneMode,
- SceneName = GetSceneNameFromNetcodeSceneIndex(SceneEventData.SceneIndex),
+ SceneName = ScenesInBuild[(int)SceneEventData.SceneIndex],
ClientId = m_NetworkManager.LocalClientId,
Scene = scene,
});
@@ -995,7 +1104,7 @@ internal void SynchronizeNetworkObjects(ulong clientId)
{
var scene = SceneManager.GetSceneAt(i);
- var sceneIndex = GetNetcodeSceneIndexFromScene(scene);
+ var sceneIndex = GetBuildIndexFromSceneName(scene.name);
if (sceneIndex == uint.MaxValue)
{
@@ -1005,9 +1114,17 @@ internal void SynchronizeNetworkObjects(ulong clientId)
// If we are the base scene, then we set the root scene index;
if (activeScene == scene)
{
+ if(!ValidateSceneBeforeLoading(sceneIndex, LoadSceneMode.Single))
+ {
+ continue;
+ }
ClientSynchEventData.SceneIndex = sceneIndex;
ClientSynchEventData.SceneHandle = scene.handle;
}
+ else if (!ValidateSceneBeforeLoading(sceneIndex, LoadSceneMode.Additive))
+ {
+ continue;
+ }
ClientSynchEventData.AddSceneToSynchronize(sceneIndex, scene.handle);
}
@@ -1038,19 +1155,24 @@ private void OnClientBeginSync()
{
var sceneIndex = SceneEventData.GetNextSceneSynchronizationIndex();
var sceneHandle = SceneEventData.GetNextSceneSynchronizationHandle();
- if (!SceneIndexToString.TryGetValue(sceneIndex, out string sceneName) || !RegisteredSceneNames.Contains(sceneName))
+ if (!IsSceneIndexValid(sceneIndex))
{
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
{
NetworkLog.LogWarning("Server requested a scene switch to a non-registered scene");
}
-
return;
}
-
+ var sceneName = ScenesInBuild[(int)sceneIndex];
var activeScene = SceneManager.GetActiveScene();
var loadSceneMode = sceneIndex == SceneEventData.SceneIndex ? SceneEventData.LoadSceneMode : LoadSceneMode.Additive;
+ // Always check to see if the scene needs to be validated
+ if (!ValidateSceneBeforeLoading(SceneEventData.SceneIndex, loadSceneMode))
+ {
+ return;
+ }
+
// If this is the beginning of the synchronization event, then send client a notification that synchronization has begun
if (sceneIndex == SceneEventData.SceneIndex)
{
@@ -1115,7 +1237,7 @@ private void OnClientBeginSync()
/// Netcode scene index that was loaded
private void ClientLoadedSynchronization(uint sceneIndex, int sceneHandle)
{
- var sceneName = GetSceneNameFromNetcodeSceneIndex(sceneIndex);
+ var sceneName = ScenesInBuild[(int)sceneIndex];
var nextScene = GetAndAddNewlyLoadedSceneByName(sceneName);
if (!nextScene.isLoaded || !nextScene.IsValid())
@@ -1237,7 +1359,7 @@ private void HandleClientSceneEvent(Stream stream)
OnSceneEvent?.Invoke(new SceneEvent()
{
SceneEventType = SceneEventData.SceneEventType,
- SceneName = GetSceneNameFromNetcodeSceneIndex(SceneEventData.SceneIndex),
+ SceneName = ScenesInBuild[(int)SceneEventData.SceneIndex],
ClientId = m_NetworkManager.ServerClientId,
LoadSceneMode = SceneEventData.LoadSceneMode,
ClientsThatCompleted = SceneEventData.ClientsCompleted,
@@ -1270,7 +1392,7 @@ private void HandleServerSceneEvent(ulong clientId, Stream stream)
{
SceneEventType = SceneEventData.SceneEventType,
LoadSceneMode = SceneEventData.LoadSceneMode,
- SceneName = GetSceneNameFromNetcodeSceneIndex(SceneEventData.SceneIndex),
+ SceneName = ScenesInBuild[(int)SceneEventData.SceneIndex],
ClientId = clientId
});
@@ -1292,7 +1414,7 @@ private void HandleServerSceneEvent(ulong clientId, Stream stream)
{
SceneEventType = SceneEventData.SceneEventType,
LoadSceneMode = SceneEventData.LoadSceneMode,
- SceneName = GetSceneNameFromNetcodeSceneIndex(SceneEventData.SceneIndex),
+ SceneName = ScenesInBuild[(int)SceneEventData.SceneIndex],
ClientId = clientId
});
diff --git a/com.unity.netcode.gameobjects/Runtime/SceneManagement/SceneEventProgress.cs b/com.unity.netcode.gameobjects/Runtime/SceneManagement/SceneEventProgress.cs
index d8db7d3476..d38df4ddfb 100644
--- a/com.unity.netcode.gameobjects/Runtime/SceneManagement/SceneEventProgress.cs
+++ b/com.unity.netcode.gameobjects/Runtime/SceneManagement/SceneEventProgress.cs
@@ -37,7 +37,11 @@ public enum SceneEventProgressStatus
/// or is invalid
///
InvalidSceneName,
-
+ ///
+ /// Server side: Returned if the delegate handler returns false
+ /// (i.e. scene is considered not valid/safe to load)
+ ///
+ SceneFailedVerification,
///
/// This is used for internal error notifications.
/// If you receive this event then it is most likely due to a bug.
@@ -84,7 +88,7 @@ internal class SceneEventProgress
///
internal bool AreAllClientsDoneLoading { get; private set; }
- internal string SceneName { get; set; }
+ internal uint SceneIndex { get; set; }
internal Guid Guid { get; } = Guid.NewGuid();
diff --git a/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerCustomMessageManagerTests.cs b/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerCustomMessageManagerTests.cs
index 2da24c6d38..2094b1efd3 100644
--- a/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerCustomMessageManagerTests.cs
+++ b/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerCustomMessageManagerTests.cs
@@ -1,7 +1,5 @@
-using System.Collections.Generic;
using NUnit.Framework;
using UnityEngine;
-using UnityEngine.SceneManagement;
namespace Unity.Netcode.EditorTests
{
@@ -14,19 +12,13 @@ public void CustomMessageManagerAssigned()
var networkManager = gameObject.AddComponent();
var transport = gameObject.AddComponent();
- // Netcode sets this in validate
- networkManager.NetworkConfig = new NetworkConfig()
- {
- // Set the current scene to prevent unexpected log messages which would trigger a failure
- RegisteredScenes = new List() { SceneManager.GetActiveScene().name }
- };
-
+ networkManager.NetworkConfig = new NetworkConfig();
// Set dummy transport that does nothing
networkManager.NetworkConfig.NetworkTransport = transport;
CustomMessagingManager preManager = networkManager.CustomMessagingManager;
- // Start server to cause init
+ // Start server to cause initialization
networkManager.StartServer();
Debug.Assert(preManager == null);
diff --git a/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerMessageHandlerTests.cs b/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerMessageHandlerTests.cs
index 45727c22f8..2b01929ccc 100644
--- a/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerMessageHandlerTests.cs
+++ b/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerMessageHandlerTests.cs
@@ -1,9 +1,7 @@
using System;
-using System.Collections.Generic;
using NUnit.Framework;
using Unity.Netcode.Editor;
using UnityEngine;
-using UnityEngine.SceneManagement;
using UnityEngine.TestTools;
using Object = UnityEngine.Object;
@@ -19,13 +17,7 @@ public void MessageHandlerReceivedMessageServerClient()
var networkManager = gameObject.AddComponent();
var transport = gameObject.AddComponent();
- // Netcode sets this in validate
- networkManager.NetworkConfig = new NetworkConfig()
- {
- // Set the current scene to prevent unexpected log messages which would trigger a failure
- RegisteredScenes = new List() { SceneManager.GetActiveScene().name }
- };
-
+ networkManager.NetworkConfig = new NetworkConfig();
// Set dummy transport that does nothing
networkManager.NetworkConfig.NetworkTransport = transport;
diff --git a/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerSceneManagerTests.cs b/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerSceneManagerTests.cs
index c641b2f4b1..c1f5b30d14 100644
--- a/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerSceneManagerTests.cs
+++ b/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerSceneManagerTests.cs
@@ -1,7 +1,5 @@
-using System.Collections.Generic;
using NUnit.Framework;
using UnityEngine;
-using UnityEngine.SceneManagement;
namespace Unity.Netcode.EditorTests
{
@@ -13,20 +11,13 @@ public void SceneManagerAssigned()
var gameObject = new GameObject(nameof(SceneManagerAssigned));
var networkManager = gameObject.AddComponent();
var transport = gameObject.AddComponent();
-
- // Netcode sets this in validate
- networkManager.NetworkConfig = new NetworkConfig()
- {
- // Set the current scene to prevent unexpected log messages which would trigger a failure
- RegisteredScenes = new List() { SceneManager.GetActiveScene().name }
- };
-
+ networkManager.NetworkConfig = new NetworkConfig();
// Set dummy transport that does nothing
networkManager.NetworkConfig.NetworkTransport = transport;
NetworkSceneManager preManager = networkManager.SceneManager;
- // Start server to cause init
+ // Start server to cause initialization process
networkManager.StartServer();
Debug.Assert(preManager == null);
diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/BaseMultiInstanceTest.cs b/com.unity.netcode.gameobjects/Tests/Runtime/BaseMultiInstanceTest.cs
index 756385a7af..ce1691f339 100644
--- a/com.unity.netcode.gameobjects/Tests/Runtime/BaseMultiInstanceTest.cs
+++ b/com.unity.netcode.gameobjects/Tests/Runtime/BaseMultiInstanceTest.cs
@@ -43,8 +43,7 @@ public virtual IEnumerator Teardown()
// Make sure any NetworkObject with a GlobalObjectIdHash value of 0 is destroyed
// If we are tearing down, we don't want to leave NetworkObjects hanging around
var networkObjects = Object.FindObjectsOfType().ToList();
- var networkObjectsList = networkObjects.Where(c => c.GlobalObjectIdHash == 0);
- foreach (var networkObject in networkObjectsList)
+ foreach (var networkObject in networkObjects)
{
Object.DestroyImmediate(networkObject);
}
diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Helpers/NetworkManagerHelper.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Helpers/NetworkManagerHelper.cs
index 91cbe0a571..57129aef1b 100644
--- a/com.unity.netcode.gameobjects/Tests/Runtime/Helpers/NetworkManagerHelper.cs
+++ b/com.unity.netcode.gameobjects/Tests/Runtime/Helpers/NetworkManagerHelper.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using UnityEngine;
-using UnityEngine.SceneManagement;
using NUnit.Framework;
using Unity.Netcode.Transports.UNET;
@@ -71,19 +70,13 @@ public static bool StartNetworkManager(out NetworkManager networkManager, Networ
Debug.Log($"{nameof(NetworkManager)} Instantiated.");
var unetTransport = NetworkManagerGameObject.AddComponent();
-
if (networkConfig == null)
{
networkConfig = new NetworkConfig
{
EnableSceneManagement = false,
- RegisteredScenes = new List() { SceneManager.GetActiveScene().name }
};
}
- else
- {
- networkConfig.RegisteredScenes.Add(SceneManager.GetActiveScene().name);
- }
NetworkManagerObject.NetworkConfig = networkConfig;
diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/MultiInstanceHelpers.cs b/com.unity.netcode.gameobjects/Tests/Runtime/MultiInstanceHelpers.cs
index c2eb731e19..a59d3300dd 100644
--- a/com.unity.netcode.gameobjects/Tests/Runtime/MultiInstanceHelpers.cs
+++ b/com.unity.netcode.gameobjects/Tests/Runtime/MultiInstanceHelpers.cs
@@ -31,7 +31,6 @@ public static class MultiInstanceHelpers
public static bool Create(int clientCount, out NetworkManager server, out NetworkManager[] clients, int targetFrameRate = 60)
{
s_NetworkManagerInstances = new List();
-
CreateNewClients(clientCount, out clients);
// Create gameObject
@@ -44,8 +43,6 @@ public static bool Create(int clientCount, out NetworkManager server, out Networ
// Set the NetworkConfig
server.NetworkConfig = new NetworkConfig()
{
- // Set the current scene to prevent unexpected log messages which would trigger a failure
- RegisteredScenes = new List() { SceneManager.GetActiveScene().name },
// Set transport
NetworkTransport = go.AddComponent()
};
@@ -65,7 +62,7 @@ public static bool Create(int clientCount, out NetworkManager server, out Networ
public static bool CreateNewClients(int clientCount, out NetworkManager[] clients)
{
clients = new NetworkManager[clientCount];
-
+ var activeSceneName = SceneManager.GetActiveScene().name;
for (int i = 0; i < clientCount; i++)
{
// Create gameObject
@@ -76,8 +73,6 @@ public static bool CreateNewClients(int clientCount, out NetworkManager[] client
// Set the NetworkConfig
clients[i].NetworkConfig = new NetworkConfig()
{
- // Set the current scene to prevent unexpected log messages which would trigger a failure
- RegisteredScenes = new List() { SceneManager.GetActiveScene().name },
// Set transport
NetworkTransport = go.AddComponent()
};
@@ -131,7 +126,7 @@ public static void Destroy()
// Destroy the network manager instances
foreach (var networkManager in NetworkManagerInstances)
{
- Object.Destroy(networkManager.gameObject);
+ Object.DestroyImmediate(networkManager.gameObject);
}
NetworkManagerInstances.Clear();
@@ -139,7 +134,8 @@ public static void Destroy()
// Destroy the temporary GameObject used to run co-routines
if (s_CoroutineRunner != null)
{
- Object.Destroy(s_CoroutineRunner);
+ s_CoroutineRunner.StopAllCoroutines();
+ Object.DestroyImmediate(s_CoroutineRunner);
}
Application.targetFrameRate = s_OriginalTargetFrameRate;
diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkObject/NetworkObjectOnSpawnTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkObject/NetworkObjectOnSpawnTests.cs
index 37d262d516..835f852625 100644
--- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkObject/NetworkObjectOnSpawnTests.cs
+++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkObject/NetworkObjectOnSpawnTests.cs
@@ -57,7 +57,6 @@ public override IEnumerator Setup()
[UnityTearDown]
public override IEnumerator Teardown()
{
- yield return base.Teardown();
if (m_TestNetworkObjectPrefab != null)
{
@@ -68,6 +67,8 @@ public override IEnumerator Teardown()
{
Object.Destroy(m_TestNetworkObjectInstance);
}
+ yield return base.Teardown();
+
}
///
diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkPrefabHandlerTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkPrefabHandlerTests.cs
index c4fdcac29f..da1b712051 100644
--- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkPrefabHandlerTests.cs
+++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkPrefabHandlerTests.cs
@@ -17,13 +17,13 @@ public class NetworkPrefabHandlerTests
{
private const string k_TestPrefabObjectName = "NetworkPrefabTestObject";
- private uint m_GlobalObjectIdHashBase = 123456;
+ private uint m_ObjectId = 1;
private GameObject MakeValidNetworkPrefab()
{
- Guid baseObjectID = NetworkManagerHelper.AddGameNetworkObject(k_TestPrefabObjectName + m_GlobalObjectIdHashBase.ToString());
+ Guid baseObjectID = NetworkManagerHelper.AddGameNetworkObject(k_TestPrefabObjectName + m_ObjectId.ToString());
NetworkObject validPrefab = NetworkManagerHelper.InstantiatedNetworkObjects[baseObjectID];
- MultiInstanceHelpers.MakeNetworkObjectTestPrefab(validPrefab, m_GlobalObjectIdHashBase);
- m_GlobalObjectIdHashBase++;
+ MultiInstanceHelpers.MakeNetworkObjectTestPrefab(validPrefab);
+ m_ObjectId++;
return validPrefab.gameObject;
}
diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/ObjectParenting/NetworkObjectParentingTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/ObjectParenting/NetworkObjectParentingTests.cs
index 9f1386bae7..90f7317216 100644
--- a/com.unity.netcode.gameobjects/Tests/Runtime/ObjectParenting/NetworkObjectParentingTests.cs
+++ b/com.unity.netcode.gameobjects/Tests/Runtime/ObjectParenting/NetworkObjectParentingTests.cs
@@ -40,11 +40,24 @@ private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
}
}
+ private bool VerifySceneBeforeLoading(int sceneIndex, string sceneName, LoadSceneMode loadSceneMode)
+ {
+ if(sceneName.StartsWith("InitTestScene"))
+ {
+ return false;
+ }
+ return true;
+ }
+
[UnitySetUp]
public IEnumerator Setup()
{
SceneManager.sceneLoaded += OnSceneLoaded;
+ // We need NetworkManager to be instantiated first before you load scenes externally in order to be able to determine if
+ // we are running a unit test or not. (it is this or manually setting a property)
+ Assert.That(MultiInstanceHelpers.Create(k_ClientInstanceCount, out m_ServerNetworkManager, out m_ClientNetworkManagers));
+
var execAssembly = Assembly.GetExecutingAssembly();
var packagePath = PackageInfo.FindForAssembly(execAssembly).assetPath;
var scenePath = Path.Combine(packagePath, $"Tests/Runtime/ObjectParenting/{nameof(NetworkObjectParentingTests)}.unity");
@@ -56,7 +69,6 @@ public IEnumerator Setup()
const int setCount = k_ClientInstanceCount + 1;
- Assert.That(MultiInstanceHelpers.Create(k_ClientInstanceCount, out m_ServerNetworkManager, out m_ClientNetworkManagers));
Assert.That(m_ServerNetworkManager, Is.Not.Null);
Assert.That(m_ClientNetworkManagers, Is.Not.Null);
Assert.That(m_ClientNetworkManagers.Length, Is.EqualTo(k_ClientInstanceCount));
@@ -86,6 +98,18 @@ public IEnumerator Setup()
// Start server and client NetworkManager instances
Assert.That(MultiInstanceHelpers.Start(true, m_ServerNetworkManager, m_ClientNetworkManagers));
+ m_ServerNetworkManager.SceneManager.ScenesInBuild.Add(nameof(NetworkObjectParentingTests));
+ // Register our scene verification delegate handler so we don't load the unit test scene
+ m_ServerNetworkManager.SceneManager.VerifySceneBeforeLoading = VerifySceneBeforeLoading;
+ foreach (var entry in m_ClientNetworkManagers)
+ {
+ if (!entry.SceneManager.ScenesInBuild.Contains(nameof(NetworkObjectParentingTests)))
+ {
+ entry.SceneManager.ScenesInBuild.Add(nameof(NetworkObjectParentingTests));
+ }
+ // Register our scene verification delegate handler so we don't load the unit test scene
+ entry.SceneManager.VerifySceneBeforeLoading = VerifySceneBeforeLoading;
+ }
// Wait for connection on client side
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnected(m_ClientNetworkManagers));
diff --git a/testproject/Assets/Prefabs/RandomMoverObject.prefab b/testproject/Assets/Prefabs/RandomMoverObject.prefab
index 852d8d0059..44665854b4 100644
--- a/testproject/Assets/Prefabs/RandomMoverObject.prefab
+++ b/testproject/Assets/Prefabs/RandomMoverObject.prefab
@@ -146,7 +146,6 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: e96cb6065543e43c4a752faaa1468eb1, type: 3}
m_Name:
m_EditorClassIdentifier:
- Authority: 2
Channel: 0
InLocalSpace: 0
SyncPositionX: 1
@@ -158,6 +157,9 @@ MonoBehaviour:
SyncScaleX: 1
SyncScaleY: 1
SyncScaleZ: 1
+ PositionThreshold: 0
+ RotAngleThreshold: 0
+ ScaleThreshold: 0
FixedSendsPerSecond: 5
--- !u!114 &1932194183178713890
MonoBehaviour:
@@ -168,7 +170,7 @@ MonoBehaviour:
m_GameObject: {fileID: 771575417923360811}
m_Enabled: 1
m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: c552ef0ccf6ff8148a9c9606e7d3fc15, type: 3}
+ m_Script: {fileID: 11500000, guid: c4152da5a2f4e7746aecdcd815f6616b, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &2058396567867412356
diff --git a/testproject/Assets/Prefabs/SceneLevelGeometry.prefab b/testproject/Assets/Prefabs/SceneLevelGeometry.prefab
index 680403c8f0..da9864d139 100644
--- a/testproject/Assets/Prefabs/SceneLevelGeometry.prefab
+++ b/testproject/Assets/Prefabs/SceneLevelGeometry.prefab
@@ -1,5 +1,93 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &910007655143077103
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 6283120762215196916}
+ - component: {fileID: 3739510624437302406}
+ m_Layer: 0
+ m_Name: CornerBumper (1)
+ m_TagString: Boundary
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &6283120762215196916
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 910007655143077103}
+ m_LocalRotation: {x: -0, y: -0.9244967, z: -0, w: -0.38119}
+ m_LocalPosition: {x: -29.72, y: 0.98, z: 29.82}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_Children: []
+ m_Father: {fileID: 4012615692778511849}
+ m_RootOrder: 6
+ m_LocalEulerAnglesHint: {x: 0, y: -224.815, z: 0}
+--- !u!65 &3739510624437302406
+BoxCollider:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 910007655143077103}
+ m_Material: {fileID: 0}
+ m_IsTrigger: 0
+ m_Enabled: 1
+ serializedVersion: 2
+ m_Size: {x: 4, y: 2, z: 1}
+ m_Center: {x: 0, y: 0, z: 0}
+--- !u!1 &1854705290947220173
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 2290144462706082272}
+ - component: {fileID: 4559046433245738380}
+ m_Layer: 0
+ m_Name: CornerBumper (2)
+ m_TagString: Boundary
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &2290144462706082272
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1854705290947220173}
+ m_LocalRotation: {x: -0, y: -0.3771283, z: -0, w: -0.92616105}
+ m_LocalPosition: {x: -29.53, y: 0.98, z: -29.71}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_Children: []
+ m_Father: {fileID: 4012615692778511849}
+ m_RootOrder: 7
+ m_LocalEulerAnglesHint: {x: 0, y: -315.688, z: 0}
+--- !u!65 &4559046433245738380
+BoxCollider:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1854705290947220173}
+ m_Material: {fileID: 0}
+ m_IsTrigger: 0
+ m_Enabled: 1
+ serializedVersion: 2
+ m_Size: {x: 4, y: 2, z: 1}
+ m_Center: {x: 0, y: 0, z: 0}
--- !u!1 &4012615691354089848
GameObject:
m_ObjectHideFlags: 0
@@ -190,8 +278,8 @@ BoxCollider:
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 2
- m_Size: {x: 1, y: 1, z: 1}
- m_Center: {x: 0, y: 0, z: 0}
+ m_Size: {x: 2, y: 1, z: 1}
+ m_Center: {x: -0.5, y: 0, z: 0}
--- !u!1 &4012615691965054905
GameObject:
m_ObjectHideFlags: 0
@@ -286,8 +374,8 @@ BoxCollider:
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 2
- m_Size: {x: 1, y: 1, z: 1}
- m_Center: {x: 0, y: 0, z: 0}
+ m_Size: {x: 1, y: 1, z: 2}
+ m_Center: {x: 0, y: 0, z: 0.5}
--- !u!1 &4012615692269653858
GameObject:
m_ObjectHideFlags: 0
@@ -382,8 +470,8 @@ BoxCollider:
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 2
- m_Size: {x: 1, y: 1, z: 1}
- m_Center: {x: 0, y: 0, z: 0}
+ m_Size: {x: 1, y: 1, z: 2}
+ m_Center: {x: 0, y: 0, z: -0.5}
--- !u!1 &4012615692778511854
GameObject:
m_ObjectHideFlags: 0
@@ -394,7 +482,7 @@ GameObject:
m_Component:
- component: {fileID: 4012615692778511849}
m_Layer: 0
- m_Name: Level
+ m_Name: SceneLevelGeometry
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@@ -416,6 +504,10 @@ Transform:
- {fileID: 4012615692269653854}
- {fileID: 4012615691503252839}
- {fileID: 4012615692791378778}
+ - {fileID: 3910294717376836327}
+ - {fileID: 6283120762215196916}
+ - {fileID: 2290144462706082272}
+ - {fileID: 6959258897999621209}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@@ -513,5 +605,93 @@ BoxCollider:
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 2
- m_Size: {x: 1, y: 1, z: 1}
+ m_Size: {x: 2, y: 1, z: 1}
+ m_Center: {x: 0.5, y: 0, z: 0}
+--- !u!1 &4674276234353933548
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 3910294717376836327}
+ - component: {fileID: 3136259738973340924}
+ m_Layer: 0
+ m_Name: CornerBumper
+ m_TagString: Boundary
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &3910294717376836327
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 4674276234353933548}
+ m_LocalRotation: {x: 0, y: -0.38268343, z: 0, w: 0.92387956}
+ m_LocalPosition: {x: 29.7, y: 0.98, z: -29.61}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_Children: []
+ m_Father: {fileID: 4012615692778511849}
+ m_RootOrder: 5
+ m_LocalEulerAnglesHint: {x: 0, y: -45, z: 0}
+--- !u!65 &3136259738973340924
+BoxCollider:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 4674276234353933548}
+ m_Material: {fileID: 0}
+ m_IsTrigger: 0
+ m_Enabled: 1
+ serializedVersion: 2
+ m_Size: {x: 4, y: 2, z: 1}
+ m_Center: {x: 0, y: 0, z: 0}
+--- !u!1 &7080625901286762351
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 6959258897999621209}
+ - component: {fileID: 7672408768716900064}
+ m_Layer: 0
+ m_Name: CornerBumper (3)
+ m_TagString: Boundary
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &6959258897999621209
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 7080625901286762351}
+ m_LocalRotation: {x: -0, y: 0.93588465, z: -0, w: -0.35230666}
+ m_LocalPosition: {x: 29.26, y: 0.98, z: 29.45}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_Children: []
+ m_Father: {fileID: 4012615692778511849}
+ m_RootOrder: 8
+ m_LocalEulerAnglesHint: {x: 0, y: -498.74298, z: 0}
+--- !u!65 &7672408768716900064
+BoxCollider:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 7080625901286762351}
+ m_Material: {fileID: 0}
+ m_IsTrigger: 0
+ m_Enabled: 1
+ serializedVersion: 2
+ m_Size: {x: 4, y: 2, z: 1}
m_Center: {x: 0, y: 0, z: 0}
diff --git a/testproject/Assets/Samples/PrefabPool/PrefabPoolOverrideExample.unity b/testproject/Assets/Samples/PrefabPool/PrefabPoolOverrideExample.unity
index d3ffd1e1ec..d358a72d23 100644
--- a/testproject/Assets/Samples/PrefabPool/PrefabPoolOverrideExample.unity
+++ b/testproject/Assets/Samples/PrefabPool/PrefabPoolOverrideExample.unity
@@ -38,7 +38,7 @@ RenderSettings:
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
- m_IndirectSpecularColor: {r: 0.44657874, g: 0.49641275, b: 0.5748172, a: 1}
+ m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
@@ -265,6 +265,7 @@ MeshRenderer:
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
+ m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
@@ -563,6 +564,7 @@ MeshRenderer:
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
+ m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
@@ -850,7 +852,7 @@ GameObject:
- component: {fileID: 1024114719}
- component: {fileID: 1024114718}
m_Layer: 0
- m_Name: '[NetworkManager]'
+ m_Name: NetworkManager
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@@ -874,10 +876,6 @@ MonoBehaviour:
NetworkConfig:
ProtocolVersion: 0
NetworkTransport: {fileID: 1024114719}
- RegisteredScenes:
- - PrefabPoolExample
- - PrefabPoolOverrideExample
- AllowRuntimeSceneChanges: 0
PlayerPrefab: {fileID: 4079352819444256614, guid: c16f03336b6104576a565ef79ad643c0,
type: 3}
NetworkPrefabs:
@@ -905,6 +903,10 @@ MonoBehaviour:
LoadSceneTimeOut: 120
MessageBufferTimeout: 20
EnableNetworkLogs: 1
+ UseSnapshotDelta: 0
+ UseSnapshotSpawn: 0
+ ScenesInBuild: {fileID: 11400000, guid: bf58cb10b5121b843991aa419917e22c, type: 2}
+ DefaultScenesInBuildAssetNameAndPath: Assets/ScenesInBuildList.asset
--- !u!114 &1024114719
MonoBehaviour:
m_ObjectHideFlags: 0
@@ -1091,6 +1093,7 @@ MeshRenderer:
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
+ m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
@@ -1464,6 +1467,7 @@ MeshRenderer:
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
+ m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
@@ -1684,6 +1688,7 @@ MeshRenderer:
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
+ m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
@@ -1781,6 +1786,8 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
m_ClientServerToggle: {fileID: 1588117327}
+ m_TrackSceneEvents: 0
+ m_LogSceneEventsToConsole: 1
--- !u!114 &2107482023
MonoBehaviour:
m_ObjectHideFlags: 0
diff --git a/testproject/Assets/Tests/Manual/HybridScripts/RpcQueueManualTests.cs b/testproject/Assets/Tests/Manual/HybridScripts/RpcQueueManualTests.cs
index a2491102d0..e599b080bb 100644
--- a/testproject/Assets/Tests/Manual/HybridScripts/RpcQueueManualTests.cs
+++ b/testproject/Assets/Tests/Manual/HybridScripts/RpcQueueManualTests.cs
@@ -333,15 +333,16 @@ public override void OnNetworkSpawn()
}
///
- /// Unregister for the client connected and disconnected events upon being destroyed
+ /// Unregister for the client connected and disconnected events upon being despawned
///
- private void OnDestroy()
+ public override void OnNetworkDespawn()
{
if (IsServer)
{
NetworkManager.OnClientConnectedCallback -= OnClientConnectedCallback;
NetworkManager.OnClientDisconnectCallback -= OnClientDisconnectCallback;
}
+ base.OnNetworkDespawn();
}
///
diff --git a/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/AdditiveSceneMultiInstance.unity b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/AdditiveSceneMultiInstance.unity
index 5e2a4dcbf1..6ea9d5e74b 100644
--- a/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/AdditiveSceneMultiInstance.unity
+++ b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/AdditiveSceneMultiInstance.unity
@@ -123,6 +123,154 @@ NavMeshSettings:
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
+--- !u!1001 &151772428
+PrefabInstance:
+ m_ObjectHideFlags: 0
+ serializedVersion: 2
+ m_Modification:
+ m_TransformParent: {fileID: 0}
+ m_Modifications:
+ - target: {fileID: -5591000292386890817, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: GlobalObjectIdHash
+ value: 2264043126
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360811, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_Name
+ value: RandomMoverObject (1)
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_RootOrder
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalPosition.x
+ value: 4.08
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalPosition.y
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalPosition.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalRotation.w
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalRotation.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalRotation.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalRotation.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.z
+ value: 0
+ objectReference: {fileID: 0}
+ m_RemovedComponents: []
+ m_SourcePrefab: {fileID: 100100000, guid: ea906834639fa3f4ba65c95db6181d6b, type: 3}
+--- !u!1001 &365996112
+PrefabInstance:
+ m_ObjectHideFlags: 0
+ serializedVersion: 2
+ m_Modification:
+ m_TransformParent: {fileID: 0}
+ m_Modifications:
+ - target: {fileID: -5591000292386890817, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: GlobalObjectIdHash
+ value: 179273863
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360811, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_Name
+ value: RandomMoverObject (3)
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_RootOrder
+ value: 3
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalPosition.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalPosition.y
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalPosition.z
+ value: -5.45
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalRotation.w
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalRotation.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalRotation.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalRotation.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.z
+ value: 0
+ objectReference: {fileID: 0}
+ m_RemovedComponents: []
+ m_SourcePrefab: {fileID: 100100000, guid: ea906834639fa3f4ba65c95db6181d6b, type: 3}
--- !u!850595691 &903034822
LightingSettings:
m_ObjectHideFlags: 0
@@ -184,6 +332,80 @@ LightingSettings:
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
m_PVRFilteringAtrousPositionSigmaIndirect: 2
m_PVRFilteringAtrousPositionSigmaAO: 1
+--- !u!1001 &1152084533
+PrefabInstance:
+ m_ObjectHideFlags: 0
+ serializedVersion: 2
+ m_Modification:
+ m_TransformParent: {fileID: 0}
+ m_Modifications:
+ - target: {fileID: -5591000292386890817, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: GlobalObjectIdHash
+ value: 860074760
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360811, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_Name
+ value: RandomMoverObject (2)
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_RootOrder
+ value: 2
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalPosition.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalPosition.y
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalPosition.z
+ value: 8.05
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalRotation.w
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalRotation.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalRotation.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalRotation.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.z
+ value: 0
+ objectReference: {fileID: 0}
+ m_RemovedComponents: []
+ m_SourcePrefab: {fileID: 100100000, guid: ea906834639fa3f4ba65c95db6181d6b, type: 3}
--- !u!1001 &1247056486
PrefabInstance:
m_ObjectHideFlags: 0
@@ -209,7 +431,7 @@ PrefabInstance:
- target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
type: 3}
propertyPath: m_LocalPosition.x
- value: 0
+ value: -3.8
objectReference: {fileID: 0}
- target: {fileID: 771575417923360822, guid: ea906834639fa3f4ba65c95db6181d6b,
type: 3}
diff --git a/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/AdditiveSceneToggleHandler.cs b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/AdditiveSceneToggleHandler.cs
index b1e24eb859..ef13b2dc9f 100644
--- a/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/AdditiveSceneToggleHandler.cs
+++ b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/AdditiveSceneToggleHandler.cs
@@ -1,4 +1,5 @@
using System.Collections;
+using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
@@ -100,7 +101,7 @@ private void SceneManager_OnSceneEvent(SceneEvent sceneEvent)
}
else if (sceneEvent.SceneEventType == SceneEventData.SceneEventTypes.C2S_UnloadComplete)
{
- if (sceneEvent.ClientId == NetworkManager.Singleton.ServerClientId && !m_SceneLoaded.isLoaded)
+ if (sceneEvent.ClientId == NetworkManager.Singleton.ServerClientId && !m_SceneLoaded.isLoaded )
{
m_SceneLoaded = new Scene();
m_WaitForSceneLoadOrUnload = false;
@@ -126,19 +127,22 @@ public void OnToggle()
if (m_ToggleObject)
{
m_ToggleObject.enabled = false;
- StartCoroutine(SceneEventCoroutine(m_ToggleObject.isOn));
+ ToggleSceneManager.AddNewToggleHandler(this);
}
}
}
+
private bool m_WaitForSceneLoadOrUnload;
- private IEnumerator SceneEventCoroutine(bool isLoading)
+ public IEnumerator SceneEventCoroutine()
{
+ var isLoading = m_ToggleObject.isOn;
var sceneEventProgressStatus = SceneEventProgressStatus.None;
var continueCheck = true;
+
NetworkManager.Singleton.SceneManager.OnSceneEvent += SceneManager_OnSceneEvent;
- while (continueCheck && sceneEventProgressStatus != SceneEventProgressStatus.Started)
+ while (continueCheck && sceneEventProgressStatus != SceneEventProgressStatus.Started && sceneEventProgressStatus != SceneEventProgressStatus.SceneFailedVerification)
{
if (isLoading)
{
@@ -148,31 +152,31 @@ private IEnumerator SceneEventCoroutine(bool isLoading)
{
sceneEventProgressStatus = NetworkManager.Singleton.SceneManager.UnloadScene(m_SceneLoaded);
}
- if (sceneEventProgressStatus == SceneEventProgressStatus.SceneEventInProgress)
- {
- yield return new WaitForSeconds(0.25f);
- }
- else
+
+ switch (sceneEventProgressStatus)
{
- switch (sceneEventProgressStatus)
+ case SceneEventProgressStatus.SceneEventInProgress:
{
- case SceneEventProgressStatus.Started:
- {
- continueCheck = false;
- break;
- }
- case SceneEventProgressStatus.InternalNetcodeError:
- case SceneEventProgressStatus.InvalidSceneName:
- case SceneEventProgressStatus.SceneNotLoaded:
- {
- continueCheck = false;
- break;
- }
+ yield return new WaitForSeconds(0.25f);
+ break;
}
+ case SceneEventProgressStatus.Started:
+ {
+ continueCheck = false;
+ break;
+ }
+ case SceneEventProgressStatus.InternalNetcodeError:
+ case SceneEventProgressStatus.InvalidSceneName:
+ case SceneEventProgressStatus.SceneNotLoaded:
+ {
+ Debug.Log($"Scene Event Error: {sceneEventProgressStatus}");
+ continueCheck = false;
+ break;
+ }
}
}
m_WaitForSceneLoadOrUnload = true;
- var timeOutAfter = Time.realtimeSinceStartup + 10.0f;
+ var timeOutAfter = Time.realtimeSinceStartup + 5.0f;
while (m_WaitForSceneLoadOrUnload)
{
if (timeOutAfter < Time.realtimeSinceStartup)
@@ -183,11 +187,46 @@ private IEnumerator SceneEventCoroutine(bool isLoading)
yield return new WaitForSeconds(0.5f);
}
-
NetworkManager.Singleton.SceneManager.OnSceneEvent -= SceneManager_OnSceneEvent;
m_ToggleObject.isOn = isLoading;
m_ToggleObject.enabled = true;
+ ToggleSceneManager.CurrentQueueItem = null;
yield return null;
}
}
+
+
+ public static class ToggleSceneManager
+ {
+
+ private static Queue s_QueueUpForLoadUnload = new Queue();
+ public static AdditiveSceneToggleHandler CurrentQueueItem;
+ static private IEnumerator GlobalQueueToggleRoutine()
+ {
+ while (s_QueueUpForLoadUnload.Count > 0)
+ {
+ CurrentQueueItem = s_QueueUpForLoadUnload.Dequeue();
+ CurrentQueueItem.StartCoroutine(CurrentQueueItem.SceneEventCoroutine());
+ while (CurrentQueueItem != null)
+ {
+ yield return new WaitForSeconds(0.25f);
+ }
+ }
+ yield return null;
+ }
+
+
+ public static void AddNewToggleHandler(AdditiveSceneToggleHandler handler)
+ {
+ if (s_QueueUpForLoadUnload.Count == 0 && CurrentQueueItem == null)
+ {
+ s_QueueUpForLoadUnload.Enqueue(handler);
+ NetworkManager.Singleton.StartCoroutine(GlobalQueueToggleRoutine());
+ }
+ else
+ {
+ s_QueueUpForLoadUnload.Enqueue(handler);
+ }
+ }
+ }
}
diff --git a/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/SceneEventNotificationQueue.cs b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/SceneEventNotificationQueue.cs
index 6e36aa912f..f4e9838a04 100644
--- a/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/SceneEventNotificationQueue.cs
+++ b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/SceneEventNotificationQueue.cs
@@ -38,6 +38,25 @@ private void Start()
m_NetworkManager = gameObject.GetComponent();
}
+ private void DeregisterFromOnSceneEvent()
+ {
+ if (m_IsInitialized && m_NetworkManager != null && m_NetworkManager.SceneManager != null)
+ {
+ m_IsInitialized = false;
+ m_NetworkManager.SceneManager.OnSceneEvent -= OnSceneEvent;
+ }
+ }
+
+ private void OnApplicationQuit()
+ {
+ DeregisterFromOnSceneEvent();
+ }
+
+ private void OnDisable()
+ {
+ DeregisterFromOnSceneEvent();
+ }
+
///
/// Invoked on all local scene event notifications
///
@@ -97,11 +116,6 @@ private void Update()
m_SceneEvents.Dequeue();
}
}
- else if (m_IsInitialized)
- {
- m_IsInitialized = false;
- m_NetworkManager.SceneManager.OnSceneEvent -= OnSceneEvent;
- }
}
}
}
diff --git a/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/SceneTransitioningBase1.unity b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/SceneTransitioningBase1.unity
index 54c12bae18..9fdb0b1d3b 100644
--- a/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/SceneTransitioningBase1.unity
+++ b/testproject/Assets/Tests/Manual/SceneTransitioningAdditive/SceneTransitioningBase1.unity
@@ -5053,6 +5053,46 @@ PrefabInstance:
propertyPath: m_Name
value: ExitButton
objectReference: {fileID: 0}
+ - target: {fileID: 2848221157716786269, guid: 3200770c16e3b2b4ebe7f604154faac7,
+ type: 3}
+ propertyPath: m_Text
+ value: X
+ objectReference: {fileID: 0}
+ - target: {fileID: 2848221157716786269, guid: 3200770c16e3b2b4ebe7f604154faac7,
+ type: 3}
+ propertyPath: m_FontData.m_Font
+ value:
+ objectReference: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+ - target: {fileID: 2848221157716786269, guid: 3200770c16e3b2b4ebe7f604154faac7,
+ type: 3}
+ propertyPath: m_FontData.m_MaxSize
+ value: 40
+ objectReference: {fileID: 0}
+ - target: {fileID: 2848221157716786269, guid: 3200770c16e3b2b4ebe7f604154faac7,
+ type: 3}
+ propertyPath: m_FontData.m_MinSize
+ value: 10
+ objectReference: {fileID: 0}
+ - target: {fileID: 2848221157716786269, guid: 3200770c16e3b2b4ebe7f604154faac7,
+ type: 3}
+ propertyPath: m_FontData.m_FontSize
+ value: 14
+ objectReference: {fileID: 0}
+ - target: {fileID: 2848221157716786269, guid: 3200770c16e3b2b4ebe7f604154faac7,
+ type: 3}
+ propertyPath: m_FontData.m_RichText
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 2848221157716786269, guid: 3200770c16e3b2b4ebe7f604154faac7,
+ type: 3}
+ propertyPath: m_FontData.m_Alignment
+ value: 4
+ objectReference: {fileID: 0}
+ - target: {fileID: 2848221157716786269, guid: 3200770c16e3b2b4ebe7f604154faac7,
+ type: 3}
+ propertyPath: m_FontData.m_LineSpacing
+ value: 1
+ objectReference: {fileID: 0}
- target: {fileID: 5266522511616468950, guid: 3200770c16e3b2b4ebe7f604154faac7,
type: 3}
propertyPath: m_SceneMenuToLoad
diff --git a/testproject/Assets/Tests/Manual/Scripts/IndependentMover.cs.meta b/testproject/Assets/Tests/Manual/Scripts/IndependentMover.cs.meta
index 37294f1a0e..1e4e5b2879 100644
--- a/testproject/Assets/Tests/Manual/Scripts/IndependentMover.cs.meta
+++ b/testproject/Assets/Tests/Manual/Scripts/IndependentMover.cs.meta
@@ -1,5 +1,9 @@
fileFormatVersion: 2
+<<<<<<< HEAD:com.unity.netcode.gameobjects/Runtime/SceneManagement/ScenesInBuild.cs.meta
+guid: c4152da5a2f4e7746aecdcd815f6616b
+=======
guid: c552ef0ccf6ff8148a9c9606e7d3fc15
+>>>>>>> test/AdditiveSceneLoading:testproject/Assets/Tests/Manual/Scripts/IndependentMover.cs.meta
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs
index ec09ba7f6b..f4334eb4c4 100644
--- a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs
+++ b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPool.cs
@@ -7,7 +7,7 @@
namespace TestProject.ManualTests
{
- public class NetworkPrefabPool : NetworkBehaviour
+ public class NetworkPrefabPool : NetworkBehaviour, INetworkPrefabInstanceHandler
{
[Header("General Settings")]
public bool AutoSpawnEnable = true;
@@ -42,8 +42,6 @@ public class NetworkPrefabPool : NetworkBehaviour
private GameObject m_ObjectToSpawn;
private List m_ObjectPool;
- private MyCustomPrefabSpawnHandler m_MyCustomPrefabSpawnHandler;
-
///
/// Called when enabled, if already connected we register any custom prefab spawn handler here
///
@@ -55,24 +53,37 @@ private void OnEnable()
}
}
+ private bool m_IsQuitting;
+ private void OnApplicationQuit()
+ {
+ m_IsQuitting = true;
+ }
+
+ private void OnDisable()
+ {
+ if (!m_IsQuitting)
+ {
+ DeregisterCustomPrefabHandler();
+ }
+ }
+
///
/// Handles registering the custom prefab handler
///
private void RegisterCustomPrefabHandler()
{
// Register the custom spawn handler?
- if (m_MyCustomPrefabSpawnHandler == null && EnableHandler)
+ if (EnableHandler)
{
if (NetworkManager && NetworkManager.PrefabHandler != null)
{
- m_MyCustomPrefabSpawnHandler = new MyCustomPrefabSpawnHandler(this);
if (RegisterUsingNetworkObject)
{
- NetworkManager.PrefabHandler.AddHandler(ServerObjectToPool.GetComponent(), m_MyCustomPrefabSpawnHandler);
+ NetworkManager.PrefabHandler.AddHandler(ServerObjectToPool.GetComponent(), this);
}
else
{
- NetworkManager.PrefabHandler.AddHandler(ServerObjectToPool, m_MyCustomPrefabSpawnHandler);
+ NetworkManager.PrefabHandler.AddHandler(ServerObjectToPool, this);
}
}
else if (!IsServer)
@@ -82,15 +93,10 @@ private void RegisterCustomPrefabHandler()
}
}
- private void OnDisable()
- {
- OnUnloadScene();
- }
-
private void DeregisterCustomPrefabHandler()
{
// Register the custom spawn handler?
- if (EnableHandler && NetworkManager && NetworkManager.PrefabHandler != null && m_MyCustomPrefabSpawnHandler != null)
+ if (EnableHandler && NetworkManager && NetworkManager.PrefabHandler != null)
{
NetworkManager.PrefabHandler.RemoveHandler(ServerObjectToPool);
if (IsClient && m_ObjectToSpawn != null)
@@ -132,12 +138,18 @@ private void OnUnloadScene()
DeregisterCustomPrefabHandler();
CleanNetworkObjects();
+
+ if (NetworkManager != null && NetworkManager.SceneManager != null)
+ {
+ NetworkManager.SceneManager.OnSceneEvent -= OnSceneEvent;
+ }
}
}
public override void OnNetworkDespawn()
{
+ DeregisterCustomPrefabHandler();
if (NetworkManager != null)
{
NetworkManager.SceneManager.OnSceneEvent -= OnSceneEvent;
@@ -392,18 +404,10 @@ private IEnumerator SpawnObjects()
}
}
}
- }
-
- ///
- /// The custom prefab handler that returns an object from the prefab pool
- ///
- public class MyCustomPrefabSpawnHandler : INetworkPrefabInstanceHandler
- {
- private NetworkPrefabPool m_PrefabPool;
public NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation)
{
- var obj = m_PrefabPool.GetObject();
+ var obj = GetObject();
if (obj != null)
{
obj.transform.position = position;
@@ -421,13 +425,8 @@ public void Destroy(NetworkObject networkObject)
}
else
{
- Object.Destroy(networkObject.gameObject);
+ Destroy(networkObject.gameObject);
}
}
-
- public MyCustomPrefabSpawnHandler(NetworkPrefabPool objectPool)
- {
- m_PrefabPool = objectPool;
- }
}
}
diff --git a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPoolAdditive.cs b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPoolAdditive.cs
index b4c0c2f515..0fd3cc8f5f 100644
--- a/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPoolAdditive.cs
+++ b/testproject/Assets/Tests/Manual/Scripts/NetworkPrefabPoolAdditive.cs
@@ -6,7 +6,7 @@
namespace TestProject.ManualTests
{
- public class NetworkPrefabPoolAdditive : NetworkBehaviour
+ public class NetworkPrefabPoolAdditive : NetworkBehaviour, INetworkPrefabInstanceHandler
{
[Header("General Settings")]
public bool RandomMovement = true;
@@ -43,26 +43,23 @@ public class NetworkPrefabPoolAdditive : NetworkBehaviour
private GameObject m_ObjectToSpawn;
private List m_ObjectPool;
- private MyAdditiveCustomPrefabSpawnHandler m_AdditiveCustomPrefabSpawnHandler;
-
///
/// Handles registering the custom prefab handler
///
private void RegisterCustomPrefabHandler()
{
// Register the custom spawn handler?
- if (m_AdditiveCustomPrefabSpawnHandler == null && EnableHandler)
+ if (EnableHandler)
{
if (NetworkManager && NetworkManager.PrefabHandler != null)
{
- m_AdditiveCustomPrefabSpawnHandler = new MyAdditiveCustomPrefabSpawnHandler(this);
if (RegisterUsingNetworkObject)
{
- NetworkManager.PrefabHandler.AddHandler(ServerObjectToPool.GetComponent(), m_AdditiveCustomPrefabSpawnHandler);
+ NetworkManager.PrefabHandler.AddHandler(ServerObjectToPool.GetComponent(), this);
}
else
{
- NetworkManager.PrefabHandler.AddHandler(ServerObjectToPool, m_AdditiveCustomPrefabSpawnHandler);
+ NetworkManager.PrefabHandler.AddHandler(ServerObjectToPool, this);
}
}
}
@@ -71,7 +68,7 @@ private void RegisterCustomPrefabHandler()
private void DeregisterCustomPrefabHandler()
{
// Register the custom spawn handler?
- if (EnableHandler && NetworkManager && NetworkManager.PrefabHandler != null && m_AdditiveCustomPrefabSpawnHandler != null)
+ if (EnableHandler && NetworkManager && NetworkManager.PrefabHandler != null)
{
NetworkManager.PrefabHandler.RemoveHandler(ServerObjectToPool);
if (IsClient && m_ObjectToSpawn != null)
@@ -108,7 +105,6 @@ private void Start()
}
-
///
/// For additive scenes, we only clear out our pooled NetworkObjects if we are migrating them from the ActiveScene
/// to the scene where this NetworkPrefabPoolAdditive component is instantiated.
@@ -368,6 +364,12 @@ public void UpdateSpawnsPerSecond()
}
+
+ private void OnDisable()
+ {
+ StopCoroutine(SpawnObjects());
+ }
+
///
/// Coroutine to spawn boxes
///
@@ -425,18 +427,10 @@ private IEnumerator SpawnObjects()
}
}
}
- }
-
- ///
- /// The custom prefab handler that returns an object from the prefab pool
- ///
- public class MyAdditiveCustomPrefabSpawnHandler : INetworkPrefabInstanceHandler
- {
- private NetworkPrefabPoolAdditive m_PrefabPool;
public NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation)
{
- var obj = m_PrefabPool.GetObject();
+ var obj = GetObject();
if (obj != null)
{
obj.transform.position = position;
@@ -455,13 +449,8 @@ public void Destroy(NetworkObject networkObject)
}
else
{
- Object.Destroy(networkObject.gameObject);
+ Destroy(networkObject.gameObject);
}
}
-
- public MyAdditiveCustomPrefabSpawnHandler(NetworkPrefabPoolAdditive objectPool)
- {
- m_PrefabPool = objectPool;
- }
}
}
diff --git a/testproject/Assets/Tests/Manual/Scripts/PlayerMovementManager.cs b/testproject/Assets/Tests/Manual/Scripts/PlayerMovementManager.cs
index 554920a9ec..73a887c657 100644
--- a/testproject/Assets/Tests/Manual/Scripts/PlayerMovementManager.cs
+++ b/testproject/Assets/Tests/Manual/Scripts/PlayerMovementManager.cs
@@ -19,7 +19,6 @@ public class PlayerMovementManager : NetworkBehaviour
private void Start()
{
m_RandomMovement = GetComponent();
-
}
public override void OnNetworkSpawn()
@@ -33,19 +32,22 @@ public override void OnNetworkSpawn()
private void Update()
{
- if (NetworkObject.IsOwner && Input.GetKeyDown(KeyCode.Space))
+ if (NetworkObject != null)
{
- if (m_RandomMovement)
+ if (IsOwner && Input.GetKeyDown(KeyCode.Space))
{
- m_RandomMovement.enabled = !m_RandomMovement.enabled;
+ if (m_RandomMovement)
+ {
+ m_RandomMovement.enabled = !m_RandomMovement.enabled;
+ }
}
- }
- if (NetworkObject && NetworkObject.NetworkManager && NetworkObject.NetworkManager.IsListening)
- {
- if (m_RandomMovement.enabled)
+ if (NetworkObject != null && NetworkObject.NetworkManager != null && NetworkObject.NetworkManager.IsListening)
{
- m_RandomMovement.Move(MoveSpeed);
+ if (m_RandomMovement.enabled)
+ {
+ m_RandomMovement.Move(MoveSpeed);
+ }
}
}
}
diff --git a/testproject/Assets/Tests/Manual/Scripts/RandomMovement.cs b/testproject/Assets/Tests/Manual/Scripts/RandomMovement.cs
index 5d1e1f1422..7134251686 100644
--- a/testproject/Assets/Tests/Manual/Scripts/RandomMovement.cs
+++ b/testproject/Assets/Tests/Manual/Scripts/RandomMovement.cs
@@ -46,7 +46,11 @@ public void Move(int speed)
else if (!IsServer && IsOwner)
{
// Client must sent Rpc
- MovePlayerServerRpc(m_Direction * speed);
+ MovePlayerServerRpc(m_Direction * speed*1.05f);
+ }
+ else if (IsServer && !IsOwner)
+ {
+ m_MoveTowardsPosition = Vector3.Lerp(m_MoveTowardsPosition, Vector3.zero, 0.01f);
}
}
diff --git a/testproject/Assets/Tests/Runtime/FixedUpdateMessagesAreOnlyProcessedOnceTest.cs b/testproject/Assets/Tests/Runtime/FixedUpdateMessagesAreOnlyProcessedOnceTest.cs
index a543cfb3c0..edab517e84 100644
--- a/testproject/Assets/Tests/Runtime/FixedUpdateMessagesAreOnlyProcessedOnceTest.cs
+++ b/testproject/Assets/Tests/Runtime/FixedUpdateMessagesAreOnlyProcessedOnceTest.cs
@@ -51,8 +51,8 @@ public IEnumerator TestFixedUpdateMessagesAreOnlyProcessedOnce()
var networkObject = m_Prefab.AddComponent();
// Make it a prefab
- MultiInstanceHelpers.MakeNetworkObjectTestPrefab(networkObject, 1);
- var handler = new SpawnRpcDespawnInstanceHandler(1);
+ MultiInstanceHelpers.MakeNetworkObjectTestPrefab(networkObject);
+ var handler = new SpawnRpcDespawnInstanceHandler(networkObject.GlobalObjectIdHash);
foreach (var client in clients)
{
client.PrefabHandler.AddHandler(networkObject, handler);
diff --git a/testproject/Assets/Tests/Runtime/NetworkSceneManagerTests.cs b/testproject/Assets/Tests/Runtime/NetworkSceneManagerTests.cs
index 508d5a341b..495d6b29ab 100644
--- a/testproject/Assets/Tests/Runtime/NetworkSceneManagerTests.cs
+++ b/testproject/Assets/Tests/Runtime/NetworkSceneManagerTests.cs
@@ -139,22 +139,20 @@ public IEnumerator SceneLoadingAndNotifications()
///
/// Initializes the m_ShouldWaitList
///
- private void InitializeSceneTestInfo()
+ private void InitializeSceneTestInfo(bool enableSceneVerification = false)
{
m_ShouldWaitList.Add(new SceneTestInfo() { ClientId = m_ServerNetworkManager.ServerClientId, ShouldWait = false });
- if (!m_ServerNetworkManager.NetworkConfig.RegisteredScenes.Contains(m_CurrentSceneName))
+ if (enableSceneVerification)
{
- m_ServerNetworkManager.NetworkConfig.AllowRuntimeSceneChanges = true;
- m_ServerNetworkManager.SceneManager.AddRuntimeSceneName(m_CurrentSceneName, (uint)(m_ServerNetworkManager.NetworkConfig.RegisteredScenes.Count + 1));
+ m_ServerNetworkManager.SceneManager.VerifySceneBeforeLoading = ServerVerifySceneBeforeLoading;
}
foreach (var manager in m_ClientNetworkManagers)
{
m_ShouldWaitList.Add(new SceneTestInfo() { ClientId = manager.LocalClientId, ShouldWait = false });
- if (!manager.NetworkConfig.RegisteredScenes.Contains(m_CurrentSceneName))
+ if (enableSceneVerification)
{
- manager.NetworkConfig.AllowRuntimeSceneChanges = true;
- manager.SceneManager.AddRuntimeSceneName(m_CurrentSceneName, (uint)(manager.NetworkConfig.RegisteredScenes.Count + 1));
+ manager.SceneManager.VerifySceneBeforeLoading = ClientVerifySceneBeforeLoading;
}
}
}
@@ -182,7 +180,15 @@ private void ResetWait()
private bool ShouldWait()
{
m_TimedOut = m_TimeOutMarker < Time.realtimeSinceStartup;
- return (m_ShouldWaitList.Select(c => c).Where(c => c.ProcessedEvent != true && c.ShouldWait == true).Count() > 0) && !m_TimedOut;
+ if (!m_IsTestingVerifyScene)
+ {
+ return (m_ShouldWaitList.Select(c => c).Where(c => c.ProcessedEvent != true && c.ShouldWait == true).Count() > 0) && !m_TimedOut;
+ }
+ else
+ {
+ return (m_ShouldWaitList.Select(c => c).Where(c => c.ProcessedEvent != true && c.ShouldWait == true &&
+ c.ClientId == m_ServerNetworkManager.ServerClientId).Count() > 0) && !m_TimedOut && m_ClientsThatFailedVerification != NbClients;
+ }
}
///
@@ -300,5 +306,107 @@ private void SceneManager_OnSceneEvent(SceneEvent sceneEvent)
}
}
}
+
+ private bool m_IsTestingVerifyScene;
+ private bool m_ServerVerifyScene;
+ private bool m_ClientVerifyScene;
+ private int m_ExpectedSceneIndex;
+ private int m_ClientsThatFailedVerification;
+ private string m_ExpectedSceneName;
+ private LoadSceneMode m_ExpectedLoadMode;
+
+ private bool ServerVerifySceneBeforeLoading(int sceneIndex, string sceneName, LoadSceneMode loadSceneMode)
+ {
+ Assert.IsTrue(m_ExpectedSceneIndex == sceneIndex);
+ Assert.IsTrue(m_ExpectedSceneName == sceneName);
+ Assert.IsTrue(m_ExpectedLoadMode == loadSceneMode);
+
+ return m_ServerVerifyScene;
+ }
+
+ private bool ClientVerifySceneBeforeLoading(int sceneIndex, string sceneName, LoadSceneMode loadSceneMode)
+ {
+ Assert.IsTrue(m_ExpectedSceneIndex == sceneIndex);
+ Assert.IsTrue(m_ExpectedSceneName == sceneName);
+ Assert.IsTrue(m_ExpectedLoadMode == loadSceneMode);
+ if (!m_ClientVerifyScene)
+ {
+ m_ClientsThatFailedVerification++;
+ }
+ return m_ClientVerifyScene;
+ }
+
+ ///
+ /// Unit test to verify that user defined scene verification works on both the client and
+ /// the server side.
+ ///
+ ///
+ [UnityTest]
+ public IEnumerator SceneVerifyBeforeLoadTest()
+ {
+ m_ServerNetworkManager.SceneManager.OnSceneEvent += SceneManager_OnSceneEvent;
+ m_CurrentSceneName = "AdditiveScene1";
+
+ // Now prepare for the loading and unloading additive scene testing
+ InitializeSceneTestInfo(true);
+
+ // Test VerifySceneBeforeLoading with both server and client set to true
+ ResetWait();
+ m_ServerVerifyScene = m_ClientVerifyScene = true;
+ m_ExpectedSceneIndex = (int)m_ServerNetworkManager.SceneManager.GetBuildIndexFromSceneName(m_CurrentSceneName);
+ m_ExpectedSceneName = m_CurrentSceneName;
+ m_ExpectedLoadMode = LoadSceneMode.Additive;
+ var result = m_ServerNetworkManager.SceneManager.LoadScene(m_CurrentSceneName, LoadSceneMode.Additive);
+ Assert.True(result == SceneEventProgressStatus.Started);
+
+ // Wait for all clients to load the scene
+ yield return new WaitWhile(ShouldWait);
+ Assert.IsFalse(m_TimedOut);
+
+ // Unload the scene
+ ResetWait();
+ result = m_ServerNetworkManager.SceneManager.UnloadScene(m_CurrentScene);
+ Assert.True(result == SceneEventProgressStatus.Started);
+
+ yield return new WaitWhile(ShouldWait);
+ Assert.IsFalse(m_TimedOut);
+
+ // Test VerifySceneBeforeLoading with m_ServerVerifyScene set to false
+ // Server will notify it failed scene verification and no client should load
+ ResetWait();
+ m_ServerVerifyScene = false;
+ result = m_ServerNetworkManager.SceneManager.LoadScene(m_CurrentSceneName, LoadSceneMode.Additive);
+ Assert.True(result == SceneEventProgressStatus.SceneFailedVerification);
+
+ // Test VerifySceneBeforeLoading with m_ServerVerifyScene set to true and m_ClientVerifyScene set to false
+ // Server should load and clients will notify they failed scene verification
+ ResetWait();
+ m_CurrentSceneName = "AdditiveScene2";
+ m_ExpectedSceneName = m_CurrentSceneName;
+ m_ExpectedSceneIndex = (int)m_ServerNetworkManager.SceneManager.GetBuildIndexFromSceneName(m_CurrentSceneName);
+ m_ServerVerifyScene = true;
+ m_ClientVerifyScene = false;
+ m_IsTestingVerifyScene = true;
+ m_ClientsThatFailedVerification = 0;
+ result = m_ServerNetworkManager.SceneManager.LoadScene(m_CurrentSceneName, LoadSceneMode.Additive);
+ Assert.True(result == SceneEventProgressStatus.Started);
+
+ // Now wait for server to complete and all clients to fail
+ yield return new WaitWhile(ShouldWait);
+ Assert.IsFalse(m_TimedOut);
+
+ // Now unload the scene the server loaded from last test
+ ResetWait();
+ m_IsTestingVerifyScene = false;
+ result = m_ServerNetworkManager.SceneManager.UnloadScene(m_CurrentScene);
+ Assert.True(result == SceneEventProgressStatus.Started);
+
+ // Now wait for server to unload and clients will fake unload
+ yield return new WaitWhile(ShouldWait);
+ Assert.IsFalse(m_TimedOut);
+
+ yield break;
+ }
+
}
}
diff --git a/testproject/Assets/Tests/Runtime/NetworkSceneManagerTests.cs.meta b/testproject/Assets/Tests/Runtime/NetworkSceneManagerTests.cs.meta
index 7e4d9c6ae8..31c443308c 100644
--- a/testproject/Assets/Tests/Runtime/NetworkSceneManagerTests.cs.meta
+++ b/testproject/Assets/Tests/Runtime/NetworkSceneManagerTests.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: f7bf3513fa4b1c846af40172cdb7c9af
+guid: e536693df1c81e94388cab0f062c2352
MonoImporter:
externalObjects: {}
serializedVersion: 2