Skip to content

Commit e122376

Browse files
refactor: move NetworkBehaviour update to a separate non-static class (#917)
Behaviour update was static and made multiinstance tests flaky. Moving this to its own separate component on NetworkManager solves this. This PR also adds a first pass at tests for NetworkBehaviourUpdater.
1 parent 0855557 commit e122376

File tree

6 files changed

+307
-85
lines changed

6 files changed

+307
-85
lines changed

com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviour.cs

Lines changed: 0 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
using MLAPI.Serialization;
1414
using MLAPI.Serialization.Pooled;
1515
using MLAPI.Transports;
16-
using Unity.Profiling;
1716

1817
namespace MLAPI
1918
{
@@ -297,11 +296,6 @@ protected NetworkBehaviour GetNetworkBehaviour(ushort behaviourId)
297296
/// </summary>
298297
public ulong OwnerClientId => NetworkObject.OwnerClientId;
299298

300-
/// <summary>
301-
/// Stores the network tick at the NetworkBehaviourUpdate time
302-
/// This allows sending NetworkVariables not more often than once per network tick, regardless of the update rate
303-
/// </summary>
304-
public static ushort CurrentTick { get; private set; }
305299

306300
/// <summary>
307301
/// Gets called when message handlers are ready to be registered and the network is setup
@@ -353,7 +347,6 @@ public virtual void OnNetworkObjectParentChanged(NetworkObject parentNetworkObje
353347
private readonly List<NetworkChannel> m_ChannelsForNetworkVariableGroups = new List<NetworkChannel>();
354348
internal readonly List<INetworkVariable> NetworkVariableFields = new List<INetworkVariable>();
355349

356-
private static HashSet<NetworkObject> s_Touched = new HashSet<NetworkObject>();
357350
private static Dictionary<Type, FieldInfo[]> s_FieldTypes = new Dictionary<Type, FieldInfo[]>();
358351

359352
private static FieldInfo[] GetFieldInfoForType(Type type)
@@ -446,83 +439,6 @@ internal void InitializeVariables()
446439
}
447440
}
448441

449-
#if DEVELOPMENT_BUILD || UNITY_EDITOR
450-
private static ProfilerMarker s_NetworkBehaviourUpdate = new ProfilerMarker($"{nameof(NetworkBehaviour)}.{nameof(NetworkBehaviourUpdate)}");
451-
#endif
452-
453-
internal static void NetworkBehaviourUpdate(NetworkManager networkManager)
454-
{
455-
// Do not execute NetworkBehaviourUpdate more than once per network tick
456-
ushort tick = networkManager.NetworkTickSystem.GetTick();
457-
if (tick == CurrentTick)
458-
{
459-
return;
460-
}
461-
462-
CurrentTick = tick;
463-
464-
#if DEVELOPMENT_BUILD || UNITY_EDITOR
465-
s_NetworkBehaviourUpdate.Begin();
466-
#endif
467-
try
468-
{
469-
if (networkManager.IsServer)
470-
{
471-
s_Touched.Clear();
472-
for (int i = 0; i < networkManager.ConnectedClientsList.Count; i++)
473-
{
474-
var client = networkManager.ConnectedClientsList[i];
475-
var spawnedObjs = networkManager.SpawnManager.SpawnedObjectsList;
476-
s_Touched.UnionWith(spawnedObjs);
477-
foreach (var sobj in spawnedObjs)
478-
{
479-
// Sync just the variables for just the objects this client sees
480-
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
481-
{
482-
sobj.ChildNetworkBehaviours[k].VariableUpdate(client.ClientId);
483-
}
484-
}
485-
}
486-
487-
// Now, reset all the no-longer-dirty variables
488-
foreach (var sobj in s_Touched)
489-
{
490-
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
491-
{
492-
sobj.ChildNetworkBehaviours[k].PostNetworkVariableWrite();
493-
}
494-
}
495-
}
496-
else
497-
{
498-
// when client updates the sever, it tells it about all its objects
499-
foreach (var sobj in networkManager.SpawnManager.SpawnedObjectsList)
500-
{
501-
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
502-
{
503-
sobj.ChildNetworkBehaviours[k].VariableUpdate(networkManager.ServerClientId);
504-
}
505-
}
506-
507-
// Now, reset all the no-longer-dirty variables
508-
foreach (var sobj in networkManager.SpawnManager.SpawnedObjectsList)
509-
{
510-
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
511-
{
512-
sobj.ChildNetworkBehaviours[k].PostNetworkVariableWrite();
513-
}
514-
}
515-
}
516-
}
517-
finally
518-
{
519-
#if DEVELOPMENT_BUILD || UNITY_EDITOR
520-
s_NetworkBehaviourUpdate.End();
521-
#endif
522-
}
523-
}
524-
525-
526442
internal void PreNetworkVariableWrite()
527443
{
528444
// reset our "which variables got written" data
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
using System.Collections.Generic;
2+
using Unity.Profiling;
3+
4+
namespace MLAPI
5+
{
6+
public class NetworkBehaviourUpdater
7+
{
8+
private HashSet<NetworkObject> m_Touched = new HashSet<NetworkObject>();
9+
10+
/// <summary>
11+
/// Stores the network tick at the NetworkBehaviourUpdate time
12+
/// This allows sending NetworkVariables not more often than once per network tick, regardless of the update rate
13+
/// </summary>
14+
public ushort CurrentTick { get; set; }
15+
16+
#if DEVELOPMENT_BUILD || UNITY_EDITOR
17+
private ProfilerMarker m_NetworkBehaviourUpdate = new ProfilerMarker($"{nameof(NetworkBehaviour)}.{nameof(NetworkBehaviourUpdate)}");
18+
#endif
19+
20+
internal void NetworkBehaviourUpdate(NetworkManager networkManager)
21+
{
22+
// Do not execute NetworkBehaviourUpdate more than once per network tick
23+
ushort tick = networkManager.NetworkTickSystem.GetTick();
24+
if (tick == CurrentTick)
25+
{
26+
return;
27+
}
28+
29+
CurrentTick = tick;
30+
31+
#if DEVELOPMENT_BUILD || UNITY_EDITOR
32+
m_NetworkBehaviourUpdate.Begin();
33+
#endif
34+
try
35+
{
36+
if (networkManager.IsServer)
37+
{
38+
m_Touched.Clear();
39+
for (int i = 0; i < networkManager.ConnectedClientsList.Count; i++)
40+
{
41+
var client = networkManager.ConnectedClientsList[i];
42+
var spawnedObjs = networkManager.SpawnManager.SpawnedObjectsList;
43+
m_Touched.UnionWith(spawnedObjs);
44+
foreach (var sobj in spawnedObjs)
45+
{
46+
// Sync just the variables for just the objects this client sees
47+
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
48+
{
49+
sobj.ChildNetworkBehaviours[k].VariableUpdate(client.ClientId);
50+
}
51+
}
52+
}
53+
54+
// Now, reset all the no-longer-dirty variables
55+
foreach (var sobj in m_Touched)
56+
{
57+
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
58+
{
59+
sobj.ChildNetworkBehaviours[k].PostNetworkVariableWrite();
60+
}
61+
}
62+
}
63+
else
64+
{
65+
// when client updates the server, it tells it about all its objects
66+
foreach (var sobj in networkManager.SpawnManager.SpawnedObjectsList)
67+
{
68+
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
69+
{
70+
sobj.ChildNetworkBehaviours[k].VariableUpdate(networkManager.ServerClientId);
71+
}
72+
}
73+
74+
// Now, reset all the no-longer-dirty variables
75+
foreach (var sobj in networkManager.SpawnManager.SpawnedObjectsList)
76+
{
77+
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
78+
{
79+
sobj.ChildNetworkBehaviours[k].PostNetworkVariableWrite();
80+
}
81+
}
82+
}
83+
}
84+
finally
85+
{
86+
#if DEVELOPMENT_BUILD || UNITY_EDITOR
87+
m_NetworkBehaviourUpdate.End();
88+
#endif
89+
}
90+
}
91+
92+
}
93+
}

com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviourUpdater.cs.meta

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

com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public class NetworkManager : MonoBehaviour, INetworkUpdateSystem, IProfilableTr
5959
internal NetworkTickSystem NetworkTickSystem { get; private set; }
6060

6161
internal SnapshotSystem SnapshotSystem { get; private set; }
62+
internal NetworkBehaviourUpdater BehaviourUpdater { get; private set; }
6263

6364
private NetworkPrefabHandler m_PrefabHandler;
6465
public NetworkPrefabHandler PrefabHandler
@@ -348,6 +349,8 @@ private void Initialize(bool server)
348349

349350
SceneManager = new NetworkSceneManager(this);
350351

352+
BehaviourUpdater = new NetworkBehaviourUpdater();
353+
351354
// Only create this if it's not already set (like in test cases)
352355
MessageHandler ??= CreateMessageHandler();
353356

@@ -845,6 +848,11 @@ public void Shutdown()
845848
CustomMessagingManager = null;
846849
}
847850

851+
if (BehaviourUpdater != null)
852+
{
853+
BehaviourUpdater = null;
854+
}
855+
848856
//The Transport is set during Init time, thus it is possible for the Transport to be null
849857
NetworkConfig?.NetworkTransport?.Shutdown();
850858
}
@@ -932,7 +940,7 @@ private void OnNetworkPreUpdate()
932940
if (NetworkConfig.EnableNetworkVariable)
933941
{
934942
// Do NetworkVariable updates
935-
NetworkBehaviour.NetworkBehaviourUpdate(this);
943+
BehaviourUpdater.NetworkBehaviourUpdate(this);
936944
}
937945

938946
if (!IsServer && NetworkConfig.EnableMessageBuffering)

0 commit comments

Comments
 (0)