Skip to content

feat: Add metrics for multiple objects spawned and destroyed (i.e. NetworkShow/Hide) #935

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
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6cdc325
Add new network object spawn/destroy metrics
Jun 9, 2021
c940eb1
Move tests into their own directory
Jun 9, 2021
0a63e20
Merge branch 'experimental/netstats-dispatcher' into experimental/net…
Jun 10, 2021
0c6442c
Move tests to their own directory, use new framework
Jun 10, 2021
4a9ba88
Merge branch 'experimental/netstats-dispatcher' into experimental/net…
Jun 10, 2021
11fa397
Fix network spawn test
Jun 10, 2021
150b520
Implement test for spawn call received
Jun 10, 2021
e456d22
Add full tests for network object spawn/destroy sent and received
Jun 14, 2021
92a9004
Grab network object early so we can report network object name in met…
Jun 14, 2021
2f00d44
Add metrics for multiple network objects spawned/destroyed
Jun 17, 2021
d96c2ff
Merge branch 'experimental/netstats-dispatcher' into experimental/net…
Jun 28, 2021
557d525
Merge branch 'experimental/netstats/network-object-spawn-destroy' int…
Jun 28, 2021
88626bc
Small fix ups after merge
Jun 28, 2021
898201d
Merge branch 'experimental/netstats-dispatcher' into experimental/net…
Jun 29, 2021
78aa0e1
Merge branch 'experimental/netstats/network-object-spawn-destroy' int…
Jun 29, 2021
c8322cb
Improve tests and fix bad merge
Jun 30, 2021
2f76a16
Remove unused import
Jun 30, 2021
3cdd938
Merge branch 'experimental/netstats/network-object-spawn-destroy' int…
Jun 30, 2021
acae2f0
track spawned objects
Jun 30, 2021
00092c0
Remove unnecessary changes
Jun 30, 2021
ab95b83
Merge branch 'experimental/netstats/network-object-spawn-destroy' int…
Jun 30, 2021
a84247c
Initial tests for many objects spawned/destroyed
Jun 30, 2021
a08c5ff
Add tests for Spawn sent, remove 'received' metrics as no longer used
Jun 30, 2021
8d2c03c
Merge branch 'experimental/netstats-dispatcher' into experimental/net…
Jun 30, 2021
67a938c
Remove overzealous linter changes
Jul 1, 2021
d1652f2
Use individual metrics for multiple object spawn/destroy to avoid run…
Jul 7, 2021
80e23fd
Clean up after removing types
Jul 7, 2021
21a36e6
one more
Jul 7, 2021
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
11 changes: 7 additions & 4 deletions com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -286,23 +286,23 @@ public static void NetworkShow(List<NetworkObject> networkObjects, ulong clientI
throw new ArgumentNullException("All " + nameof(NetworkObject) + "s must belong to the same " + nameof(NetworkManager));
}
}

using (var buffer = PooledNetworkBuffer.Get())
using (var writer = PooledNetworkWriter.Get(buffer))
{
writer.WriteUInt16Packed((ushort)networkObjects.Count);

long prevLength = 0;
for (int i = 0; i < networkObjects.Count; i++)
{
// Send spawn call
networkObjects[i].Observers.Add(clientId);

networkManager.SpawnManager.WriteSpawnCallForObject(buffer, clientId, networkObjects[i], payload);
networkManager.NetworkMetrics.TrackObjectSpawnSent(clientId, networkObjects[i].NetworkObjectId, networkObjects[i].name, (ulong)(buffer.Length - prevLength));
prevLength = buffer.Length;
}

networkManager.MessageSender.Send(clientId, NetworkConstants.ADD_OBJECTS, NetworkChannel.Internal, buffer);
}
// TODO: add metric for spawn objects here
}

/// <summary>
Expand Down Expand Up @@ -392,17 +392,20 @@ public static void NetworkHide(List<NetworkObject> networkObjects, ulong clientI
{
writer.WriteUInt16Packed((ushort)networkObjects.Count);

long prevLength = 0;

for (int i = 0; i < networkObjects.Count; i++)
{
// Send destroy call
networkObjects[i].Observers.Remove(clientId);

writer.WriteUInt64Packed(networkObjects[i].NetworkObjectId);
networkManager.NetworkMetrics.TrackObjectDestroySent(clientId, networkObjects[i].NetworkObjectId, networkObjects[i].name, (ulong)(buffer.Length - prevLength));
prevLength = buffer.Length;
}

networkManager.MessageSender.Send(clientId, NetworkConstants.DESTROY_OBJECTS, NetworkChannel.Internal, buffer);
}
// TODO: add metric for destroy objects here
}

private void OnDestroy()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using MLAPI.Metrics;
using NUnit.Framework;
Expand Down Expand Up @@ -144,5 +145,80 @@ public IEnumerator TrackNetworkObjectDestroyReceivedMetric()
// Bug: Currently the object name is always "Player Clone"
// Assert.AreEqual(m_NewNetworkObjectName, objectDestroyed.NetworkId.Name);
}

[UnityTest]
public IEnumerator TrackMultipleNetworkObjectDestroySentMetric()
{
m_NewNetworkObject.Spawn();

// Spawn another network object so we can hide multiple.
var gameObject = new GameObject(m_NewNetworkObjectName);
var anotherNetworkObject = gameObject.AddComponent<NetworkObject>();
anotherNetworkObject.NetworkManagerOwner = m_Server;
anotherNetworkObject.Spawn();

var waitForMetricEvent = new WaitForMetricValues<ObjectDestroyedEvent>(m_ServerMetrics.Dispatcher, MetricNames.ObjectDestroyedSent);
yield return waitForMetricEvent.WaitForAFewFrames();

NetworkObject.NetworkHide(new List<NetworkObject>{m_NewNetworkObject, anotherNetworkObject}, m_Client.LocalClientId);

yield return waitForMetricEvent.Wait(60);

var objectDestroyedSentMetricValues = waitForMetricEvent.EnsureMetricValuesHaveBeenFound();
// As there's a client and server, this event is emitted twice.
Assert.AreEqual(2, objectDestroyedSentMetricValues.Count);

var networkIDFound = true;
var networkNameFound = true;
// not sure that we can guarantee the order of these so just ensure the data is in the received metrics.
foreach (var metricValue in objectDestroyedSentMetricValues)
{
Assert.AreEqual(m_Client.LocalClientId, metricValue.Connection.Id);
networkIDFound &= metricValue.NetworkId.NetworkId == m_NewNetworkObject.NetworkObjectId || metricValue.NetworkId.NetworkId == anotherNetworkObject.NetworkObjectId;
networkNameFound &= metricValue.NetworkId.Name == m_NewNetworkObject.name || metricValue.NetworkId.Name == anotherNetworkObject.name;
}
Assert.IsTrue(networkIDFound);
Assert.IsTrue(networkNameFound);
}

[UnityTest]
public IEnumerator TrackMultipleNetworkObjectSpawnSentMetric()
{
m_NewNetworkObject.Spawn();

// Spawn another network object so we can hide multiple.
var gameObject = new GameObject(m_NewNetworkObjectName);
var anotherNetworkObject = gameObject.AddComponent<NetworkObject>();
anotherNetworkObject.NetworkManagerOwner = m_Server;
anotherNetworkObject.Spawn();

var waitForMetricEvent = new WaitForMetricValues<ObjectSpawnedEvent>(m_ServerMetrics.Dispatcher, MetricNames.ObjectSpawnedSent);
yield return waitForMetricEvent.WaitForAFewFrames();

NetworkObject.NetworkHide(new List<NetworkObject>{m_NewNetworkObject, anotherNetworkObject}, m_Client.LocalClientId);

yield return waitForMetricEvent.WaitForAFewFrames();

NetworkObject.NetworkShow(new List<NetworkObject>{m_NewNetworkObject, anotherNetworkObject}, m_Client.LocalClientId);

yield return waitForMetricEvent.Wait(60);

var objectSpawnedSentMetricValues = waitForMetricEvent.EnsureMetricValuesHaveBeenFound();
// As there's a client and server, this event is emitted twice.
Assert.AreEqual(2, objectSpawnedSentMetricValues.Count);

var networkIDFound = true;
var networkNameFound = true;
// not sure that we can guarantee the order of these so just ensure the data is in the received metrics.
foreach (var metricValue in objectSpawnedSentMetricValues)
{
Assert.AreEqual(m_Client.LocalClientId, metricValue.Connection.Id);
networkIDFound &= metricValue.NetworkId.NetworkId == m_NewNetworkObject.NetworkObjectId || metricValue.NetworkId.NetworkId == anotherNetworkObject.NetworkObjectId;
networkNameFound &= metricValue.NetworkId.Name == m_NewNetworkObject.name || metricValue.NetworkId.Name == anotherNetworkObject.name;
}

Assert.IsTrue(networkIDFound);
Assert.IsTrue(networkNameFound);
}
}
}