Skip to content

Commit bb21bd1

Browse files
update
Cleaned up two areas for in-scene placed NetworkObject parenting after having a good paired programming session with Emma.
1 parent d31724f commit bb21bd1

File tree

3 files changed

+32
-46
lines changed

3 files changed

+32
-46
lines changed

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

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2316,7 +2316,7 @@ private void OnTransformParentChanged()
23162316
// we call CheckOrphanChildren() method and quickly iterate over OrphanChildren set and see if we can reparent/adopt one.
23172317
internal static HashSet<NetworkObject> OrphanChildren = new HashSet<NetworkObject>();
23182318

2319-
internal bool ApplyNetworkParenting(bool removeParent = false, bool ignoreNotSpawned = false, bool orphanedChildPass = false, bool silentParenting = false)
2319+
internal bool ApplyNetworkParenting(bool removeParent = false, bool ignoreNotSpawned = false, bool orphanedChildPass = false, bool enableNotification = true)
23202320
{
23212321
if (!AutoObjectParentSync)
23222322
{
@@ -2389,7 +2389,7 @@ internal bool ApplyNetworkParenting(bool removeParent = false, bool ignoreNotSpa
23892389
// to WorldPositionStays which can cause scaling issues if the parent's
23902390
// scale is not the default (Vetctor3.one) value.
23912391
transform.SetParent(null, m_CachedWorldPositionStays);
2392-
if (!silentParenting)
2392+
if (enableNotification)
23932393
{
23942394
InvokeBehaviourOnNetworkObjectParentChanged(null);
23952395
}
@@ -2417,7 +2417,7 @@ internal bool ApplyNetworkParenting(bool removeParent = false, bool ignoreNotSpa
24172417
}
24182418
SetCachedParent(parentObject.transform);
24192419
transform.SetParent(parentObject.transform, m_CachedWorldPositionStays);
2420-
if (!silentParenting)
2420+
if (enableNotification)
24212421
{
24222422
InvokeBehaviourOnNetworkObjectParentChanged(parentObject);
24232423
}
@@ -3057,6 +3057,8 @@ internal SceneObject GetMessageSceneObject(ulong targetClientId = NetworkManager
30573057
{
30583058
var obj = new SceneObject
30593059
{
3060+
HasParent = transform.parent != null,
3061+
WorldPositionStays = m_CachedWorldPositionStays,
30603062
NetworkObjectId = NetworkObjectId,
30613063
OwnerClientId = OwnerClientId,
30623064
IsPlayerObject = IsPlayerObject,
@@ -3073,31 +3075,16 @@ internal SceneObject GetMessageSceneObject(ulong targetClientId = NetworkManager
30733075
TargetClientId = targetClientId
30743076
};
30753077

3076-
NetworkObject parentNetworkObject = null;
3077-
3078-
if (!AlwaysReplicateAsRoot && transform.parent != null)
3078+
// Handle Parenting
3079+
if (!AlwaysReplicateAsRoot && obj.HasParent)
30793080
{
3080-
parentNetworkObject = transform.parent.GetComponent<NetworkObject>();
3081-
// In-scene placed NetworkObjects parented under GameObjects with no NetworkObject
3082-
// should set the has parent flag and preserve the world position stays value
3083-
if (parentNetworkObject == null && obj.IsSceneObject)
3084-
{
3085-
obj.HasParent = true;
3086-
obj.WorldPositionStays = m_CachedWorldPositionStays;
3087-
}
3088-
}
3081+
var parentNetworkObject = transform.parent.GetComponent<NetworkObject>();
30893082

3090-
if (parentNetworkObject != null)
3091-
{
3092-
obj.HasParent = true;
3093-
obj.ParentObjectId = parentNetworkObject.NetworkObjectId;
3094-
obj.WorldPositionStays = m_CachedWorldPositionStays;
3095-
var latestParent = GetNetworkParenting();
3096-
var isLatestParentSet = latestParent != null && latestParent.HasValue;
3097-
obj.IsLatestParentSet = isLatestParentSet;
3098-
if (isLatestParentSet)
3083+
if (parentNetworkObject)
30993084
{
3100-
obj.LatestParent = latestParent.Value;
3085+
obj.ParentObjectId = parentNetworkObject.NetworkObjectId;
3086+
obj.LatestParent = GetNetworkParenting();
3087+
obj.IsLatestParentSet = obj.LatestParent != null && obj.LatestParent.HasValue;
31013088
}
31023089
}
31033090

@@ -3186,7 +3173,6 @@ internal static NetworkObject AddSceneObject(in SceneObject sceneObject, FastBuf
31863173
// Synchronize NetworkBehaviours
31873174
var bufferSerializer = new BufferSerializer<BufferSerializerReader>(new BufferSerializerReader(reader));
31883175
networkObject.SynchronizeNetworkBehaviours(ref bufferSerializer, networkManager.LocalClientId);
3189-
Debug.Log($"Spawning {networkObject.name}");
31903176

31913177
// If we are an in-scene placed NetworkObject and we originally had a parent but when synchronized we are
31923178
// being told we do not have a parent, then we want to clear the latest parent so it is not automatically

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,7 @@ internal void SerializeScenePlacedObjects(FastBufferWriter writer)
695695
SortObjectsToSync();
696696

697697
// Serialize the sorted objects to sync.
698-
foreach(var objectToSycn in m_NetworkObjectsSync)
698+
foreach (var objectToSycn in m_NetworkObjectsSync)
699699
{
700700
// Serialize the NetworkObject
701701
var sceneObject = objectToSycn.GetMessageSceneObject(TargetClientId, distributedAuthority);

com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,6 @@ internal NetworkObject CreateLocalNetworkObject(NetworkObject.SceneObject sceneO
884884
var scale = sceneObject.HasTransform ? sceneObject.Transform.Scale : default;
885885
var parentNetworkId = sceneObject.HasParent ? sceneObject.ParentObjectId : default;
886886
var worldPositionStays = (!sceneObject.HasParent) || sceneObject.WorldPositionStays;
887-
var isSpawnedByPrefabHandler = false;
888887

889888
// If scene management is disabled or the NetworkObject was dynamically spawned
890889
if (!NetworkManager.NetworkConfig.EnableSceneManagement || !sceneObject.IsSceneObject)
@@ -917,7 +916,6 @@ internal NetworkObject CreateLocalNetworkObject(NetworkObject.SceneObject sceneO
917916
networkObject.DontDestroyWithOwner = sceneObject.DontDestroyWithOwner;
918917
networkObject.Ownership = (NetworkObject.OwnershipStatus)sceneObject.OwnershipFlags;
919918

920-
921919
var nonNetworkObjectParent = false;
922920
// SPECIAL CASE FOR IN-SCENE PLACED: (only when the parent has a NetworkObject)
923921
// This is a special case scenario where a late joining client has joined and loaded one or
@@ -929,31 +927,34 @@ internal NetworkObject CreateLocalNetworkObject(NetworkObject.SceneObject sceneO
929927
if (sceneObject.IsSceneObject && networkObject.transform.parent != null)
930928
{
931929
var parentNetworkObject = networkObject.transform.parent.GetComponent<NetworkObject>();
930+
931+
// special case to handle being parented under a GameObject with no NetworkObject
932+
nonNetworkObjectParent = !parentNetworkObject && !sceneObject.HasParent;
933+
932934
// if the in-scene placed NetworkObject has a parent NetworkObject but the synchronization information does not
933935
// include parenting, then we need to force the removal of that parent (i.e. it is at the root)
934-
if (!sceneObject.HasParent && parentNetworkObject)
935-
{
936-
// remove the parent
937-
networkObject.ApplyNetworkParenting(true, true);
938-
}
939-
else // If we are parented and our latest parent known is not the parent =or= we are keeping world space values when parenting.
940-
if (parentNetworkObject && sceneObject.HasParent && sceneObject.LatestParent.HasValue
941-
&& (sceneObject.LatestParent.Value != parentNetworkObject.NetworkObjectId || sceneObject.WorldPositionStays))
936+
if (parentNetworkObject)
942937
{
943-
// remove the parent silently so we can re-parent an in-scene placed NetworkObject
944-
networkObject.ApplyNetworkParenting(true, true, silentParenting: true);
945-
}
946-
else // special case to handle being parented under a GameObject with no NetworkObject
947-
if (sceneObject.HasParent && !parentNetworkObject)
948-
{
949-
nonNetworkObjectParent = true;
938+
// Remove the parent if:
939+
// - The authority says we don't have a parent (but locally we do).
940+
// - The auhtority says we have a parent but either of the two are true:
941+
// -- It isn't the same parent.
942+
// -- It was parented using world position stays.
943+
var removeParent = !sceneObject.HasParent || (sceneObject.IsLatestParentSet
944+
&& (sceneObject.LatestParent.Value != parentNetworkObject.NetworkObjectId || sceneObject.WorldPositionStays));
945+
if (removeParent)
946+
{
947+
// If parenting without notifications then we are temporarily removing the parent to set the transform
948+
// values before reparenting under the current parent.
949+
networkObject.ApplyNetworkParenting(true, true, enableNotification: !sceneObject.HasParent);
950+
}
950951
}
951952
}
952953

953954
// Set the transform unless we were spawned by a prefab handler
954955
// Note: prefab handlers are provided the position and rotation
955956
// but it is up to the user to set those values
956-
if (sceneObject.HasTransform && !isSpawnedByPrefabHandler)
957+
if (sceneObject.HasTransform)
957958
{
958959
// If world position stays is true or we have auto object parent synchronization disabled
959960
// then we want to apply the position and rotation values world space relative
@@ -996,7 +997,6 @@ internal NetworkObject CreateLocalNetworkObject(NetworkObject.SceneObject sceneO
996997
networkObject.SetNetworkParenting(parentId, worldPositionStays);
997998
}
998999

999-
10001000
// Dynamically spawned NetworkObjects that occur during a LoadSceneMode.Single load scene event are migrated into the DDOL
10011001
// until the scene is loaded. They are then migrated back into the newly loaded and currently active scene.
10021002
if (!sceneObject.IsSceneObject && NetworkSceneManager.IsSpawnedObjectsPendingInDontDestroyOnLoad)

0 commit comments

Comments
 (0)