diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md
index 06ebf2c108..cc261b6aec 100644
--- a/com.unity.netcode.gameobjects/CHANGELOG.md
+++ b/com.unity.netcode.gameobjects/CHANGELOG.md
@@ -18,6 +18,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
### Deprecated
+- Deprecated the nullable boolean `NetworkObject.IsSceneObject` and introduced `NetworkObject.InScenePlaced`. (#4000)
- Deprecated a number of methods that were no longer valid or being used. (#3987)
### Removed
diff --git a/com.unity.netcode.gameobjects/Editor/InScenePlacedProcessor.cs b/com.unity.netcode.gameobjects/Editor/InScenePlacedProcessor.cs
new file mode 100644
index 0000000000..423ff4a65c
--- /dev/null
+++ b/com.unity.netcode.gameobjects/Editor/InScenePlacedProcessor.cs
@@ -0,0 +1,45 @@
+using UnityEditor;
+using UnityEditor.Build;
+using UnityEditor.Build.Reporting;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+
+namespace Unity.Netcode.Editor
+{
+ ///
+ /// A that sets the property to true for all s in the scene.
+ /// Ensures that InScenePlaced is always true for all objects in the scene.
+ ///
+ ///
+ /// This will always run as the game enters the scene,
+ ///
+ internal class SetInScenePlaced : IProcessSceneWithReport
+ {
+ public int callbackOrder => 0;
+ public void OnProcessScene(Scene scene, BuildReport report)
+ {
+ foreach (var networkObject in FindObjects.FromSceneByType(scene, true))
+ {
+ networkObject.InScenePlaced = true;
+ }
+ }
+ }
+
+ ///
+ /// An that sets the property to false for all s in prefabs.
+ /// Ensures that InScenePlaced is always false for all prefab objects.
+ /// This is important because when a prefab is instantiated in the scene, it should be treated as a dynamically spawned object.
+ ///
+ internal class InScenePlacedPrefabBuilder : AssetPostprocessor
+ {
+ public void OnPostprocessPrefab(GameObject root)
+ {
+ var networkObjects = root.GetComponentsInChildren(true);
+ foreach (var networkObject in networkObjects)
+ {
+ networkObject.InScenePlaced = false;
+ }
+ }
+ }
+}
diff --git a/com.unity.netcode.gameobjects/Editor/InScenePlacedProcessor.cs.meta b/com.unity.netcode.gameobjects/Editor/InScenePlacedProcessor.cs.meta
new file mode 100644
index 0000000000..784aa38575
--- /dev/null
+++ b/com.unity.netcode.gameobjects/Editor/InScenePlacedProcessor.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: cda0fb70bdcd545a7983ca78f516bcff
\ No newline at end of file
diff --git a/com.unity.netcode.gameobjects/Editor/NetworkObjectEditor.cs b/com.unity.netcode.gameobjects/Editor/NetworkObjectEditor.cs
index 04e0d1f698..0335896784 100644
--- a/com.unity.netcode.gameobjects/Editor/NetworkObjectEditor.cs
+++ b/com.unity.netcode.gameobjects/Editor/NetworkObjectEditor.cs
@@ -67,14 +67,10 @@ public override void OnInspectorGUI()
EditorGUILayout.Toggle(nameof(NetworkObject.IsOwner), m_NetworkObject.IsOwner);
EditorGUILayout.Toggle(nameof(NetworkObject.IsOwnedByServer), m_NetworkObject.IsOwnedByServer);
EditorGUILayout.Toggle(nameof(NetworkObject.IsPlayerObject), m_NetworkObject.IsPlayerObject);
- if (m_NetworkObject.IsSceneObject.HasValue)
- {
- EditorGUILayout.Toggle(nameof(NetworkObject.IsSceneObject), m_NetworkObject.IsSceneObject.Value);
- }
- else
- {
- EditorGUILayout.TextField(nameof(NetworkObject.IsSceneObject), "null");
- }
+#pragma warning disable CS0618 // Type or member is obsolete
+ // TODO-3.x: Update name in 3.x branch
+ EditorGUILayout.Toggle(nameof(NetworkObject.IsSceneObject), m_NetworkObject.InScenePlaced);
+#pragma warning restore CS0618 // Type or member is obsolete
EditorGUILayout.Toggle(nameof(NetworkObject.DestroyWithScene), m_NetworkObject.DestroyWithScene);
EditorGUILayout.TextField(nameof(NetworkObject.NetworkManager), m_NetworkObject.NetworkManager == null ? "null" : m_NetworkObject.NetworkManager.gameObject.name);
GUI.enabled = guiEnabled;
diff --git a/com.unity.netcode.gameobjects/Runtime/Components/NetworkTransform.cs b/com.unity.netcode.gameobjects/Runtime/Components/NetworkTransform.cs
index 3ca9093b34..0259138b46 100644
--- a/com.unity.netcode.gameobjects/Runtime/Components/NetworkTransform.cs
+++ b/com.unity.netcode.gameobjects/Runtime/Components/NetworkTransform.cs
@@ -2231,7 +2231,7 @@ private bool CheckForStateChange(ref NetworkTransformState networkState, bool is
// In-scene placed NetworkObjects parented under a GameObject with no
// NetworkObject preserve their lossyScale when synchronizing.
- if (parentNetworkObject == null && NetworkObject.IsSceneObject != false)
+ if (parentNetworkObject == null && NetworkObject.InScenePlaced)
{
hasParentNetworkObject = true;
}
diff --git a/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs b/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs
index aaeb67f4db..1da9ddb3bb 100644
--- a/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs
+++ b/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs
@@ -1184,7 +1184,11 @@ internal void CreateAndSpawnPlayer(ulong ownerId)
return;
}
- networkObject.IsSceneObject = false;
+#pragma warning disable CS0618 // Type or member is obsolete
+ // Obsolete with warning means we need the underlying behaviour to keep existing
+ // TODO: remove in the 3.x branch
+ networkObject.SetSceneObjectStatus(false);
+#pragma warning restore CS0618 // Type or member is obsolete
networkObject.NetworkManagerOwner = NetworkManager;
networkObject.SpawnAsPlayerObject(ownerId, networkObject.DestroyWithScene);
}
diff --git a/com.unity.netcode.gameobjects/Runtime/Core/FindObjects.cs b/com.unity.netcode.gameobjects/Runtime/Core/FindObjects.cs
index a283cabe52..59329f8a81 100644
--- a/com.unity.netcode.gameobjects/Runtime/Core/FindObjects.cs
+++ b/com.unity.netcode.gameobjects/Runtime/Core/FindObjects.cs
@@ -1,7 +1,8 @@
-#if NGO_FINDOBJECTS_NOSORTING
using System;
-#endif
+using System.Collections;
+using System.Collections.Generic;
using System.Runtime.CompilerServices;
+using UnityEngine.SceneManagement;
using Object = UnityEngine.Object;
namespace Unity.Netcode
@@ -11,14 +12,14 @@ namespace Unity.Netcode
///
///
/// It is intentional that we do not include the UnityEngine namespace in order to avoid
- /// over-complicatd define wrapping between versions that do or don't support FindObjectsSortMode.
+ /// over-complicated define wrapping between versions that do or don't support FindObjectsSortMode.
///
internal static class FindObjects
{
///
/// Replaces to have one place where these changes are applied.
///
- ///
+ /// The type of object to find. Must be a reference type derived from
/// When true, inactive objects will be included.
/// When true, the array returned will be sorted by identifier.
/// Results as an of type T
@@ -39,5 +40,90 @@ public static T[] ByType(bool includeInactive = false, bool orderByIdentifier
#endif
return results;
}
+
+ ///
+ /// Returns an enumerator that enumerates over all the components of a given type in a scene.
+ ///
+ /// The scene to use for searching
+ /// When true, inactive objects will be included.
+ /// Type of to get from the scene
+ /// a generator that yields successive NetworkObjects in the current scene
+ public static IEnumerable FromSceneByType(Scene scene, bool includeInactive) where T : UnityEngine.Component
+ {
+ return new ObjectsInSceneEnumerator(scene, includeInactive);
+ }
+
+ ///
+ /// An Enumerator that enumerates over each component of type in the given scene.
+ ///
+ /// Type of to get from the scene
+ private struct ObjectsInSceneEnumerator : IEnumerable, IEnumerator where T : UnityEngine.Component
+ {
+ private readonly UnityEngine.GameObject[] m_RootObjects;
+ private int m_RootIndex;
+ private T[] m_CurrentChildObjects;
+ private int m_CurrentChildIndex;
+
+ private readonly bool m_IncludeInactive;
+
+ internal ObjectsInSceneEnumerator(Scene scene, bool includeInactive)
+ {
+ m_IncludeInactive = includeInactive;
+
+ m_RootObjects = scene.GetRootGameObjects();
+ m_RootIndex = 0;
+ m_CurrentChildObjects = null;
+ m_CurrentChildIndex = 0;
+ Current = null;
+ }
+
+ public void Dispose() { }
+
+ public bool MoveNext()
+ {
+ while (m_CurrentChildObjects == null && m_RootIndex < m_RootObjects.Length)
+ {
+ m_CurrentChildObjects = m_RootObjects[m_RootIndex].GetComponentsInChildren(m_IncludeInactive);
+ m_RootIndex++;
+
+ if (m_CurrentChildObjects.Length == 0)
+ {
+ m_CurrentChildObjects = null;
+ }
+ }
+
+ if (m_CurrentChildObjects != null && m_CurrentChildIndex < m_CurrentChildObjects.Length)
+ {
+ Current = m_CurrentChildObjects[m_CurrentChildIndex];
+ m_CurrentChildIndex++;
+
+ if (m_CurrentChildIndex >= m_CurrentChildObjects.Length)
+ {
+ m_CurrentChildIndex = 0;
+ m_CurrentChildObjects = null;
+ }
+ return true;
+ }
+
+ Current = null;
+ return false;
+ }
+
+ public void Reset()
+ {
+ m_RootIndex = 0;
+ m_CurrentChildObjects = null;
+ m_CurrentChildIndex = 0;
+ Current = null;
+ }
+
+ object IEnumerator.Current => Current;
+
+ public T Current { get; private set; }
+
+ public IEnumerator GetEnumerator() => this;
+
+ IEnumerator IEnumerable.GetEnumerator() => this;
+ }
}
}
diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs
index 55fdd6dbf8..2e7e3a7572 100644
--- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs
+++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs
@@ -1644,7 +1644,7 @@ internal void ShutdownInternal()
// place (i.e. sending any last state updates or the like).
SpawnManager?.DespawnAndDestroyNetworkObjects();
- SpawnManager?.ServerResetShudownStateForSceneObjects();
+ SpawnManager?.ServerResetShutdownStateForSceneObjects();
////
RpcTarget?.Dispose();
diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs
index d2f5aa5869..173d7fba8d 100644
--- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs
+++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs
@@ -291,7 +291,7 @@ internal void OnValidate()
if (GlobalObjectIdHash != oldValue)
{
// Check if this is an in-scnee placed NetworkObject (Special Case for In-Scene Placed).
- if (IsSceneObject.HasValue && IsSceneObject.Value)
+ if (InScenePlaced)
{
// Sanity check to make sure this is a scene placed object.
if (globalId.identifierType != k_SceneObjectType)
@@ -340,7 +340,12 @@ private void CheckForInScenePlaced()
EditorUtility.SetDirty(this);
}
}
- IsSceneObject = true;
+
+#pragma warning disable CS0618 // Type or member is obsolete
+ // Obsolete with warning means we need the underlying behaviour to keep existing
+ // TODO-3.x: remove in the 3.x branch
+ SetSceneObjectStatus(true);
+#pragma warning restore CS0618 // Type or member is obsolete
// Default scene migration synchronization to false for in-scene placed NetworkObjects
SceneMigrationSynchronization = false;
@@ -1225,15 +1230,24 @@ private bool InternalHasAuthority()
public bool IsSpawned { get; internal set; }
///
- /// Gets if the object is a SceneObject, null if it's not yet spawned but is a scene object.
+ /// Gets if the object is a SceneObject.
///
+ [Obsolete("Use InScenePlaced instead")]
public bool? IsSceneObject { get; internal set; }
- //DANGOEXP TODO: Determine if we want to keep this
+ ///
+ /// True if this object is placed in a scene; false otherwise.
+ ///
+ [field: HideInInspector]
+ [field: SerializeField]
+ public bool InScenePlaced { get; internal set; }
+
///
/// Sets whether this NetworkObject was instantiated as part of a scene
///
+ /// Only use this when using custom scene loading
/// When true, marks this as a scene-instantiated object; when false, marks it as runtime-instantiated
+ [Obsolete("SetSceneObjectStatus is now calculated during the build.")]
public void SetSceneObjectStatus(bool isSceneObject = false)
{
IsSceneObject = isSceneObject;
@@ -1457,7 +1471,7 @@ internal Scene SceneOrigin
///
internal NetworkSceneHandle GetSceneOriginHandle()
{
- if (SceneOriginHandle.IsEmpty() && IsSpawned && IsSceneObject != false)
+ if (SceneOriginHandle.IsEmpty() && IsSpawned && InScenePlaced)
{
if (NetworkManager.LogLevel <= LogLevel.Error)
{
@@ -1622,7 +1636,7 @@ public void NetworkHide(ulong clientId)
var message = new DestroyObjectMessage
{
NetworkObjectId = NetworkObjectId,
- DestroyGameObject = !IsSceneObject.Value,
+ DestroyGameObject = !InScenePlaced,
IsDistributedAuthority = NetworkManagerOwner.DistributedAuthorityMode,
IsTargetedDestroy = NetworkManagerOwner.DistributedAuthorityMode,
TargetClientId = clientId, // Just always populate this value whether we write it or not
@@ -1750,7 +1764,7 @@ private void OnDestroy()
var isStillValid = gameObject != null && gameObject.scene.IsValid() && gameObject.scene.isLoaded;
// If we're not the authority and everything is valid and dynamically spawned, then the destroy is not valid.
- if (!isAuthorityDestroy && IsSceneObject == false && isStillValid)
+ if (!isAuthorityDestroy && !InScenePlaced && isStillValid)
{
if (networkManager.LogLevel <= LogLevel.Error)
{
@@ -1849,7 +1863,7 @@ internal void SpawnInternal(bool destroyWithScene, ulong ownerClientId, bool pla
}
}
- if (!NetworkManagerOwner.SpawnManager.AuthorityLocalSpawn(this, NetworkManagerOwner.SpawnManager.GetNetworkObjectId(), IsSceneObject.HasValue && IsSceneObject.Value, playerObject, ownerClientId, destroyWithScene))
+ if (!NetworkManagerOwner.SpawnManager.AuthorityLocalSpawn(this, NetworkManagerOwner.SpawnManager.GetNetworkObjectId(), InScenePlaced, playerObject, ownerClientId, destroyWithScene))
{
if (NetworkManagerOwner.LogLevel <= LogLevel.Normal)
{
@@ -2528,8 +2542,7 @@ internal bool ApplyNetworkParenting(bool removeParent = false, bool ignoreNotSpa
// Handle the first in-scene placed NetworkObject parenting scenarios. Once the m_LatestParent
// has been set, this will not be entered into again (i.e. the later code will be invoked and
// users will get notifications when the parent changes).
- var isInScenePlaced = IsSceneObject.HasValue && IsSceneObject.Value;
- if (transform.parent != null && !removeParent && !m_LatestParent.HasValue && isInScenePlaced)
+ if (transform.parent != null && !removeParent && !m_LatestParent.HasValue && InScenePlaced)
{
var parentNetworkObject = transform.parent.GetComponent();
@@ -3271,7 +3284,7 @@ internal SerializedObject Serialize(ulong targetClientId = NetworkManager.Server
NetworkObjectId = NetworkObjectId,
OwnerClientId = OwnerClientId,
IsPlayerObject = IsPlayerObject,
- IsSceneObject = IsSceneObject ?? true,
+ IsSceneObject = InScenePlaced,
DestroyWithScene = DestroyWithScene,
DontDestroyWithOwner = DontDestroyWithOwner,
HasOwnershipFlags = NetworkManagerOwner.DistributedAuthorityMode,
@@ -3456,7 +3469,7 @@ internal void SubscribeToActiveSceneForSynch()
{
if (ActiveSceneSynchronization)
{
- if (IsSceneObject.HasValue && !IsSceneObject.Value)
+ if (!InScenePlaced)
{
// Just in case it is a recycled NetworkObject, unsubscribe first
SceneManager.activeSceneChanged -= CurrentlyActiveSceneChanged;
@@ -3473,7 +3486,7 @@ private void CurrentlyActiveSceneChanged(Scene current, Scene next)
{
// Early exit if the NetworkObject is not spawned, is an in-scene placed NetworkObject,
// or the NetworkManager is shutting down.
- if (!IsSpawned || IsSceneObject != false || NetworkManagerOwner.ShutdownInProgress)
+ if (!IsSpawned || NetworkManagerOwner.ShutdownInProgress || InScenePlaced)
{
return;
}
@@ -3483,7 +3496,7 @@ private void CurrentlyActiveSceneChanged(Scene current, Scene next)
{
// Only dynamically spawned NetworkObjects that are not already in the newly assigned active scene will migrate
// and update their scene handles
- if (IsSceneObject.HasValue && !IsSceneObject.Value && gameObject.scene != next && gameObject.transform.parent == null)
+ if (gameObject.scene != next && gameObject.transform.parent == null)
{
SceneManager.MoveGameObjectToScene(gameObject, next);
SceneChangedUpdate(next);
@@ -3571,7 +3584,7 @@ internal bool UpdateForSceneChanges()
// the NetworkManager is shutting down, the NetworkObject is not spawned, it is an in-scene placed
// NetworkObject, or the GameObject's current scene handle is the same as the SceneOriginHandle
if (!SceneMigrationSynchronization || !IsSpawned || NetworkManagerOwner.ShutdownInProgress ||
- !NetworkManagerOwner.NetworkConfig.EnableSceneManagement || IsSceneObject != false || !gameObject)
+ !NetworkManagerOwner.NetworkConfig.EnableSceneManagement || InScenePlaced || !gameObject)
{
// Stop checking for a scene migration
return false;
@@ -3606,7 +3619,7 @@ internal uint CheckForGlobalObjectIdHashOverride()
// If scene management is disabled and this is an in-scene placed NetworkObject then go ahead
// and send the InScenePlacedSourcePrefab's GlobalObjectIdHash value (i.e. what to dynamically spawn)
- if (!networkManager.NetworkConfig.EnableSceneManagement && IsSceneObject.Value && InScenePlacedSourceGlobalObjectIdHash != 0)
+ if (!networkManager.NetworkConfig.EnableSceneManagement && InScenePlaced && InScenePlacedSourceGlobalObjectIdHash != 0)
{
return InScenePlacedSourceGlobalObjectIdHash;
}
@@ -3614,7 +3627,7 @@ internal uint CheckForGlobalObjectIdHashOverride()
// If the PrefabGlobalObjectIdHash is a non-zero value and the GlobalObjectIdHash value is
// different from the PrefabGlobalObjectIdHash value, then the NetworkObject instance is
// an override for the original network prefab (i.e. PrefabGlobalObjectIdHash)
- if (!IsSceneObject.Value && GlobalObjectIdHash != PrefabGlobalObjectIdHash)
+ if (!InScenePlaced && GlobalObjectIdHash != PrefabGlobalObjectIdHash)
{
// If the PrefabGlobalObjectIdHash is already populated (i.e. InstantiateAndSpawn used), then return this
if (PrefabGlobalObjectIdHash != 0)
diff --git a/com.unity.netcode.gameobjects/Runtime/SceneManagement/DefaultSceneManagerHandler.cs b/com.unity.netcode.gameobjects/Runtime/SceneManagement/DefaultSceneManagerHandler.cs
index 5a11a01b4a..6e3954b294 100644
--- a/com.unity.netcode.gameobjects/Runtime/SceneManagement/DefaultSceneManagerHandler.cs
+++ b/com.unity.netcode.gameobjects/Runtime/SceneManagement/DefaultSceneManagerHandler.cs
@@ -311,7 +311,7 @@ public void MoveObjectsFromSceneToDontDestroyOnLoad(ref NetworkManager networkMa
if (!networkObject.DestroyWithScene && networkObject.gameObject.scene != networkManager.SceneManager.DontDestroyOnLoadScene)
{
// Only move dynamically spawned NetworkObjects with no parent as the children will follow
- if (networkObject.gameObject.transform.parent == null && networkObject.IsSceneObject != null && !networkObject.IsSceneObject.Value)
+ if (networkObject.gameObject.transform.parent == null && !networkObject.InScenePlaced)
{
UnityEngine.Object.DontDestroyOnLoad(networkObject.gameObject);
}
diff --git a/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneHandle.cs b/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneHandle.cs
index e544eb1f24..f57414bcc5 100644
--- a/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneHandle.cs
+++ b/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneHandle.cs
@@ -34,7 +34,6 @@ public void NetworkSerialize(BufferSerializer serializer) where T : IReade
else
{
var reader = serializer.GetFastBufferReader();
- // DANGO-TODO Rust needs to be updated to either handle this ulong or to remove the scene store.
#if SCENE_MANAGEMENT_SCENE_HANDLE_MUST_USE_ULONG
reader.ReadValueSafe(out ulong rawData);
m_Handle = SceneHandle.FromRawData(rawData);
@@ -87,6 +86,11 @@ internal NetworkSceneHandle(int handle, bool asMock)
public int GetRawData() => m_Handle;
#endif
+ public override string ToString()
+ {
+ return m_Handle.ToString();
+ }
+
#region Implicit conversions
#if SCENE_MANAGEMENT_SCENE_HANDLE_AVAILABLE
///
diff --git a/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs b/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs
index 2fbdf1fbe9..5cc5604e8d 100644
--- a/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs
+++ b/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs
@@ -2234,7 +2234,7 @@ private void SynchronizeNetworkObjectScene()
// This is only done for dynamically spawned NetworkObjects
// Theoretically, a server could have NetworkObjects in a server-side only scene, if the client doesn't have that scene loaded
// then skip it (it will reside in the currently active scene in this scenario on the client-side)
- if (networkObject.IsSceneObject.Value == false && ServerSceneHandleToClientSceneHandle.ContainsKey(networkObject.NetworkSceneHandle))
+ if (!networkObject.InScenePlaced && ServerSceneHandleToClientSceneHandle.ContainsKey(networkObject.NetworkSceneHandle))
{
networkObject.SceneOriginHandle = ServerSceneHandleToClientSceneHandle[networkObject.NetworkSceneHandle];
@@ -2709,7 +2709,7 @@ internal void MoveObjectsToDontDestroyOnLoad()
if (!networkObject.DestroyWithScene)
{
// Only move dynamically spawned NetworkObjects with no parent as the children will follow
- if (networkObject.gameObject.transform.parent == null && networkObject.IsSceneObject != null && !networkObject.IsSceneObject.Value)
+ if (networkObject.gameObject.transform.parent == null && !networkObject.InScenePlaced)
{
UnityEngine.Object.DontDestroyOnLoad(networkObject.gameObject);
// When temporarily migrating to the DDOL, adjust the network and origin scene handles so no messages are generated
@@ -2721,10 +2721,9 @@ internal void MoveObjectsToDontDestroyOnLoad()
else if (networkObject.HasAuthority)
{
networkObject.SetIsDestroying();
- var isSceneObject = networkObject.IsSceneObject;
// Only destroy non-scene placed NetworkObjects to avoid warnings about destroying in-scene placed NetworkObjects.
// (MoveObjectsToDontDestroyOnLoad is only invoked during a scene event type of load and the load scene mode is single)
- networkObject.Despawn(isSceneObject.HasValue && isSceneObject.Value == false);
+ networkObject.Despawn(!networkObject.InScenePlaced);
}
}
}
@@ -2745,19 +2744,18 @@ internal void PopulateScenePlacedObjects(Scene sceneToFilterBy, bool clearSceneP
{
ScenePlacedObjects.Clear();
}
- var networkObjects = FindObjects.ByType();
+ var sceneHandle = sceneToFilterBy.handle;
// Just add every NetworkObject found that isn't already in the list
// With additive scenes, we can have multiple in-scene placed NetworkObjects with the same GlobalObjectIdHash value
// During Client Side Synchronization: We add them on a FIFO basis, for each scene loaded without clearing, and then
// at the end of scene loading we use this list to soft synchronize all in-scene placed NetworkObjects
- foreach (var networkObjectInstance in networkObjects)
+ foreach (var networkObjectInstance in FindObjects.FromSceneByType(sceneToFilterBy, false))
{
var globalObjectIdHash = networkObjectInstance.GlobalObjectIdHash;
- var sceneHandle = networkObjectInstance.gameObject.scene.handle;
- // We check to make sure the NetworkManager instance is the same one to be "NetcodeIntegrationTestHelpers" compatible and filter the list on a per scene basis (for additive scenes)
- if (networkObjectInstance.IsSceneObject != false && (networkObjectInstance.NetworkManager == NetworkManager ||
- networkObjectInstance.NetworkManagerOwner == null) && sceneHandle == sceneToFilterBy.handle)
+ // We check to make sure the NetworkManager instance is the same one to be "NetcodeIntegrationTestHelpers" compatible and filter the list on a per-scene basis (for additive scenes)
+ if (networkObjectInstance.InScenePlaced && (networkObjectInstance.NetworkManager == NetworkManager ||
+ networkObjectInstance.NetworkManagerOwner == null))
{
if (!ScenePlacedObjects.ContainsKey(globalObjectIdHash))
{
@@ -2795,7 +2793,7 @@ internal void MoveObjectsFromDontDestroyOnLoadToScene(Scene scene)
{
// only move dynamically spawned network objects, with no parent as child objects will follow,
// back into the currently active scene
- if (networkObject.gameObject.transform.parent == null && networkObject.IsSceneObject != null && !networkObject.IsSceneObject.Value)
+ if (networkObject.gameObject.transform.parent == null && !networkObject.InScenePlaced)
{
if (NetworkManager.DistributedAuthorityMode)
{
@@ -2879,7 +2877,7 @@ internal void NotifyNetworkObjectSceneChanged(NetworkObject networkObject)
}
// Ignore in-scene placed NetworkObjects
- if (networkObject.IsSceneObject != false)
+ if (networkObject.InScenePlaced)
{
// Really, this should ever happen but in case it does
if (NetworkManager.LogLevel == LogLevel.Developer)
diff --git a/com.unity.netcode.gameobjects/Runtime/SceneManagement/SceneEventData.cs b/com.unity.netcode.gameobjects/Runtime/SceneManagement/SceneEventData.cs
index 0fff313574..9ab7ea7d86 100644
--- a/com.unity.netcode.gameobjects/Runtime/SceneManagement/SceneEventData.cs
+++ b/com.unity.netcode.gameobjects/Runtime/SceneManagement/SceneEventData.cs
@@ -133,7 +133,6 @@ internal class SceneEventData : IDisposable
private List m_NetworkObjectsSync = new List();
private List m_DespawnedInSceneObjectsSync = new List();
- private Dictionary> m_DespawnedInSceneObjects = new Dictionary>();
///
/// Server Side Re-Synchronization:
@@ -369,12 +368,11 @@ internal void AddDespawnedInSceneNetworkObjects()
{
m_DespawnedInSceneObjectsSync.Clear();
// Find all active and non-active in-scene placed NetworkObjects
- var inSceneNetworkObjects = FindObjects.ByType(true, true).Where((c) => c.NetworkManager == m_NetworkManager);
+ var inSceneNetworkObjects = FindObjects.ByType(true, true);
foreach (var sobj in inSceneNetworkObjects)
{
- if (sobj.IsSceneObject.HasValue && sobj.IsSceneObject.Value && !sobj.IsSpawned)
+ if (sobj.NetworkManager == m_NetworkManager && sobj.InScenePlaced && !sobj.IsSpawned)
{
- sobj.NetworkManagerOwner = m_NetworkManager;
m_DespawnedInSceneObjectsSync.Add(sobj);
}
}
@@ -1009,7 +1007,6 @@ internal void WriteClientSynchronizationResults(FastBufferWriter writer)
private void DeserializeDespawnedInScenePlacedNetworkObjects()
{
// Process all de-spawned in-scene NetworkObjects for this network session
- m_DespawnedInSceneObjects.Clear();
InternalBuffer.ReadValueSafe(out int despawnedObjectsCount);
var sceneCache = new Dictionary>();
@@ -1018,25 +1015,21 @@ private void DeserializeDespawnedInScenePlacedNetworkObjects()
// We just need to get the scene
InternalBuffer.ReadValueSafe(out NetworkSceneHandle networkSceneHandle);
InternalBuffer.ReadValueSafe(out uint globalObjectIdHash);
- var sceneRelativeNetworkObjects = new Dictionary();
- if (!sceneCache.ContainsKey(networkSceneHandle))
+
+ // Check if we already have processed the objects in this scene
+ if (!sceneCache.TryGetValue(networkSceneHandle, out var sceneRelativeNetworkObjects))
{
- if (m_NetworkManager.SceneManager.ServerSceneHandleToClientSceneHandle.ContainsKey(networkSceneHandle))
+ // If we haven't already cached the objects in this scene, build the cache
+ sceneRelativeNetworkObjects = new Dictionary();
+ if (m_NetworkManager.SceneManager.ServerSceneHandleToClientSceneHandle.TryGetValue(networkSceneHandle, out var localSceneHandle))
{
- var localSceneHandle = m_NetworkManager.SceneManager.ServerSceneHandleToClientSceneHandle[networkSceneHandle];
- if (m_NetworkManager.SceneManager.ScenesLoaded.ContainsKey(localSceneHandle))
+ if (m_NetworkManager.SceneManager.ScenesLoaded.TryGetValue(localSceneHandle, out var objectRelativeScene))
{
- var objectRelativeScene = m_NetworkManager.SceneManager.ScenesLoaded[localSceneHandle];
-
- // Find all active and non-active in-scene placed NetworkObjects
- var inSceneNetworkObjects = FindObjects.ByType(true, true).Where((c) =>
- c.GetSceneOriginHandle() == localSceneHandle && (c.IsSceneObject != false)).ToList();
-
- foreach (var inSceneObject in inSceneNetworkObjects)
+ foreach (var networkObject in FindObjects.FromSceneByType(objectRelativeScene, true))
{
- if (!sceneRelativeNetworkObjects.ContainsKey(inSceneObject.GlobalObjectIdHash))
+ if (networkObject.InScenePlaced)
{
- sceneRelativeNetworkObjects.Add(inSceneObject.GlobalObjectIdHash, inSceneObject);
+ sceneRelativeNetworkObjects.TryAdd(networkObject.GlobalObjectIdHash, networkObject);
}
}
// Add this to a cache so we don't have to run this potentially multiple times (nothing will spawn or despawn during this time
@@ -1052,10 +1045,6 @@ private void DeserializeDespawnedInScenePlacedNetworkObjects()
UnityEngine.Debug.LogError($"In-Scene NetworkObject GlobalObjectIdHash ({globalObjectIdHash}) cannot find its relative NetworkSceneHandle {networkSceneHandle}!");
}
}
- else // Use the cached NetworkObjects if they exist
- {
- sceneRelativeNetworkObjects = sceneCache[networkSceneHandle];
- }
// Now find the in-scene NetworkObject with the current GlobalObjectIdHash we are looking for
if (sceneRelativeNetworkObjects.TryGetValue(globalObjectIdHash, out var despawnedObject))
@@ -1143,7 +1132,7 @@ internal void SynchronizeSceneNetworkObjects(NetworkManager networkManager)
// Notify that all in-scene placed NetworkObjects have been spawned
foreach (var networkObject in m_NetworkObjectsSync)
{
- if (networkObject.IsSceneObject.HasValue && networkObject.IsSceneObject.Value)
+ if (networkObject.IsSpawned && networkObject.InScenePlaced)
{
networkObject.InternalInSceneNetworkObjectsSpawned();
}
diff --git a/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs b/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs
index 7a2f45b1d1..46f52bc4f9 100644
--- a/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs
+++ b/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs
@@ -1320,11 +1320,15 @@ internal bool SpawnNetworkObjectLocallyCommon(NetworkObject networkObject, ulong
return false;
}
- networkObject.IsSceneObject = sceneObject;
+#pragma warning disable CS0618 // Type or member is obsolete
+ // Obsolete with warning means we need the underlying behaviour to keep existing
+ // TODO: remove in the 3.x branch
+ networkObject.SetSceneObjectStatus(sceneObject);
+#pragma warning restore CS0618 // Type or member is obsolete
// Always check to make sure our scene of origin is properly set for in-scene placed NetworkObjects
// Note: Always check SceneOriginHandle directly at this specific location.
- if (networkObject.IsSceneObject != false && networkObject.SceneOriginHandle.IsEmpty())
+ if (networkObject.InScenePlaced && networkObject.SceneOriginHandle.IsEmpty())
{
networkObject.SceneOrigin = networkObject.gameObject.scene;
}
@@ -1379,17 +1383,6 @@ internal bool SpawnNetworkObjectLocallyCommon(NetworkObject networkObject, ulong
networkObject.InvokeBehaviourNetworkSpawn();
- // propagate the IsSceneObject setting to child NetworkObjects
- var children = networkObject.GetComponentsInChildren();
- foreach (var childObject in children)
- {
- // Do not propagate the in-scene object setting if a child was dynamically spawned.
- if (childObject.IsSceneObject.HasValue && !childObject.IsSceneObject.Value)
- {
- continue;
- }
- childObject.IsSceneObject = sceneObject;
- }
// Only dynamically spawned NetworkObjects are allowed
if (!sceneObject)
@@ -1404,7 +1397,7 @@ internal bool SpawnNetworkObjectLocallyCommon(NetworkObject networkObject, ulong
// If we are an in-scene placed NetworkObject and our InScenePlacedSourceGlobalObjectIdHash is set
// then assign this to the PrefabGlobalObjectIdHash
- if (networkObject.IsSceneObject.Value && networkObject.InScenePlacedSourceGlobalObjectIdHash != 0)
+ if (networkObject.InScenePlaced && networkObject.InScenePlacedSourceGlobalObjectIdHash != 0)
{
networkObject.PrefabGlobalObjectIdHash = networkObject.InScenePlacedSourceGlobalObjectIdHash;
}
@@ -1552,14 +1545,17 @@ internal void DespawnObject(NetworkObject networkObject, bool destroyObject = fa
}
// Makes scene objects ready to be reused
- internal void ServerResetShudownStateForSceneObjects()
+ internal void ServerResetShutdownStateForSceneObjects()
{
- var networkObjects = FindObjects.ByType(orderByIdentifier: true).Where((c) => c.IsSceneObject != null && c.IsSceneObject == true);
+ var networkObjects = FindObjects.ByType(orderByIdentifier: true, includeInactive: true);
foreach (var sobj in networkObjects)
{
+ if (!sobj.InScenePlaced)
+ {
+ continue;
+ }
sobj.IsSpawned = false;
sobj.DestroyWithScene = false;
- sobj.IsSceneObject = null;
}
}
@@ -1575,7 +1571,7 @@ internal void ServerDestroySpawnedSceneObjects()
foreach (var networkObject in spawnedObjects)
{
- if (networkObject.IsSceneObject != null && networkObject.IsSceneObject.Value && networkObject.DestroyWithScene
+ if (networkObject.InScenePlaced && networkObject.DestroyWithScene
&& networkObject.gameObject.scene != NetworkManager.SceneManager.DontDestroyOnLoadScene)
{
if (networkObject.IsSpawned && networkObject.HasAuthority)
@@ -1619,7 +1615,7 @@ internal void DespawnAndDestroyNetworkObjects()
{
// If it is an in-scene placed NetworkObject then just despawn and let it be destroyed when the scene
// is unloaded. Otherwise, despawn and destroy it.
- var shouldDestroy = !(networkObject.IsSceneObject == null || (networkObject.IsSceneObject != null && networkObject.IsSceneObject.Value));
+ var shouldDestroy = !networkObject.InScenePlaced;
// If we are going to destroy this NetworkObject, check for any in-scene placed children that need to be removed
if (shouldDestroy)
@@ -1635,7 +1631,7 @@ internal void DespawnAndDestroyNetworkObjects()
// If the child is an in-scene placed NetworkObject then remove the child from the parent (which was dynamically spawned)
// and set its parent to root
- if (childObject.IsSceneObject != null && childObject.IsSceneObject.Value)
+ if (childObject.InScenePlaced)
{
childObject.TryRemoveParentCachedWorldPositionStays();
}
@@ -1654,27 +1650,24 @@ internal void DestroySceneObjects()
for (int i = 0; i < networkObjects.Length; i++)
{
- if (networkObjects[i].NetworkManager == NetworkManager)
+ if (networkObjects[i].NetworkManager == NetworkManager && networkObjects[i].InScenePlaced)
{
- if (networkObjects[i].IsSceneObject == null || networkObjects[i].IsSceneObject.Value == true)
+ if (NetworkManager.PrefabHandler.ContainsHandler(networkObjects[i]))
{
- if (NetworkManager.PrefabHandler.ContainsHandler(networkObjects[i]))
+ if (SpawnedObjects.ContainsKey(networkObjects[i].NetworkObjectId))
{
- if (SpawnedObjects.ContainsKey(networkObjects[i].NetworkObjectId))
- {
- // This method invokes HandleNetworkPrefabDestroy, we only want to handle this once.
- OnDespawnObject(networkObjects[i], false);
- }
- else // If not spawned, then just invoke the handler
- {
- NetworkManager.PrefabHandler.HandleNetworkPrefabDestroy(networkObjects[i]);
- }
+ // This method invokes HandleNetworkPrefabDestroy, we only want to handle this once.
+ OnDespawnObject(networkObjects[i], false);
}
- else
+ else // If not spawned, then just invoke the handler
{
- Object.Destroy(networkObjects[i].gameObject);
+ NetworkManager.PrefabHandler.HandleNetworkPrefabDestroy(networkObjects[i]);
}
}
+ else
+ {
+ Object.Destroy(networkObjects[i].gameObject);
+ }
}
}
}
@@ -1693,7 +1686,7 @@ internal void ServerSpawnSceneObjectsOnStartSweep()
// This used to be two loops.
// The first added all NetworkObjects to a list and the second spawned all NetworkObjects in the list.
// Now, a parent will set its children's IsSceneObject value when spawned, so we check for null or for true.
- if (networkObject.IsSceneObject == null || (networkObject.IsSceneObject.HasValue && networkObject.IsSceneObject.Value))
+ if (networkObject.InScenePlaced)
{
var ownerId = networkObject.OwnerClientId;
if (NetworkManager.DistributedAuthorityMode)
@@ -1744,7 +1737,7 @@ internal void OnDespawnNonAuthorityObject([NotNull] NetworkObject networkObject,
}
}
- if (networkObject.IsSceneObject == false)
+ if (!networkObject.InScenePlaced)
{
// If the object is not an in-scene placed NetworkObject, then we always destroy the object on the non-authority side
destroyGameObject = true;
@@ -1786,7 +1779,7 @@ internal void OnDespawnObject([NotNull] NetworkObject networkObject, bool destro
// DistributedAuthorityMode: All clients need to remove the parent locally due to mixed-authority hierarchies and race-conditions
if (!NetworkManager.ShutdownInProgress && (NetworkManager.IsServer || distributedAuthority))
{
- if (destroyGameObject && networkObject.IsSceneObject == true && !NetworkManager.SceneManager.IsSceneUnloading(networkObject))
+ if (destroyGameObject && networkObject.InScenePlaced && !NetworkManager.SceneManager.IsSceneUnloading(networkObject))
{
if (NetworkManager.LogLevel <= LogLevel.Normal)
{
@@ -2113,7 +2106,7 @@ internal void GetObjectDistribution(ulong clientId, ref Dictionary();
networkObject.IsSpawned = true;
networkObject.SceneOriginHandle = default;
- networkObject.IsSceneObject = false;
// This validates invoking GetSceneOriginHandle will not throw an exception for a dynamically spawned NetworkObject
// when the scene of origin hasn't been set.
var sceneOriginHandle = networkObject.GetSceneOriginHandle();
diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkObject/NetworkObjectSpawnManyObjectsTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkObject/NetworkObjectSpawnManyObjectsTests.cs
index cf786bd0c4..ad643d7ca7 100644
--- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkObject/NetworkObjectSpawnManyObjectsTests.cs
+++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkObject/NetworkObjectSpawnManyObjectsTests.cs
@@ -37,7 +37,6 @@ protected override void OnServerAndClientsCreated()
var gameObject = new GameObject("TestObject");
var networkObject = gameObject.AddComponent();
NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(networkObject);
- networkObject.IsSceneObject = false;
gameObject.AddComponent();
m_PrefabToSpawn = new NetworkPrefab() { Prefab = gameObject };
diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableBaseInitializesWhenPersisted.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableBaseInitializesWhenPersisted.cs
index 0245602fcd..6e8dc8cde9 100644
--- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableBaseInitializesWhenPersisted.cs
+++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableBaseInitializesWhenPersisted.cs
@@ -26,7 +26,6 @@ protected override void OnOneTimeSetup()
s_NetworkPrefab = new GameObject("PresistPrefab");
var networkObject = s_NetworkPrefab.AddComponent();
networkObject.GlobalObjectIdHash = 8888888;
- networkObject.SetSceneObjectStatus(false);
s_NetworkPrefab.AddComponent();
s_NetworkPrefab.AddComponent();
// Create enough prefab instance handlers to be re-used for all tests.
@@ -374,7 +373,6 @@ public NetworkObject GetInstance()
if (PrefabInstances.Count == 0)
{
instanceToReturn = Object.Instantiate(m_NetworkPrefab).GetComponent();
- instanceToReturn.SetSceneObjectStatus(false);
instanceToReturn.gameObject.SetActive(true);
}
else
diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Prefabs/NetworkPrefabOverrideTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Prefabs/NetworkPrefabOverrideTests.cs
index 502146fa24..571ab30133 100644
--- a/com.unity.netcode.gameobjects/Tests/Runtime/Prefabs/NetworkPrefabOverrideTests.cs
+++ b/com.unity.netcode.gameobjects/Tests/Runtime/Prefabs/NetworkPrefabOverrideTests.cs
@@ -174,11 +174,6 @@ protected override void OnServerAndClientsCreated()
networkManager.NetworkConfig.Prefabs.Add(m_ClientSidePlayerPrefab);
}
- m_PrefabOverride.Prefab.GetComponent().IsSceneObject = false;
- m_PrefabOverride.SourcePrefabToOverride.GetComponent().IsSceneObject = false;
- m_PrefabOverride.OverridingTargetPrefab.GetComponent().IsSceneObject = false;
- m_ClientSidePlayerPrefab.Prefab.GetComponent().IsSceneObject = false;
-
base.OnServerAndClientsCreated();
}
diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/IntegrationTestSceneHandler.cs b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/IntegrationTestSceneHandler.cs
index 2a5c2c35f9..209caf300b 100644
--- a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/IntegrationTestSceneHandler.cs
+++ b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/IntegrationTestSceneHandler.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;
using Object = UnityEngine.Object;
@@ -141,47 +140,27 @@ private static void SceneManager_sceneLoaded(Scene scene, LoadSceneMode loadScen
{
SceneManager.sceneLoaded -= SceneManager_sceneLoaded;
- ProcessInSceneObjects(scene, CurrentQueuedSceneJob.IntegrationTestSceneHandler.NetworkManager);
+ ProcessInSceneObjects(scene);
CurrentQueuedSceneJob.JobType = QueuedSceneJob.JobTypes.Completed;
}
}
///
- /// Handles some pre-spawn processing of in-scene placed NetworkObjects
- /// to make sure the appropriate NetworkManagerOwner is assigned. It
- /// also makes sure that each in-scene placed NetworkObject has an
+ /// Handles some pre-spawn processing of in-scene placed NetworkObjects.
+ /// Makes sure that each in-scene placed NetworkObject has an
/// ObjectIdentifier component if one is not assigned to it or its
/// children.
///
/// the scenes that was just loaded
- /// the relative NetworkManager
- private static void ProcessInSceneObjects(Scene scene, NetworkManager networkManager)
+ private static void ProcessInSceneObjects(Scene scene)
{
- // Get all in-scene placed NeworkObjects that were instantiated when this scene loaded
- var inSceneNetworkObjects = FindObjects.ByType(orderByIdentifier: true).Where((c) => c.IsSceneObject != false && c.GetSceneOriginHandle() == scene.handle);
- foreach (var sobj in inSceneNetworkObjects)
+ // Get all in-scene placed NetworkObjects that were instantiated when this scene loaded
+ foreach (var sceneObject in FindObjects.FromSceneByType(scene, false))
{
- ProcessInSceneObject(sobj, networkManager);
- }
- }
-
- ///
- /// Assures to apply an ObjectNameIdentifier to all children
- ///
- private static void ProcessInSceneObject(NetworkObject networkObject, NetworkManager networkManager)
- {
- if (networkObject.GetComponent() == null)
- {
- networkObject.gameObject.AddComponent();
- var networkObjects = networkObject.gameObject.GetComponentsInChildren();
- foreach (var child in networkObjects)
+ if (sceneObject.InScenePlaced && sceneObject.GetComponent() == null)
{
- if (child == networkObject)
- {
- continue;
- }
- ProcessInSceneObject(child, networkManager);
+ sceneObject.gameObject.AddComponent();
}
}
}
@@ -288,7 +267,7 @@ private void Sever_SceneLoaded(Scene scene, LoadSceneMode arg1)
if (m_ServerSceneBeingLoaded == scene.name)
{
SceneManager.sceneLoaded -= Sever_SceneLoaded;
- ProcessInSceneObjects(scene, NetworkManager);
+ ProcessInSceneObjects(scene);
}
}
@@ -708,16 +687,11 @@ public void MoveObjectsFromSceneToDontDestroyOnLoad(ref NetworkManager networkMa
{
// Create a local copy of the spawned objects list since the spawn manager will adjust the list as objects
// are despawned.
- var networkObjects = FindObjects.ByType(orderByIdentifier: true).Where((c) => c.IsSpawned);
var distributedAuthority = networkManager.DistributedAuthorityMode;
- foreach (var networkObject in networkObjects)
+ foreach (var networkObject in FindObjects.FromSceneByType(scene, false))
{
- if (networkObject == null || (networkObject != null && networkObject.gameObject.scene.handle != scene.handle))
+ if (!networkObject.IsSpawned)
{
- if (networkObject != null)
- {
- VerboseDebug($"[MoveObjects from {scene.name} | {scene.handle}] Ignoring {networkObject.gameObject.name} because it isn't in scene {networkObject.gameObject.scene.name} ");
- }
continue;
}
@@ -750,7 +724,7 @@ public void MoveObjectsFromSceneToDontDestroyOnLoad(ref NetworkManager networkMa
if (!networkObject.DestroyWithScene && networkObject.gameObject.scene != networkManager.SceneManager.DontDestroyOnLoadScene)
{
// Only move dynamically spawned NetworkObjects with no parent as the children will follow
- if (networkObject.gameObject.transform.parent == null && networkObject.IsSceneObject != null && !networkObject.IsSceneObject.Value)
+ if (networkObject.gameObject.transform.parent == null && !networkObject.InScenePlaced)
{
VerboseDebug($"[MoveObjects from {scene.name} | {scene.handle}] Moving {networkObject.gameObject.name} because it is in scene {networkObject.gameObject.scene.name} with DWS = {networkObject.DestroyWithScene}.");
Object.DontDestroyOnLoad(networkObject.gameObject);
diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTest.cs b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTest.cs
index a6f4a83275..b9c5623759 100644
--- a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTest.cs
+++ b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTest.cs
@@ -728,7 +728,6 @@ private void CreatePlayerPrefab()
m_PlayerPrefab = new GameObject("Player");
OnPlayerPrefabGameObjectCreated();
NetworkObject networkObject = m_PlayerPrefab.AddComponent();
- networkObject.IsSceneObject = false;
// Make it a prefab
NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(networkObject);
diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTestHelpers.cs b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTestHelpers.cs
index 32a0f734d7..99c7f47afc 100644
--- a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTestHelpers.cs
+++ b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTestHelpers.cs
@@ -690,9 +690,6 @@ public static void MakeNetworkObjectTestPrefab(NetworkObject networkObject, uint
networkObject.GlobalObjectIdHash = ++s_AutoIncrementGlobalObjectIdHashCounter;
}
- // Prevent object from being snapped up as a scene object
- networkObject.IsSceneObject = false;
-
// To avoid issues with integration tests that forget to clean up,
// this feature only works with NetcodeIntegrationTest derived classes
if (IsNetcodeIntegrationTestRunning)
diff --git a/com.unity.netcode.gameobjects/package.json b/com.unity.netcode.gameobjects/package.json
index bd77e48697..b4e25e69f0 100644
--- a/com.unity.netcode.gameobjects/package.json
+++ b/com.unity.netcode.gameobjects/package.json
@@ -2,7 +2,7 @@
"name": "com.unity.netcode.gameobjects",
"displayName": "Netcode for GameObjects",
"description": "Netcode for GameObjects is a high-level netcode SDK that provides networking capabilities to GameObject/MonoBehaviour workflows within Unity and sits on top of underlying transport layer.",
- "version": "2.12.0",
+ "version": "2.13.0",
"unity": "6000.0",
"dependencies": {
"com.unity.nuget.mono-cecil": "1.11.4",
diff --git a/testproject/Assets/Tests/Runtime/NetworkManagerTests.cs b/testproject/Assets/Tests/Runtime/NetworkManagerTests.cs
index 411d7e6fec..ccf46cb61c 100644
--- a/testproject/Assets/Tests/Runtime/NetworkManagerTests.cs
+++ b/testproject/Assets/Tests/Runtime/NetworkManagerTests.cs
@@ -155,7 +155,7 @@ public IEnumerator ValidateShutdown([Values] ShutdownChecks shutdownCheck)
for (int i = spawnedObjects.Count - 1; i >= 0; i--)
{
var spawnedObject = spawnedObjects[i];
- if (spawnedObject.IsSceneObject != null && spawnedObject.IsSceneObject.Value)
+ if (spawnedObject.InScenePlaced)
{
spawnedObject.Despawn();
}
diff --git a/testproject/Assets/Tests/Runtime/NetworkSceneManager/AttachableBehaviourSceneLoadTests.cs b/testproject/Assets/Tests/Runtime/NetworkSceneManager/AttachableBehaviourSceneLoadTests.cs
index 58d056d8d0..a3e31983e1 100644
--- a/testproject/Assets/Tests/Runtime/NetworkSceneManager/AttachableBehaviourSceneLoadTests.cs
+++ b/testproject/Assets/Tests/Runtime/NetworkSceneManager/AttachableBehaviourSceneLoadTests.cs
@@ -318,7 +318,7 @@ public IEnumerator AttachedUponSceneTransition([Values] bool detachOnDespawn)
var persists = m_Persists == Persists.AttachableNode ? m_TargetInstance.NetworkObjectId : m_SourceInstance.NetworkObjectId;
m_DoesNotPersistNetworkObjectIds.Add(doesNotPersist);
persistedObjects.Add(networkManager, persists);
- Debug.Log($"[{networkManager.name}] Spawned attachable and attached it.");
+ VerboseDebug($"[{networkManager.name}] Spawned attachable and attached it.");
}
// This is the actual validation point where the scene is unloaded and either the attachable or
diff --git a/testproject/Assets/Tests/Runtime/NetworkSceneManager/ClientSynchronizationValidationTest.cs b/testproject/Assets/Tests/Runtime/NetworkSceneManager/ClientSynchronizationValidationTest.cs
index 32f88e9221..ea5dfc47ad 100644
--- a/testproject/Assets/Tests/Runtime/NetworkSceneManager/ClientSynchronizationValidationTest.cs
+++ b/testproject/Assets/Tests/Runtime/NetworkSceneManager/ClientSynchronizationValidationTest.cs
@@ -110,7 +110,7 @@ public IEnumerator ClientVerifySceneBeforeLoading([Values] bool startClientBefor
foreach (var spawnedObjectEntry in m_ServerNetworkManager.SpawnManager.SpawnedObjects)
{
var networkObject = spawnedObjectEntry.Value;
- if (!networkObject.IsSceneObject.Value)
+ if (!networkObject.InScenePlaced)
{
continue;
}
@@ -138,7 +138,7 @@ public IEnumerator ClientVerifySceneBeforeLoading([Values] bool startClientBefor
foreach (var spawnedObjectEntry in m_ServerNetworkManager.SpawnManager.SpawnedObjects)
{
var networkObject = spawnedObjectEntry.Value;
- if (!networkObject.IsSceneObject.Value)
+ if (!networkObject.InScenePlaced)
{
continue;
}
diff --git a/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerDDOLTests.cs b/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerDDOLTests.cs
index f38a311ea8..70ca7c24d2 100644
--- a/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerDDOLTests.cs
+++ b/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerDDOLTests.cs
@@ -94,8 +94,8 @@ public IEnumerator InSceneNetworkObjectState([Values(DefaultState.IsEnabled, Def
[Values(NetworkObjectType.InScenePlaced, NetworkObjectType.DynamicallySpawned)] NetworkObjectType networkObjectType)
{
var waitForFullNetworkTick = new WaitForSeconds(1.0f / m_ServerNetworkManager.NetworkConfig.TickRate);
- var isActive = activeState == DefaultState.IsEnabled ? true : false;
- var isInScene = networkObjectType == NetworkObjectType.InScenePlaced ? true : false;
+ var isActive = activeState == DefaultState.IsEnabled;
+ var isInScene = networkObjectType == NetworkObjectType.InScenePlaced;
var objectInstance = Object.Instantiate(m_DDOL_ObjectToSpawn);
var networkObject = objectInstance.GetComponent();
@@ -110,7 +110,7 @@ public IEnumerator InSceneNetworkObjectState([Values(DefaultState.IsEnabled, Def
}
// Sets whether we are in-scene or dynamically spawned NetworkObject
- ddolBehaviour.SetInScene(isInScene);
+ networkObject.InScenePlaced = isInScene;
networkObject.Spawn();
yield return waitForFullNetworkTick;
@@ -148,12 +148,6 @@ public override void OnNetworkSpawn()
NetworkObject.DestroyWithScene = false;
base.OnNetworkSpawn();
}
-
- public void SetInScene(bool isInScene)
- {
- var networkObject = GetComponent();
- networkObject.IsSceneObject = isInScene;
- }
}
}
diff --git a/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerEventDataPoolTest.cs b/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerEventDataPoolTest.cs
index 7c448830f6..107db75314 100644
--- a/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerEventDataPoolTest.cs
+++ b/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerEventDataPoolTest.cs
@@ -381,11 +381,11 @@ private bool CheckNetworkObjectsToSynchronizeSceneChanges(NetworkManager network
m_ErrorMsg.Clear();
if (networkManager.SpawnManager.NetworkObjectsToSynchronizeSceneChanges.Count > 0)
{
- foreach (var entry in networkManager.SpawnManager.NetworkObjectsToSynchronizeSceneChanges)
+ foreach (var obj in networkManager.SpawnManager.NetworkObjectsToSynchronizeSceneChanges.Values)
{
- if (entry.Value.IsSceneObject.HasValue && entry.Value.IsSceneObject.Value)
+ if (obj.InScenePlaced)
{
- m_ErrorMsg.AppendLine($"{entry.Value.name} still exists within {nameof(NetworkSpawnManager.NetworkObjectsToSynchronizeSceneChanges)}!");
+ m_ErrorMsg.AppendLine($"{obj.name} still exists within {nameof(NetworkSpawnManager.NetworkObjectsToSynchronizeSceneChanges)}!");
}
}
}
diff --git a/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerPopulateInSceneTests.cs b/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerPopulateInSceneTests.cs
index bc3a24cb78..1d2302592e 100644
--- a/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerPopulateInSceneTests.cs
+++ b/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerPopulateInSceneTests.cs
@@ -40,7 +40,7 @@ protected override void OnServerAndClientsCreated()
// the scene is loaded (i.e. IsSceneObject is null)
var inScenePrefab = CreateNetworkObjectPrefab("NewSceneObject");
var networkObject = inScenePrefab.GetComponent();
- networkObject.IsSceneObject = null;
+ networkObject.InScenePlaced = true;
networkObject.NetworkManagerOwner = m_ServerNetworkManager;
m_InSceneObjectList.Add(networkObject.GlobalObjectIdHash, inScenePrefab);
@@ -49,7 +49,7 @@ protected override void OnServerAndClientsCreated()
// unloading/reloading any scenes.
inScenePrefab = CreateNetworkObjectPrefab("SetInSceneObject");
networkObject = inScenePrefab.GetComponent();
- networkObject.IsSceneObject = true;
+ networkObject.InScenePlaced = true;
networkObject.NetworkManagerOwner = m_ServerNetworkManager;
m_InSceneObjectList.Add(networkObject.GlobalObjectIdHash, inScenePrefab);
}
diff --git a/testproject/Assets/Tests/Runtime/ObjectParenting/ParentDynamicUnderInScenePlaced.cs b/testproject/Assets/Tests/Runtime/ObjectParenting/ParentDynamicUnderInScenePlaced.cs
index 3bf12e7011..2770ed4ce5 100644
--- a/testproject/Assets/Tests/Runtime/ObjectParenting/ParentDynamicUnderInScenePlaced.cs
+++ b/testproject/Assets/Tests/Runtime/ObjectParenting/ParentDynamicUnderInScenePlaced.cs
@@ -74,7 +74,7 @@ private bool TestParentedAndNotInScenePlaced()
{
// Always assign m_FailedValidation to avoid possible null reference crashes.
var serverPlayer = m_FailedValidation = m_ServerNetworkManager.LocalClient.PlayerObject;
- if (serverPlayer.transform.parent == null || serverPlayer.IsSceneObject.Value == true)
+ if (serverPlayer.transform.parent == null || serverPlayer.InScenePlaced)
{
m_FailedValidation = serverPlayer;
return false;
@@ -83,7 +83,7 @@ private bool TestParentedAndNotInScenePlaced()
foreach (var clientNetworkManager in m_ClientNetworkManagers)
{
var lateJoinPlayer = clientNetworkManager.LocalClient.PlayerObject;
- if (lateJoinPlayer.transform.parent == null || lateJoinPlayer.IsSceneObject.Value == true)
+ if (lateJoinPlayer.transform.parent == null || lateJoinPlayer.InScenePlaced)
{
m_FailedValidation = lateJoinPlayer;
return false;
@@ -93,7 +93,7 @@ private bool TestParentedAndNotInScenePlaced()
foreach (var dynamicallySpawned in ParentDynamicUnderInScenePlacedHelper.Instances)
{
var networkObject = dynamicallySpawned.Value;
- if (networkObject.transform.parent == null || networkObject.IsSceneObject.Value == true)
+ if (networkObject.transform.parent == null || networkObject.InScenePlaced)
{
m_FailedValidation = networkObject;
return false;
@@ -124,7 +124,7 @@ public IEnumerator ParentUnderInSceneplaced()
// Wait for the host-server's player to be parented under the in-scene placed NetworkObject
yield return WaitForConditionOrTimeOut(TestParentedAndNotInScenePlaced);
- AssertOnTimeout($"[{m_FailedValidation.name}] Failed validation! InScenePlaced ({m_FailedValidation.IsSceneObject.Value}) | Was Parented ({m_FailedValidation.transform.position != null})");
+ AssertOnTimeout($"[{m_FailedValidation.name}] Failed validation! InScenePlaced ({m_FailedValidation.InScenePlaced}) | Was Parented ({m_FailedValidation.transform.position != null})");
m_TargetScenePlacedId = m_ServerNetworkManager.LocalClient.PlayerObject.transform.parent.GetComponent().NetworkObjectId;
// Now dynamically spawn a NetworkObject to also test dynamically spawned NetworkObjects being parented
@@ -141,7 +141,7 @@ public IEnumerator ParentUnderInSceneplaced()
AssertOnTimeout($"[Client-{i + 1}] Failed to find in-scene placed NetworkObject or failed to parent under it!");
}
yield return WaitForConditionOrTimeOut(TestParentedAndNotInScenePlaced);
- AssertOnTimeout($"[{m_FailedValidation.name}] Failed validation! InScenePlaced ({m_FailedValidation.IsSceneObject.Value}) | Was Parented ({m_FailedValidation.transform.position != null})");
+ AssertOnTimeout($"[{m_FailedValidation.name}] Failed validation! InScenePlaced ({m_FailedValidation.InScenePlaced}) | Was Parented ({m_FailedValidation.transform.position != null})");
}
}
diff --git a/testproject/Assets/Tests/Runtime/PrefabExtendedTests.cs b/testproject/Assets/Tests/Runtime/PrefabExtendedTests.cs
index d0f7e294cb..909bb7585d 100644
--- a/testproject/Assets/Tests/Runtime/PrefabExtendedTests.cs
+++ b/testproject/Assets/Tests/Runtime/PrefabExtendedTests.cs
@@ -163,7 +163,7 @@ private bool ValidateAllClientsSpawnedObjects()
var clientSpawnedObject = s_GlobalNetworkObjects[client.LocalClientId][spawnedObject.NetworkObjectId];
// When scene management is disabled, we match against the InScenePlacedSourceGlobalObjectIdHash for in-scene placed NetworkObjects
- var spawnedObjectGlobalObjectIdHash = !m_SceneManagementEnabled && spawnedObject.IsSceneObject.Value ? spawnedObject.InScenePlacedSourceGlobalObjectIdHash : spawnedObject.GlobalObjectIdHash;
+ var spawnedObjectGlobalObjectIdHash = !m_SceneManagementEnabled && spawnedObject.InScenePlaced ? spawnedObject.InScenePlacedSourceGlobalObjectIdHash : spawnedObject.GlobalObjectIdHash;
// Validate the GlobalObjectIdHash values match
if (clientSpawnedObject.GlobalObjectIdHash != spawnedObjectGlobalObjectIdHash)
{