Skip to content

Commit

Permalink
fix(NetworkBehavior): removing NB that belong to another NI from list (
Browse files Browse the repository at this point in the history
…#970)

If there are Nested NetworkBehaviours and NetworkIdentity then there can be a problem where the parent NetworkIdentity will find Behaviour that belong to another child NetworkIdentity.

This will remove those NB from the current NI's array and then resize the array to be the correct size
  • Loading branch information
James-Frowen committed Dec 29, 2021
1 parent b5a765e commit 4738d29
Showing 1 changed file with 45 additions and 11 deletions.
56 changes: 45 additions & 11 deletions Assets/Mirage/Runtime/NetworkIdentity.cs
Expand Up @@ -232,24 +232,58 @@ public NetworkBehaviour[] NetworkBehaviours
{
get
{
if (networkBehavioursCache != null)
return networkBehavioursCache;
if (networkBehavioursCache is null)
{
NetworkBehaviour[] components = FindBehaviourForThisIdentity();

NetworkBehaviour[] components = GetComponentsInChildren<NetworkBehaviour>(true);

#if DEBUG
foreach (NetworkBehaviour item in components)

if (components.Length > byte.MaxValue)
throw new InvalidOperationException("Only 255 NetworkBehaviour per gameobject allowed");

networkBehavioursCache = components;
}

return networkBehavioursCache;
}
}

// cache list to call GetComponentsInChildren() with no allocations
private static List<NetworkBehaviour> childNetworkBehavioursCache = new List<NetworkBehaviour>();

/// <summary>
/// Removes NetworkBehaviour that belong to another NetworkIdentity from the components array
/// <para>
/// If there are nested NetworkIdentities then Behaviour that belong to those Identities will be found by GetComponentsInChildren if the child object is added before the Array is intialized.
/// This method will check each Behaviour to make sure that the Identity is the same as the current Identity, and if it is not remove it from the array
/// </para>
/// </summary>
/// <param name="components"></param>
private NetworkBehaviour[] FindBehaviourForThisIdentity()
{
GetComponentsInChildren<NetworkBehaviour>(true, childNetworkBehavioursCache);

// start at last so we can remove from end of array instead of start
for (int i = childNetworkBehavioursCache.Count - 1; i >= 0; i--)
{
NetworkBehaviour item = childNetworkBehavioursCache[i];
if (item.Identity != this)
{
logger.Assert(item.Identity == this, $"Child NetworkBehaviour had a different Identity, this:{name}, Child Identity:{item.Identity.name}");
childNetworkBehavioursCache.RemoveAt(i);
}
#endif
}

if (components.Length > byte.MaxValue)
throw new InvalidOperationException("Only 255 NetworkBehaviour per gameobject allowed");
NetworkBehaviour[] components = childNetworkBehavioursCache.ToArray();

networkBehavioursCache = components;
return networkBehavioursCache;
#if DEBUG
// validate the results here (just incase they are wrong)
// we only need to do this in debug mode because results should be right
foreach (NetworkBehaviour item in components)
{
logger.Assert(item.Identity == this, $"Child NetworkBehaviour had a different Identity, this:{name}, Child Identity:{item.Identity.name}");
}
#endif
return components;
}

NetworkVisibility _visibility;
Expand Down

0 comments on commit 4738d29

Please sign in to comment.