Skip to content

Commit edf73f6

Browse files
update
Bringing over the SyncOwnerTransformWhenParented and AllowOwnerToParent functionality.
1 parent 906f202 commit edf73f6

File tree

4 files changed

+306
-13
lines changed

4 files changed

+306
-13
lines changed

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

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,24 @@ private GlobalObjectId GetGlobalId()
417417
/// </summary>
418418
public bool AutoObjectParentSync = true;
419419

420+
/// <summary>
421+
/// Determines if the owner will apply transform values sent by the parenting message.
422+
/// </summary>
423+
/// <remarks>
424+
/// When enabled, the resultant parenting transform changes sent by the authority will be applied on all instances. <br />
425+
/// When disabled, the resultant parenting transform changes sent by the authority will not be applied on the owner's instance. <br />
426+
/// When disabled, all non-owner instances will still be synchronized by the authority's transform values when parented.
427+
/// </remarks>
428+
[Tooltip("When disabled (default enabled), the owner will not apply a server or host's transform properties when parenting changes. Primarily useful for client-server network topology configurations.")]
429+
public bool SyncOwnerTransformWhenParented = true;
430+
431+
/// <summary>
432+
/// Client-Server specific, when enabled an owner of a NetworkObject can parent locally as opposed to requiring the owner to notify the server it would like to be parented.
433+
/// This behavior is always true when using a distributed authority network topology and does not require it to be set.
434+
/// </summary>
435+
[Tooltip("When enabled (default disabled), owner's can parent a NetworkObject locally without having to send an RPC to the server or host. Only pertinent when using client-server network topology configurations.")]
436+
public bool AllowOwnerToParent;
437+
420438
internal readonly HashSet<ulong> Observers = new HashSet<ulong>();
421439

422440
#if MULTIPLAYER_TOOLS
@@ -1086,8 +1104,9 @@ public bool TrySetParent(NetworkObject parent, bool worldPositionStays = true)
10861104
{
10871105
return false;
10881106
}
1089-
1090-
if (!NetworkManager.IsServer && !NetworkManager.ShutdownInProgress)
1107+
// If we don't have authority and we are not shutting down, then don't allow any parenting.
1108+
// If we are shutting down and don't have authority then allow it.
1109+
if (!(NetworkManager.IsServer || (AllowOwnerToParent && IsOwner)) && !NetworkManager.ShutdownInProgress)
10911110
{
10921111
return false;
10931112
}
@@ -1102,6 +1121,8 @@ public bool TrySetParent(NetworkObject parent, bool worldPositionStays = true)
11021121
return false;
11031122
}
11041123

1124+
1125+
11051126
m_CachedWorldPositionStays = worldPositionStays;
11061127

11071128
if (parent == null)
@@ -1135,7 +1156,9 @@ private void OnTransformParentChanged()
11351156
return;
11361157
}
11371158

1138-
if (!NetworkManager.IsServer)
1159+
var hasAuthority = NetworkManager.IsServer || (AllowOwnerToParent && IsOwner);
1160+
1161+
if (!hasAuthority)
11391162
{
11401163
// Log exception if we are a client and not shutting down.
11411164
if (!NetworkManager.ShutdownInProgress)

com.unity.netcode.gameobjects/Runtime/Messaging/Messages/ParentSyncMessage.cs

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,19 +106,42 @@ public void Handle(ref NetworkContext context)
106106
networkObject.SetNetworkParenting(LatestParent, WorldPositionStays);
107107
networkObject.ApplyNetworkParenting(RemoveParent);
108108

109-
// We set all of the transform values after parenting as they are
110-
// the values of the server-side post-parenting transform values
111-
if (!WorldPositionStays)
109+
110+
// This check is primarily for client-server network topologies when the motion model is owner authoritative:
111+
// When SyncOwnerTransformWhenParented is enabled, then always apply the transform values.
112+
// When SyncOwnerTransformWhenParented is disabled, then only synchronize the transform on non-owner instances.
113+
if (networkObject.SyncOwnerTransformWhenParented || (!networkObject.SyncOwnerTransformWhenParented && !networkObject.IsOwner))
112114
{
113-
networkObject.transform.localPosition = Position;
114-
networkObject.transform.localRotation = Rotation;
115+
// We set all of the transform values after parenting as they are
116+
// the values of the server-side post-parenting transform values
117+
if (!WorldPositionStays)
118+
{
119+
networkObject.transform.localPosition = Position;
120+
networkObject.transform.localRotation = Rotation;
121+
}
122+
else
123+
{
124+
networkObject.transform.position = Position;
125+
networkObject.transform.rotation = Rotation;
126+
}
115127
}
116-
else
128+
networkObject.transform.localScale = Scale;
129+
130+
// If client side parenting is enabled and this is the server instance, then notify the rest of the connected clients that parenting has taken place.
131+
if (networkObject.AllowOwnerToParent && context.SenderId == networkObject.OwnerClientId && networkManager.IsServer)
117132
{
118-
networkObject.transform.position = Position;
119-
networkObject.transform.rotation = Rotation;
133+
var size = 0;
134+
var message = this;
135+
foreach (var client in networkManager.ConnectedClients)
136+
{
137+
if (client.Value.ClientId == networkObject.OwnerClientId || client.Value.ClientId == networkManager.LocalClientId || !networkObject.IsNetworkVisibleTo(client.Value.ClientId))
138+
{
139+
continue;
140+
}
141+
size = networkManager.ConnectionManager.SendMessage(ref message, NetworkDelivery.ReliableSequenced, client.Value.ClientId);
142+
networkManager.NetworkMetrics.TrackOwnershipChangeSent(client.Key, networkObject, size);
143+
}
120144
}
121-
networkObject.transform.localScale = Scale;
122145
}
123146
}
124147
}

com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformBase.cs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,6 @@ protected override void OnNewClientCreated(NetworkManager networkManager)
347347
base.OnNewClientCreated(networkManager);
348348
}
349349

350-
351350
/// <summary>
352351
/// Returns true when the server-host and all clients have
353352
/// instantiated the child object to be used in <see cref="NetworkTransformParentingLocalSpaceOffsetTests"/>
@@ -378,6 +377,18 @@ protected bool AllChildObjectInstancesAreSpawned()
378377
return true;
379378
}
380379

380+
protected bool AllFirstLevelChildObjectInstancesHaveChild()
381+
{
382+
foreach (var instance in ChildObjectComponent.ClientInstances.Values)
383+
{
384+
if (instance.transform.parent == null)
385+
{
386+
return false;
387+
}
388+
}
389+
return true;
390+
}
391+
381392
protected bool AllChildObjectInstancesHaveChild()
382393
{
383394
foreach (var instance in ChildObjectComponent.ClientInstances.Values)
@@ -400,6 +411,33 @@ protected bool AllChildObjectInstancesHaveChild()
400411
return true;
401412
}
402413

414+
protected bool AllFirstLevelChildObjectInstancesHaveNoParent()
415+
{
416+
foreach (var instance in ChildObjectComponent.ClientInstances.Values)
417+
{
418+
if (instance.transform.parent != null)
419+
{
420+
return false;
421+
}
422+
}
423+
return true;
424+
}
425+
426+
protected bool AllSubChildObjectInstancesHaveNoParent()
427+
{
428+
if (ChildObjectComponent.HasSubChild)
429+
{
430+
foreach (var instance in ChildObjectComponent.ClientSubChildInstances.Values)
431+
{
432+
if (instance.transform.parent != null)
433+
{
434+
return false;
435+
}
436+
}
437+
}
438+
return true;
439+
}
440+
403441
/// <summary>
404442
/// A wait condition specific method that assures the local space coordinates
405443
/// are not impacted by NetworkTransform when parented.

0 commit comments

Comments
 (0)