Skip to content

refactor: move NetworkBehaviour update to a separate non-static class #917

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jun 29, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 0 additions & 84 deletions com.unity.multiplayer.mlapi/Runtime/Core/NetworkBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
using MLAPI.Serialization;
using MLAPI.Serialization.Pooled;
using MLAPI.Transports;
using Unity.Profiling;

namespace MLAPI
{
Expand Down Expand Up @@ -297,11 +296,6 @@ protected NetworkBehaviour GetNetworkBehaviour(ushort behaviourId)
/// </summary>
public ulong OwnerClientId => NetworkObject.OwnerClientId;

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

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

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

private static FieldInfo[] GetFieldInfoForType(Type type)
Expand Down Expand Up @@ -446,83 +439,6 @@ internal void InitializeVariables()
}
}

#if DEVELOPMENT_BUILD || UNITY_EDITOR
private static ProfilerMarker s_NetworkBehaviourUpdate = new ProfilerMarker($"{nameof(NetworkBehaviour)}.{nameof(NetworkBehaviourUpdate)}");
#endif

internal static void NetworkBehaviourUpdate(NetworkManager networkManager)
{
// Do not execute NetworkBehaviourUpdate more than once per network tick
ushort tick = networkManager.NetworkTickSystem.GetTick();
if (tick == CurrentTick)
{
return;
}

CurrentTick = tick;

#if DEVELOPMENT_BUILD || UNITY_EDITOR
s_NetworkBehaviourUpdate.Begin();
#endif
try
{
if (networkManager.IsServer)
{
s_Touched.Clear();
for (int i = 0; i < networkManager.ConnectedClientsList.Count; i++)
{
var client = networkManager.ConnectedClientsList[i];
var spawnedObjs = networkManager.SpawnManager.SpawnedObjectsList;
s_Touched.UnionWith(spawnedObjs);
foreach (var sobj in spawnedObjs)
{
// Sync just the variables for just the objects this client sees
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
{
sobj.ChildNetworkBehaviours[k].VariableUpdate(client.ClientId);
}
}
}

// Now, reset all the no-longer-dirty variables
foreach (var sobj in s_Touched)
{
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
{
sobj.ChildNetworkBehaviours[k].PostNetworkVariableWrite();
}
}
}
else
{
// when client updates the sever, it tells it about all its objects
foreach (var sobj in networkManager.SpawnManager.SpawnedObjectsList)
{
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
{
sobj.ChildNetworkBehaviours[k].VariableUpdate(networkManager.ServerClientId);
}
}

// Now, reset all the no-longer-dirty variables
foreach (var sobj in networkManager.SpawnManager.SpawnedObjectsList)
{
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
{
sobj.ChildNetworkBehaviours[k].PostNetworkVariableWrite();
}
}
}
}
finally
{
#if DEVELOPMENT_BUILD || UNITY_EDITOR
s_NetworkBehaviourUpdate.End();
#endif
}
}


internal void PreNetworkVariableWrite()
{
// reset our "which variables got written" data
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
using System.Collections.Generic;
using Unity.Profiling;

namespace MLAPI
{
public class NetworkBehaviourUpdater
{
private HashSet<NetworkObject> m_Touched = new HashSet<NetworkObject>();

/// <summary>
/// Stores the network tick at the NetworkBehaviourUpdate time
/// This allows sending NetworkVariables not more often than once per network tick, regardless of the update rate
/// </summary>
public ushort CurrentTick { get; set; }

#if DEVELOPMENT_BUILD || UNITY_EDITOR
private ProfilerMarker m_NetworkBehaviourUpdate = new ProfilerMarker($"{nameof(NetworkBehaviour)}.{nameof(NetworkBehaviourUpdate)}");
#endif

internal void NetworkBehaviourUpdate(NetworkManager networkManager)
{
// Do not execute NetworkBehaviourUpdate more than once per network tick
ushort tick = networkManager.NetworkTickSystem.GetTick();
if (tick == CurrentTick)
{
return;
}

CurrentTick = tick;

#if DEVELOPMENT_BUILD || UNITY_EDITOR
m_NetworkBehaviourUpdate.Begin();
#endif
try
{
if (networkManager.IsServer)
{
m_Touched.Clear();
for (int i = 0; i < networkManager.ConnectedClientsList.Count; i++)
{
var client = networkManager.ConnectedClientsList[i];
var spawnedObjs = networkManager.SpawnManager.SpawnedObjectsList;
m_Touched.UnionWith(spawnedObjs);
foreach (var sobj in spawnedObjs)
{
// Sync just the variables for just the objects this client sees
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
{
sobj.ChildNetworkBehaviours[k].VariableUpdate(client.ClientId);
}
}
}

// Now, reset all the no-longer-dirty variables
foreach (var sobj in m_Touched)
{
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
{
sobj.ChildNetworkBehaviours[k].PostNetworkVariableWrite();
}
}
}
else
{
// when client updates the server, it tells it about all its objects
foreach (var sobj in networkManager.SpawnManager.SpawnedObjectsList)
{
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
{
sobj.ChildNetworkBehaviours[k].VariableUpdate(networkManager.ServerClientId);
}
}

// Now, reset all the no-longer-dirty variables
foreach (var sobj in networkManager.SpawnManager.SpawnedObjectsList)
{
for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++)
{
sobj.ChildNetworkBehaviours[k].PostNetworkVariableWrite();
}
}
}
}
finally
{
#if DEVELOPMENT_BUILD || UNITY_EDITOR
m_NetworkBehaviourUpdate.End();
#endif
}
}

}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public class NetworkManager : MonoBehaviour, INetworkUpdateSystem, IProfilableTr
internal NetworkTickSystem NetworkTickSystem { get; private set; }

internal SnapshotSystem SnapshotSystem { get; private set; }
internal NetworkBehaviourUpdater BehaviourUpdater { get; private set; }

private NetworkPrefabHandler m_PrefabHandler;
public NetworkPrefabHandler PrefabHandler
Expand Down Expand Up @@ -348,6 +349,8 @@ private void Initialize(bool server)

SceneManager = new NetworkSceneManager(this);

BehaviourUpdater = new NetworkBehaviourUpdater();

// Only create this if it's not already set (like in test cases)
MessageHandler ??= CreateMessageHandler();

Expand Down Expand Up @@ -844,6 +847,11 @@ public void Shutdown()
CustomMessagingManager = null;
}

if (BehaviourUpdater != null)
{
BehaviourUpdater = null;
}

//The Transport is set during Init time, thus it is possible for the Transport to be null
NetworkConfig?.NetworkTransport?.Shutdown();
}
Expand Down Expand Up @@ -931,7 +939,7 @@ private void OnNetworkPreUpdate()
if (NetworkConfig.EnableNetworkVariable)
{
// Do NetworkVariable updates
NetworkBehaviour.NetworkBehaviourUpdate(this);
BehaviourUpdater.NetworkBehaviourUpdate(this);
}

if (!IsServer && NetworkConfig.EnableMessageBuffering)
Expand Down
Loading