Skip to content

Commit 6f87b1d

Browse files
refactor
Include any pending dirty NetworkVariable updates just prior to sending the Show/CreateObjectMessage.
1 parent d71ebca commit 6f87b1d

File tree

3 files changed

+127
-55
lines changed

3 files changed

+127
-55
lines changed

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

Lines changed: 116 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Generic;
2+
using System.Runtime.CompilerServices;
23
using Unity.Profiling;
34

45
namespace Unity.Netcode
@@ -23,6 +24,115 @@ internal void AddForUpdate(NetworkObject networkObject)
2324
m_PendingDirtyNetworkObjects.Add(networkObject);
2425
}
2526

27+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
28+
internal bool ProcessDirtyObjectServer(NetworkObject dirtyObj, bool forceSend)
29+
{
30+
var sentMessages = false;
31+
for (int k = 0; k < dirtyObj.ChildNetworkBehaviours.Count; k++)
32+
{
33+
dirtyObj.ChildNetworkBehaviours[k].PreVariableUpdate();
34+
}
35+
36+
for (int i = 0; i < m_ConnectionManager.ConnectedClientsList.Count; i++)
37+
{
38+
var client = m_ConnectionManager.ConnectedClientsList[i];
39+
if (m_NetworkManager.DistributedAuthorityMode || dirtyObj.IsNetworkVisibleTo(client.ClientId))
40+
{
41+
// Sync just the variables for just the objects this client sees
42+
for (int k = 0; k < dirtyObj.ChildNetworkBehaviours.Count; k++)
43+
{
44+
dirtyObj.ChildNetworkBehaviours[k].NetworkVariableUpdate(client.ClientId, forceSend);
45+
sentMessages = true;
46+
}
47+
}
48+
}
49+
return sentMessages;
50+
}
51+
52+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
53+
internal bool ProcessDirtyObjectClient(NetworkObject dirtyObj, bool forceSend)
54+
{
55+
var sentMessages = false;
56+
if (dirtyObj.IsOwner)
57+
{
58+
for (int k = 0; k < dirtyObj.ChildNetworkBehaviours.Count; k++)
59+
{
60+
dirtyObj.ChildNetworkBehaviours[k].PreVariableUpdate();
61+
}
62+
for (int k = 0; k < dirtyObj.ChildNetworkBehaviours.Count; k++)
63+
{
64+
dirtyObj.ChildNetworkBehaviours[k].NetworkVariableUpdate(NetworkManager.ServerClientId, forceSend);
65+
sentMessages = true;
66+
}
67+
}
68+
return sentMessages;
69+
}
70+
71+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
72+
internal void PostProcessDirtyObject(NetworkObject dirtyObj)
73+
{
74+
for (int k = 0; k < dirtyObj.ChildNetworkBehaviours.Count; k++)
75+
{
76+
var behaviour = dirtyObj.ChildNetworkBehaviours[k];
77+
for (int i = 0; i < behaviour.NetworkVariableFields.Count; i++)
78+
{
79+
// Set to true for NetworkVariable to ignore duplication of the
80+
// "internal original value" for collections support.
81+
behaviour.NetworkVariableFields[i].NetworkUpdaterCheck = true;
82+
if (behaviour.NetworkVariableFields[i].IsDirty() &&
83+
!behaviour.NetworkVariableIndexesToResetSet.Contains(i))
84+
{
85+
behaviour.NetworkVariableIndexesToResetSet.Add(i);
86+
behaviour.NetworkVariableIndexesToReset.Add(i);
87+
}
88+
// Reset back to false when done
89+
behaviour.NetworkVariableFields[i].NetworkUpdaterCheck = false;
90+
}
91+
}
92+
}
93+
94+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
95+
internal void ResetDirtyObject(NetworkObject dirtyObj, bool forceSend)
96+
{
97+
foreach (var behaviour in dirtyObj.ChildNetworkBehaviours)
98+
{
99+
behaviour.PostNetworkVariableWrite(forceSend);
100+
}
101+
}
102+
103+
/// <summary>
104+
/// Temporary work-around for assuring any pending dirty states are pushed out prior to showing the object
105+
/// TODO: We need to send all messages that are specific to a NetworkObject along with a NetworkObject event header
106+
/// such that messages will be processed after spawned.
107+
///
108+
/// </summary>
109+
/// <param name="networkObject"></param>
110+
internal void ForceSendIfDirtyOnNetworkShow(NetworkObject networkObject)
111+
{
112+
// Exit early if no pending dirty NetworkVariables.
113+
if (!m_PendingDirtyNetworkObjects.Contains(networkObject))
114+
{
115+
return;
116+
}
117+
118+
// Process a bit differently whether client or server
119+
if (m_NetworkManager.IsServer)
120+
{
121+
ProcessDirtyObjectServer(networkObject, true);
122+
}
123+
else
124+
{
125+
ProcessDirtyObjectClient(networkObject, true);
126+
}
127+
128+
// Handle post processing and resetting of the NetworkObject
129+
PostProcessDirtyObject(networkObject);
130+
ResetDirtyObject(networkObject, true);
131+
132+
// Remove it from the pending dirty objects list
133+
m_PendingDirtyNetworkObjects.Remove(networkObject);
134+
}
135+
26136
/// <summary>
27137
/// Sends NetworkVariable deltas
28138
/// </summary>
@@ -49,76 +159,29 @@ internal bool NetworkBehaviourUpdate(bool forceSend = false)
49159
{
50160
foreach (var dirtyObj in m_DirtyNetworkObjects)
51161
{
52-
for (int k = 0; k < dirtyObj.ChildNetworkBehaviours.Count; k++)
53-
{
54-
dirtyObj.ChildNetworkBehaviours[k].PreVariableUpdate();
55-
}
56-
57-
for (int i = 0; i < m_ConnectionManager.ConnectedClientsList.Count; i++)
58-
{
59-
var client = m_ConnectionManager.ConnectedClientsList[i];
60-
if (m_NetworkManager.DistributedAuthorityMode || dirtyObj.IsNetworkVisibleTo(client.ClientId))
61-
{
62-
// Sync just the variables for just the objects this client sees
63-
for (int k = 0; k < dirtyObj.ChildNetworkBehaviours.Count; k++)
64-
{
65-
dirtyObj.ChildNetworkBehaviours[k].NetworkVariableUpdate(client.ClientId, forceSend);
66-
sentMessages = true;
67-
}
68-
}
69-
}
162+
sentMessages = sentMessages || ProcessDirtyObjectServer(dirtyObj, forceSend);
70163
}
71164
}
72165
else
73166
{
74167
// when client updates the server, it tells it about all its objects
75-
foreach (var sobj in m_DirtyNetworkObjects)
168+
foreach (var dirtyObj in m_DirtyNetworkObjects)
76169
{
77-
if (sobj.IsOwner)
78-
{
79-
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
80-
{
81-
sobj.ChildNetworkBehaviours[k].PreVariableUpdate();
82-
}
83-
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
84-
{
85-
sobj.ChildNetworkBehaviours[k].NetworkVariableUpdate(NetworkManager.ServerClientId, forceSend);
86-
sentMessages = true;
87-
}
88-
}
170+
sentMessages = sentMessages || ProcessDirtyObjectClient(dirtyObj, forceSend);
89171
}
90172
}
91173

92174
foreach (var dirtyObj in m_DirtyNetworkObjects)
93175
{
94-
for (int k = 0; k < dirtyObj.ChildNetworkBehaviours.Count; k++)
95-
{
96-
var behaviour = dirtyObj.ChildNetworkBehaviours[k];
97-
for (int i = 0; i < behaviour.NetworkVariableFields.Count; i++)
98-
{
99-
// Set to true for NetworkVariable to ignore duplication of the
100-
// "internal original value" for collections support.
101-
behaviour.NetworkVariableFields[i].NetworkUpdaterCheck = true;
102-
if (behaviour.NetworkVariableFields[i].IsDirty() &&
103-
!behaviour.NetworkVariableIndexesToResetSet.Contains(i))
104-
{
105-
behaviour.NetworkVariableIndexesToResetSet.Add(i);
106-
behaviour.NetworkVariableIndexesToReset.Add(i);
107-
}
108-
// Reset back to false when done
109-
behaviour.NetworkVariableFields[i].NetworkUpdaterCheck = false;
110-
}
111-
}
176+
PostProcessDirtyObject(dirtyObj);
112177
}
113178

114179
// Now, reset all the no-longer-dirty variables
115180
foreach (var dirtyObj in m_DirtyNetworkObjects)
116181
{
117-
foreach (var behaviour in dirtyObj.ChildNetworkBehaviours)
118-
{
119-
behaviour.PostNetworkVariableWrite(forceSend);
120-
}
182+
ResetDirtyObject(dirtyObj, forceSend);
121183
}
184+
122185
m_DirtyNetworkObjects.Clear();
123186
}
124187
finally

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ public void NetworkUpdate(NetworkUpdateStage updateStage)
442442
}
443443

444444
// Send any pending objects to be shown (in-between ticks)
445-
SpawnManager.HandleNetworkObjectShow();
445+
SpawnManager.HandleNetworkObjectShow(true);
446446

447447
// Update any NetworkObject's registered to notify of scene migration changes.
448448
SpawnManager.UpdateNetworkObjectSceneChanges();

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1796,8 +1796,9 @@ internal void UpdateObservedNetworkObjects(ulong clientId)
17961796

17971797
/// <summary>
17981798
/// See <see cref="NetworkBehaviourUpdater.NetworkBehaviourUpdater_Tick"/>
1799+
/// See <see cref="NetworkManager.NetworkUpdate(NetworkUpdateStage)"/> during the <see cref="NetworkUpdateStage.PostLateUpdate"/> stage.
17991800
/// </summary>
1800-
internal void HandleNetworkObjectShow()
1801+
internal void HandleNetworkObjectShow(bool forceSend = false)
18011802
{
18021803
// Covers any distributed authority client that is not the DAHost
18031804
var isDistributedAuthorityClient = NetworkManager.DistributedAuthorityMode && !NetworkManager.DAHost;
@@ -1818,6 +1819,10 @@ internal void HandleNetworkObjectShow()
18181819
{
18191820
try
18201821
{
1822+
if (forceSend)
1823+
{
1824+
NetworkManager.BehaviourUpdater.ForceSendIfDirtyOnNetworkShow(entry.Key);
1825+
}
18211826
SendSpawnCallForObserverUpdate(entry.Value.ToArray(), entry.Key);
18221827
}
18231828
catch (Exception ex)
@@ -1844,6 +1849,10 @@ internal void HandleNetworkObjectShow()
18441849
{
18451850
try
18461851
{
1852+
if (forceSend)
1853+
{
1854+
NetworkManager.BehaviourUpdater.ForceSendIfDirtyOnNetworkShow(networkObject);
1855+
}
18471856
SendSpawnCallForObject(clientId, networkObject);
18481857
}
18491858
catch (Exception ex)

0 commit comments

Comments
 (0)