Skip to content

Commit cab1983

Browse files
refactor
Using RPCs and synchronizing the property being set using NetworkBehaviour.OnSynchronize in order to assure order of operations when it comes to messages. Updated the ComponentController to be able to stagger state updates in the event this occurs (wip and I might remove this part and not allow changes to state until any pending state is finished).
1 parent e098e31 commit cab1983

File tree

2 files changed

+195
-103
lines changed

2 files changed

+195
-103
lines changed

com.unity.netcode.gameobjects/Runtime/Components/Helpers/AttachableBehaviour.cs

Lines changed: 55 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,26 @@ public enum AttachState
116116
/// </summary>
117117
protected AttachableNode m_AttachableNode { get; private set; }
118118

119-
private NetworkVariable<NetworkBehaviourReference> m_AttachedNodeReference = new NetworkVariable<NetworkBehaviourReference>(new NetworkBehaviourReference(null));
119+
private NetworkBehaviourReference m_AttachedNodeReference = new NetworkBehaviourReference(null);
120120
private Vector3 m_OriginalLocalPosition;
121121
private Quaternion m_OriginalLocalRotation;
122122

123+
/// <inheritdoc/>
124+
protected override void OnSynchronize<T>(ref BufferSerializer<T> serializer)
125+
{
126+
// Example of how to synchronize late joining clients when using an RPC to update
127+
// a local property's state.
128+
if (serializer.IsWriter)
129+
{
130+
serializer.SerializeValue(ref m_AttachedNodeReference);
131+
}
132+
else
133+
{
134+
serializer.SerializeValue(ref m_AttachedNodeReference);
135+
}
136+
base.OnSynchronize(ref serializer);
137+
}
138+
123139
/// <summary>
124140
/// If you create a custom <see cref="AttachableBehaviour"/> and override this method, you must invoke
125141
/// this base instance of <see cref="Awake"/>.
@@ -133,21 +149,6 @@ protected virtual void Awake()
133149
m_AttachableNode = null;
134150
}
135151

136-
/// <inheritdoc/>
137-
/// <remarks>
138-
/// If you create a custom <see cref="AttachableBehaviour"/> and override this method, you must invoke
139-
/// this base instance of <see cref="OnNetworkPostSpawn"/>.
140-
/// </remarks>
141-
protected override void OnNetworkPostSpawn()
142-
{
143-
if (HasAuthority)
144-
{
145-
m_AttachedNodeReference.Value = new NetworkBehaviourReference(null);
146-
}
147-
m_AttachedNodeReference.OnValueChanged += OnAttachedNodeReferenceChanged;
148-
base.OnNetworkPostSpawn();
149-
}
150-
151152
/// <inheritdoc/>
152153
/// <remarks>
153154
/// If you create a custom <see cref="AttachableBehaviour"/> and override this method, you will want to
@@ -164,25 +165,20 @@ protected override void OnNetworkSessionSynchronized()
164165
/// <inheritdoc/>
165166
public override void OnNetworkDespawn()
166167
{
167-
m_AttachedNodeReference.OnValueChanged -= OnAttachedNodeReferenceChanged;
168168
InternalDetach();
169169
if (NetworkManager && !NetworkManager.ShutdownInProgress)
170170
{
171171
// Notify of the changed attached state
172172
UpdateAttachState(m_AttachState, m_AttachableNode);
173173
}
174+
m_AttachedNodeReference = new NetworkBehaviourReference(null);
174175
base.OnNetworkDespawn();
175176
}
176177

177-
private void OnAttachedNodeReferenceChanged(NetworkBehaviourReference previous, NetworkBehaviourReference current)
178-
{
179-
UpdateAttachedState();
180-
}
181-
182178
private void UpdateAttachedState()
183179
{
184180
var attachableNode = (AttachableNode)null;
185-
var shouldParent = m_AttachedNodeReference.Value.TryGet(out attachableNode, NetworkManager);
181+
var shouldParent = m_AttachedNodeReference.TryGet(out attachableNode, NetworkManager);
186182
var preState = shouldParent ? AttachState.Attaching : AttachState.Detaching;
187183
var preNode = shouldParent ? attachableNode : m_AttachableNode;
188184
shouldParent = shouldParent && attachableNode != null;
@@ -310,8 +306,7 @@ public void Attach(AttachableNode attachableNode)
310306
return;
311307
}
312308

313-
// Update the attached node reference to the new attachable node.
314-
m_AttachedNodeReference.Value = new NetworkBehaviourReference(attachableNode);
309+
ChangeReference(new NetworkBehaviourReference(attachableNode));
315310
}
316311

317312
/// <summary>
@@ -344,7 +339,7 @@ public void Detach()
344339
return;
345340
}
346341

347-
if (!HasAuthority)
342+
if (!OnHasAuthority())
348343
{
349344
NetworkLog.LogError($"[{name}][Detach][Not Authority] Client-{NetworkManager.LocalClientId} is not the authority!");
350345
return;
@@ -373,8 +368,40 @@ public void Detach()
373368
return;
374369
}
375370

376-
// Update the attached node reference to nothing-null.
377-
m_AttachedNodeReference.Value = new NetworkBehaviourReference(null);
371+
ChangeReference(new NetworkBehaviourReference(null));
372+
}
373+
374+
/// <summary>
375+
/// Override this method to change how the instance determines the authority.<br />
376+
/// The default is to use the <see cref="NetworkObject.HasAuthority"/> method.
377+
/// </summary>
378+
/// <remarks>
379+
/// Useful when using a <see cref="NetworkTopologyTypes.ClientServer"/> network topology and you would like
380+
/// to have the owner be the authority of this <see cref="ComponentController"/> instance.
381+
/// </remarks>
382+
/// <returns>true = has authoriy | false = does not have authority</returns>
383+
protected virtual bool OnHasAuthority()
384+
{
385+
return HasAuthority;
386+
}
387+
388+
private void ChangeReference(NetworkBehaviourReference networkBehaviourReference)
389+
{
390+
// Update the attached node reference to the new attachable node.
391+
m_AttachedNodeReference = networkBehaviourReference;
392+
UpdateAttachedState();
393+
394+
if (OnHasAuthority())
395+
{
396+
// Send notification of the change in this property's state.
397+
UpdateAttachStateRpc(m_AttachedNodeReference);
398+
}
399+
}
400+
401+
[Rpc(SendTo.NotMe)]
402+
private void UpdateAttachStateRpc(NetworkBehaviourReference attachedNodeReference)
403+
{
404+
ChangeReference(attachedNodeReference);
378405
}
379406
}
380407
}

0 commit comments

Comments
 (0)