Skip to content

Commit

Permalink
perf: Only synchronize dirty objects (#381)
Browse files Browse the repository at this point in the history
  • Loading branch information
paulpach committed Oct 5, 2020
1 parent 80c9d17 commit 64fd6ed
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 13 deletions.
18 changes: 18 additions & 0 deletions Assets/Mirror/Runtime/NetworkBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,15 @@ public int ComponentIndex
protected void InitSyncObject(ISyncObject syncObject)
{
syncObjects.Add(syncObject);
syncObject.OnChange += SyncObject_OnChange;
}

private void SyncObject_OnChange()
{
if (IsServer)
{
Server.DirtyObjects.Add(NetIdentity);
}
}

#region ServerRpcs
Expand Down Expand Up @@ -406,6 +415,7 @@ protected void SetSyncVar<T>(T value, ref T fieldValue, ulong dirtyBit)
public void SetDirtyBit(ulong dirtyBit)
{
SyncVarDirtyBits |= dirtyBit;
Server.DirtyObjects.Add(NetIdentity);
}

/// <summary>
Expand Down Expand Up @@ -451,6 +461,14 @@ public bool IsDirty()
return false;
}

// true if this component has data that has not been
// synchronized. Note that it may not synchronize
// right away because of syncInterval
public bool StillDirty()
{
return SyncVarDirtyBits != 0L || AnySyncObjectDirty();
}

/// <summary>
/// Virtual function to override to send custom serialization data. The corresponding function to send serialization data is OnDeserialize().
/// </summary>
Expand Down
22 changes: 19 additions & 3 deletions Assets/Mirror/Runtime/NetworkIdentity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,21 @@ private ulong GetDirtyComponentsMask()
return dirtyComponentsMask;
}

/// <summary>
/// Determines if there are changes in any component that have not
/// been synchronized yet. Probably due to not meeting the syncInterval
/// </summary>
/// <returns></returns>
internal bool StillDirty()
{
foreach (NetworkBehaviour behaviour in NetworkBehaviours)
{
if (behaviour.StillDirty())
return true;
}
return false;
}

private ulong GetIntialComponentsMask()
{
// set a bit for every behaviour
Expand Down Expand Up @@ -1280,9 +1295,6 @@ internal void Reset()
ClearObservers();
}

/// <summary>
/// Invoked by NetworkServer.Update during LateUpdate
/// </summary>
internal void ServerUpdate()
{
if (observers.Count > 0)
Expand All @@ -1297,6 +1309,10 @@ internal void ServerUpdate()
}
}

/// <summary>
/// return true if the object is successfully synchronized
/// </summary>
/// <returns></returns>
void SendUpdateVarsMessage()
{
// one writer for owner, one for observers
Expand Down
26 changes: 16 additions & 10 deletions Assets/Mirror/Runtime/NetworkServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ public class NetworkServer : MonoBehaviour, INetworkServer

public readonly Dictionary<uint, NetworkIdentity> Spawned = new Dictionary<uint, NetworkIdentity>();

public readonly HashSet<NetworkIdentity> DirtyObjects = new HashSet<NetworkIdentity>();

// just a cached memory area where we can collect connections
// for broadcasting messages
private static readonly List<INetworkConnection> connectionsCache = new List<INetworkConnection>();
Expand Down Expand Up @@ -424,27 +426,31 @@ public void SendToReady<T>(NetworkIdentity identity, T msg, int channelId)
SendToReady(identity, msg, true, channelId);
}

private readonly List<NetworkIdentity> DirtyObjectsTmp = new List<NetworkIdentity>();

// The user should never need to pump the update loop manually
internal void Update()
{
if (!Active)
return;

// update all server objects
foreach (KeyValuePair<uint, NetworkIdentity> kvp in Spawned)
DirtyObjectsTmp.Clear();

foreach (NetworkIdentity identity in DirtyObjects)
{
NetworkIdentity identity = kvp.Value;
if (identity != null)
{
identity.ServerUpdate();
}
else
{
// spawned list should have no null entries because we
// always call Remove in OnObjectDestroy everywhere.
logger.LogWarning("Found 'null' entry in spawned list for netId=" + kvp.Key + ". Please call NetworkServer.Destroy to destroy networked objects. Don't use GameObject.Destroy.");
}

if (identity.StillDirty())
DirtyObjectsTmp.Add(identity);
}
}

DirtyObjects.Clear();

foreach (NetworkIdentity obj in DirtyObjectsTmp)
DirtyObjects.Add(obj);
}

async Task ConnectionAcceptedAsync(INetworkConnection conn)
Expand Down

0 comments on commit 64fd6ed

Please sign in to comment.