Skip to content

Commit b6cea30

Browse files
authored
Merge branch 'develop-2.0.0' into fix/rpc-message-logging
2 parents 69c939c + 7c992c2 commit b6cea30

31 files changed

Lines changed: 345 additions & 190 deletions

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
1616

1717
### Deprecated
1818

19+
- Deprecated the nullable boolean `NetworkObject.IsSceneObject` and introduced `NetworkObject.InScenePlaced`. (#4000)
1920

2021
### Removed
2122

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using UnityEditor;
2+
using UnityEditor.Build;
3+
using UnityEditor.Build.Reporting;
4+
using UnityEngine;
5+
using UnityEngine.SceneManagement;
6+
7+
namespace Unity.Netcode.Editor
8+
{
9+
/// <summary>
10+
/// A <see cref="IProcessSceneWithReport"/> that sets the <see cref
11+
/// "NetworkObject.InScenePlaced"/> property to true for all <see cref="NetworkObject"/>s in the scene.
12+
/// Ensures that InScenePlaced is always true for all objects in the scene.
13+
/// </summary>
14+
/// <remarks>
15+
/// This will always run as the game enters the scene,
16+
/// </remarks>
17+
internal class SetInScenePlaced : IProcessSceneWithReport
18+
{
19+
public int callbackOrder => 0;
20+
public void OnProcessScene(Scene scene, BuildReport report)
21+
{
22+
foreach (var networkObject in FindObjects.FromSceneByType<NetworkObject>(scene, true))
23+
{
24+
networkObject.InScenePlaced = true;
25+
}
26+
}
27+
}
28+
29+
/// <summary>
30+
/// An <see cref="AssetPostprocessor"/> that sets the <see cref="NetworkObject.InScenePlaced"/> property to false for all <see cref="NetworkObject"/>s in prefabs.
31+
/// Ensures that InScenePlaced is always false for all prefab objects.
32+
/// This is important because when a prefab is instantiated in the scene, it should be treated as a dynamically spawned object.
33+
/// </summary>
34+
internal class InScenePlacedPrefabBuilder : AssetPostprocessor
35+
{
36+
public void OnPostprocessPrefab(GameObject root)
37+
{
38+
var networkObjects = root.GetComponentsInChildren<NetworkObject>(true);
39+
foreach (var networkObject in networkObjects)
40+
{
41+
networkObject.InScenePlaced = false;
42+
}
43+
}
44+
}
45+
}

com.unity.netcode.gameobjects/Editor/InScenePlacedProcessor.cs.meta

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

com.unity.netcode.gameobjects/Editor/NetworkObjectEditor.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,10 @@ public override void OnInspectorGUI()
6767
EditorGUILayout.Toggle(nameof(NetworkObject.IsOwner), m_NetworkObject.IsOwner);
6868
EditorGUILayout.Toggle(nameof(NetworkObject.IsOwnedByServer), m_NetworkObject.IsOwnedByServer);
6969
EditorGUILayout.Toggle(nameof(NetworkObject.IsPlayerObject), m_NetworkObject.IsPlayerObject);
70-
if (m_NetworkObject.IsSceneObject.HasValue)
71-
{
72-
EditorGUILayout.Toggle(nameof(NetworkObject.IsSceneObject), m_NetworkObject.IsSceneObject.Value);
73-
}
74-
else
75-
{
76-
EditorGUILayout.TextField(nameof(NetworkObject.IsSceneObject), "null");
77-
}
70+
#pragma warning disable CS0618 // Type or member is obsolete
71+
// TODO-3.x: Update name in 3.x branch
72+
EditorGUILayout.Toggle(nameof(NetworkObject.IsSceneObject), m_NetworkObject.InScenePlaced);
73+
#pragma warning restore CS0618 // Type or member is obsolete
7874
EditorGUILayout.Toggle(nameof(NetworkObject.DestroyWithScene), m_NetworkObject.DestroyWithScene);
7975
EditorGUILayout.TextField(nameof(NetworkObject.NetworkManager), m_NetworkObject.NetworkManager == null ? "null" : m_NetworkObject.NetworkManager.gameObject.name);
8076
GUI.enabled = guiEnabled;

com.unity.netcode.gameobjects/Runtime/Components/NetworkTransform.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2231,7 +2231,7 @@ private bool CheckForStateChange(ref NetworkTransformState networkState, bool is
22312231

22322232
// In-scene placed NetworkObjects parented under a GameObject with no
22332233
// NetworkObject preserve their lossyScale when synchronizing.
2234-
if (parentNetworkObject == null && NetworkObject.IsSceneObject != false)
2234+
if (parentNetworkObject == null && NetworkObject.InScenePlaced)
22352235
{
22362236
hasParentNetworkObject = true;
22372237
}

com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1184,7 +1184,11 @@ internal void CreateAndSpawnPlayer(ulong ownerId)
11841184
return;
11851185
}
11861186

1187-
networkObject.IsSceneObject = false;
1187+
#pragma warning disable CS0618 // Type or member is obsolete
1188+
// Obsolete with warning means we need the underlying behaviour to keep existing
1189+
// TODO: remove in the 3.x branch
1190+
networkObject.SetSceneObjectStatus(false);
1191+
#pragma warning restore CS0618 // Type or member is obsolete
11881192
networkObject.NetworkManagerOwner = NetworkManager;
11891193
networkObject.SpawnAsPlayerObject(ownerId, networkObject.DestroyWithScene);
11901194
}

com.unity.netcode.gameobjects/Runtime/Core/FindObjects.cs

Lines changed: 90 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
#if NGO_FINDOBJECTS_NOSORTING
21
using System;
3-
#endif
2+
using System.Collections;
3+
using System.Collections.Generic;
44
using System.Runtime.CompilerServices;
5+
using UnityEngine.SceneManagement;
56
using Object = UnityEngine.Object;
67

78
namespace Unity.Netcode
@@ -11,14 +12,14 @@ namespace Unity.Netcode
1112
/// </summary>
1213
/// <remarks>
1314
/// It is intentional that we do not include the UnityEngine namespace in order to avoid
14-
/// over-complicatd define wrapping between versions that do or don't support FindObjectsSortMode.
15+
/// over-complicated define wrapping between versions that do or don't support FindObjectsSortMode.
1516
/// </remarks>
1617
internal static class FindObjects
1718
{
1819
/// <summary>
1920
/// Replaces <see cref="Object.FindObjectsByType"/> to have one place where these changes are applied.
2021
/// </summary>
21-
/// <typeparam name="T"></typeparam>
22+
/// <typeparam name="T">The type of object to find. Must be a reference type derived from <see cref="Object"/></typeparam>
2223
/// <param name="includeInactive">When true, inactive objects will be included.</param>
2324
/// <param name="orderByIdentifier">When true, the array returned will be sorted by identifier.</param>
2425
/// <returns>Results as an <see cref="Array"/> of type T</returns>
@@ -39,5 +40,90 @@ public static T[] ByType<T>(bool includeInactive = false, bool orderByIdentifier
3940
#endif
4041
return results;
4142
}
43+
44+
/// <summary>
45+
/// Returns an enumerator that enumerates over all the components of a given type in a scene.
46+
/// </summary>
47+
/// <param name="scene">The scene to use for searching</param>
48+
/// <param name="includeInactive">When true, inactive objects will be included.</param>
49+
/// <typeparam name="T">Type of <see cref="Component"/> to get from the scene</typeparam>
50+
/// <returns>a generator that yields successive NetworkObjects in the current scene</returns>
51+
public static IEnumerable<T> FromSceneByType<T>(Scene scene, bool includeInactive) where T : UnityEngine.Component
52+
{
53+
return new ObjectsInSceneEnumerator<T>(scene, includeInactive);
54+
}
55+
56+
/// <summary>
57+
/// An Enumerator that enumerates over each component of type <see cref="T"/> in the given scene.
58+
/// </summary>
59+
/// <typeparam name="T">Type of <see cref="Component"/> to get from the scene</typeparam>
60+
private struct ObjectsInSceneEnumerator<T> : IEnumerable<T>, IEnumerator<T> where T : UnityEngine.Component
61+
{
62+
private readonly UnityEngine.GameObject[] m_RootObjects;
63+
private int m_RootIndex;
64+
private T[] m_CurrentChildObjects;
65+
private int m_CurrentChildIndex;
66+
67+
private readonly bool m_IncludeInactive;
68+
69+
internal ObjectsInSceneEnumerator(Scene scene, bool includeInactive)
70+
{
71+
m_IncludeInactive = includeInactive;
72+
73+
m_RootObjects = scene.GetRootGameObjects();
74+
m_RootIndex = 0;
75+
m_CurrentChildObjects = null;
76+
m_CurrentChildIndex = 0;
77+
Current = null;
78+
}
79+
80+
public void Dispose() { }
81+
82+
public bool MoveNext()
83+
{
84+
while (m_CurrentChildObjects == null && m_RootIndex < m_RootObjects.Length)
85+
{
86+
m_CurrentChildObjects = m_RootObjects[m_RootIndex].GetComponentsInChildren<T>(m_IncludeInactive);
87+
m_RootIndex++;
88+
89+
if (m_CurrentChildObjects.Length == 0)
90+
{
91+
m_CurrentChildObjects = null;
92+
}
93+
}
94+
95+
if (m_CurrentChildObjects != null && m_CurrentChildIndex < m_CurrentChildObjects.Length)
96+
{
97+
Current = m_CurrentChildObjects[m_CurrentChildIndex];
98+
m_CurrentChildIndex++;
99+
100+
if (m_CurrentChildIndex >= m_CurrentChildObjects.Length)
101+
{
102+
m_CurrentChildIndex = 0;
103+
m_CurrentChildObjects = null;
104+
}
105+
return true;
106+
}
107+
108+
Current = null;
109+
return false;
110+
}
111+
112+
public void Reset()
113+
{
114+
m_RootIndex = 0;
115+
m_CurrentChildObjects = null;
116+
m_CurrentChildIndex = 0;
117+
Current = null;
118+
}
119+
120+
object IEnumerator.Current => Current;
121+
122+
public T Current { get; private set; }
123+
124+
public IEnumerator<T> GetEnumerator() => this;
125+
126+
IEnumerator IEnumerable.GetEnumerator() => this;
127+
}
42128
}
43129
}

com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1644,7 +1644,7 @@ internal void ShutdownInternal()
16441644
// place (i.e. sending any last state updates or the like).
16451645

16461646
SpawnManager?.DespawnAndDestroyNetworkObjects();
1647-
SpawnManager?.ServerResetShudownStateForSceneObjects();
1647+
SpawnManager?.ServerResetShutdownStateForSceneObjects();
16481648
////
16491649

16501650
RpcTarget?.Dispose();

com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ internal void OnValidate()
291291
if (GlobalObjectIdHash != oldValue)
292292
{
293293
// Check if this is an in-scnee placed NetworkObject (Special Case for In-Scene Placed).
294-
if (IsSceneObject.HasValue && IsSceneObject.Value)
294+
if (InScenePlaced)
295295
{
296296
// Sanity check to make sure this is a scene placed object.
297297
if (globalId.identifierType != k_SceneObjectType)
@@ -340,7 +340,12 @@ private void CheckForInScenePlaced()
340340
EditorUtility.SetDirty(this);
341341
}
342342
}
343-
IsSceneObject = true;
343+
344+
#pragma warning disable CS0618 // Type or member is obsolete
345+
// Obsolete with warning means we need the underlying behaviour to keep existing
346+
// TODO-3.x: remove in the 3.x branch
347+
SetSceneObjectStatus(true);
348+
#pragma warning restore CS0618 // Type or member is obsolete
344349

345350
// Default scene migration synchronization to false for in-scene placed NetworkObjects
346351
SceneMigrationSynchronization = false;
@@ -1225,15 +1230,24 @@ private bool InternalHasAuthority()
12251230
public bool IsSpawned { get; internal set; }
12261231

12271232
/// <summary>
1228-
/// Gets if the object is a SceneObject, null if it's not yet spawned but is a scene object.
1233+
/// Gets if the object is a SceneObject.
12291234
/// </summary>
1235+
[Obsolete("Use InScenePlaced instead")]
12301236
public bool? IsSceneObject { get; internal set; }
12311237

1232-
//DANGOEXP TODO: Determine if we want to keep this
1238+
/// <summary>
1239+
/// True if this object is placed in a scene; false otherwise.
1240+
/// </summary>
1241+
[field: HideInInspector]
1242+
[field: SerializeField]
1243+
public bool InScenePlaced { get; internal set; }
1244+
12331245
/// <summary>
12341246
/// Sets whether this NetworkObject was instantiated as part of a scene
12351247
/// </summary>
1248+
/// <remarks>Only use this when using custom scene loading</remarks>
12361249
/// <param name="isSceneObject">When true, marks this as a scene-instantiated object; when false, marks it as runtime-instantiated</param>
1250+
[Obsolete("SetSceneObjectStatus is now calculated during the build.")]
12371251
public void SetSceneObjectStatus(bool isSceneObject = false)
12381252
{
12391253
IsSceneObject = isSceneObject;
@@ -1457,7 +1471,7 @@ internal Scene SceneOrigin
14571471
/// </summary>
14581472
internal NetworkSceneHandle GetSceneOriginHandle()
14591473
{
1460-
if (SceneOriginHandle.IsEmpty() && IsSpawned && IsSceneObject != false)
1474+
if (SceneOriginHandle.IsEmpty() && IsSpawned && InScenePlaced)
14611475
{
14621476
if (NetworkManager.LogLevel <= LogLevel.Error)
14631477
{
@@ -1622,7 +1636,7 @@ public void NetworkHide(ulong clientId)
16221636
var message = new DestroyObjectMessage
16231637
{
16241638
NetworkObjectId = NetworkObjectId,
1625-
DestroyGameObject = !IsSceneObject.Value,
1639+
DestroyGameObject = !InScenePlaced,
16261640
IsDistributedAuthority = NetworkManagerOwner.DistributedAuthorityMode,
16271641
IsTargetedDestroy = NetworkManagerOwner.DistributedAuthorityMode,
16281642
TargetClientId = clientId, // Just always populate this value whether we write it or not
@@ -1750,7 +1764,7 @@ private void OnDestroy()
17501764
var isStillValid = gameObject != null && gameObject.scene.IsValid() && gameObject.scene.isLoaded;
17511765

17521766
// If we're not the authority and everything is valid and dynamically spawned, then the destroy is not valid.
1753-
if (!isAuthorityDestroy && IsSceneObject == false && isStillValid)
1767+
if (!isAuthorityDestroy && !InScenePlaced && isStillValid)
17541768
{
17551769
if (networkManager.LogLevel <= LogLevel.Error)
17561770
{
@@ -1849,7 +1863,7 @@ internal void SpawnInternal(bool destroyWithScene, ulong ownerClientId, bool pla
18491863
}
18501864
}
18511865

1852-
if (!NetworkManagerOwner.SpawnManager.AuthorityLocalSpawn(this, NetworkManagerOwner.SpawnManager.GetNetworkObjectId(), IsSceneObject.HasValue && IsSceneObject.Value, playerObject, ownerClientId, destroyWithScene))
1866+
if (!NetworkManagerOwner.SpawnManager.AuthorityLocalSpawn(this, NetworkManagerOwner.SpawnManager.GetNetworkObjectId(), InScenePlaced, playerObject, ownerClientId, destroyWithScene))
18531867
{
18541868
if (NetworkManagerOwner.LogLevel <= LogLevel.Normal)
18551869
{
@@ -2528,8 +2542,7 @@ internal bool ApplyNetworkParenting(bool removeParent = false, bool ignoreNotSpa
25282542
// Handle the first in-scene placed NetworkObject parenting scenarios. Once the m_LatestParent
25292543
// has been set, this will not be entered into again (i.e. the later code will be invoked and
25302544
// users will get notifications when the parent changes).
2531-
var isInScenePlaced = IsSceneObject.HasValue && IsSceneObject.Value;
2532-
if (transform.parent != null && !removeParent && !m_LatestParent.HasValue && isInScenePlaced)
2545+
if (transform.parent != null && !removeParent && !m_LatestParent.HasValue && InScenePlaced)
25332546
{
25342547
var parentNetworkObject = transform.parent.GetComponent<NetworkObject>();
25352548

@@ -3271,7 +3284,7 @@ internal SerializedObject Serialize(ulong targetClientId = NetworkManager.Server
32713284
NetworkObjectId = NetworkObjectId,
32723285
OwnerClientId = OwnerClientId,
32733286
IsPlayerObject = IsPlayerObject,
3274-
IsSceneObject = IsSceneObject ?? true,
3287+
IsSceneObject = InScenePlaced,
32753288
DestroyWithScene = DestroyWithScene,
32763289
DontDestroyWithOwner = DontDestroyWithOwner,
32773290
HasOwnershipFlags = NetworkManagerOwner.DistributedAuthorityMode,
@@ -3456,7 +3469,7 @@ internal void SubscribeToActiveSceneForSynch()
34563469
{
34573470
if (ActiveSceneSynchronization)
34583471
{
3459-
if (IsSceneObject.HasValue && !IsSceneObject.Value)
3472+
if (!InScenePlaced)
34603473
{
34613474
// Just in case it is a recycled NetworkObject, unsubscribe first
34623475
SceneManager.activeSceneChanged -= CurrentlyActiveSceneChanged;
@@ -3473,7 +3486,7 @@ private void CurrentlyActiveSceneChanged(Scene current, Scene next)
34733486
{
34743487
// Early exit if the NetworkObject is not spawned, is an in-scene placed NetworkObject,
34753488
// or the NetworkManager is shutting down.
3476-
if (!IsSpawned || IsSceneObject != false || NetworkManagerOwner.ShutdownInProgress)
3489+
if (!IsSpawned || NetworkManagerOwner.ShutdownInProgress || InScenePlaced)
34773490
{
34783491
return;
34793492
}
@@ -3483,7 +3496,7 @@ private void CurrentlyActiveSceneChanged(Scene current, Scene next)
34833496
{
34843497
// Only dynamically spawned NetworkObjects that are not already in the newly assigned active scene will migrate
34853498
// and update their scene handles
3486-
if (IsSceneObject.HasValue && !IsSceneObject.Value && gameObject.scene != next && gameObject.transform.parent == null)
3499+
if (gameObject.scene != next && gameObject.transform.parent == null)
34873500
{
34883501
SceneManager.MoveGameObjectToScene(gameObject, next);
34893502
SceneChangedUpdate(next);
@@ -3571,7 +3584,7 @@ internal bool UpdateForSceneChanges()
35713584
// the NetworkManager is shutting down, the NetworkObject is not spawned, it is an in-scene placed
35723585
// NetworkObject, or the GameObject's current scene handle is the same as the SceneOriginHandle
35733586
if (!SceneMigrationSynchronization || !IsSpawned || NetworkManagerOwner.ShutdownInProgress ||
3574-
!NetworkManagerOwner.NetworkConfig.EnableSceneManagement || IsSceneObject != false || !gameObject)
3587+
!NetworkManagerOwner.NetworkConfig.EnableSceneManagement || InScenePlaced || !gameObject)
35753588
{
35763589
// Stop checking for a scene migration
35773590
return false;
@@ -3606,15 +3619,15 @@ internal uint CheckForGlobalObjectIdHashOverride()
36063619

36073620
// If scene management is disabled and this is an in-scene placed NetworkObject then go ahead
36083621
// and send the InScenePlacedSourcePrefab's GlobalObjectIdHash value (i.e. what to dynamically spawn)
3609-
if (!networkManager.NetworkConfig.EnableSceneManagement && IsSceneObject.Value && InScenePlacedSourceGlobalObjectIdHash != 0)
3622+
if (!networkManager.NetworkConfig.EnableSceneManagement && InScenePlaced && InScenePlacedSourceGlobalObjectIdHash != 0)
36103623
{
36113624
return InScenePlacedSourceGlobalObjectIdHash;
36123625
}
36133626

36143627
// If the PrefabGlobalObjectIdHash is a non-zero value and the GlobalObjectIdHash value is
36153628
// different from the PrefabGlobalObjectIdHash value, then the NetworkObject instance is
36163629
// an override for the original network prefab (i.e. PrefabGlobalObjectIdHash)
3617-
if (!IsSceneObject.Value && GlobalObjectIdHash != PrefabGlobalObjectIdHash)
3630+
if (!InScenePlaced && GlobalObjectIdHash != PrefabGlobalObjectIdHash)
36183631
{
36193632
// If the PrefabGlobalObjectIdHash is already populated (i.e. InstantiateAndSpawn used), then return this
36203633
if (PrefabGlobalObjectIdHash != 0)

0 commit comments

Comments
 (0)