Skip to content

Commit d1bc02c

Browse files
feat: count NGO and hybrid spawns per session in editor analytics
NetworkSpawnManager counts local spawns (editor only) and the hybrid ones among them. NetcodeAnalytics reads both when the session stops and adds NgoSpawnCount and HybridSpawnCount to the NGO_NetworkManager event.
1 parent 44b7386 commit d1bc02c

5 files changed

Lines changed: 118 additions & 0 deletions

File tree

‎com.unity.netcode.gameobjects/Editor/Analytics/NetcodeAnalytics.cs‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ internal struct NetworkSessionInfo
1818
public bool UsedCMBService;
1919
public string Transport;
2020
public NetworkConfig NetworkConfig;
21+
public int NgoSpawnCount;
22+
public int HybridSpawnCount;
2123
}
2224

2325
/// <summary>
@@ -124,6 +126,12 @@ internal override void SessionStopped(NetworkManager networkManager)
124126
return;
125127
}
126128
recentSession.UsedCMBService = networkManager.CMBServiceConnection;
129+
var spawnManager = networkManager.SpawnManager;
130+
if (spawnManager != null)
131+
{
132+
recentSession.HybridSpawnCount = spawnManager.HybridSpawnCount;
133+
recentSession.NgoSpawnCount = spawnManager.SpawnCount - spawnManager.HybridSpawnCount;
134+
}
127135
recentSession.SessionStopped = true;
128136
RecentSessions[lastIndex] = recentSession;
129137
}
@@ -220,6 +228,8 @@ private NetworkManagerAnalytics GetNetworkManagerAnalytics(NetworkSessionInfo ne
220228
NetworkTransport = networkSession.Transport,
221229
EnableSceneManagement = networkSession.NetworkConfig.EnableSceneManagement,
222230
TickRate = (int)networkSession.NetworkConfig.TickRate,
231+
NgoSpawnCount = networkSession.NgoSpawnCount,
232+
HybridSpawnCount = networkSession.HybridSpawnCount,
223233
};
224234
return networkManagerAnalytics;
225235
}

‎com.unity.netcode.gameobjects/Editor/Analytics/NetworkManagerAnalytics.cs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ internal struct NetworkManagerAnalytics : IAnalytic.IData, IEquatable<NetworkMan
1717
public string NetworkTransport;
1818
public bool EnableSceneManagement;
1919
public int TickRate;
20+
public int NgoSpawnCount;
21+
public int HybridSpawnCount;
2022
public override string ToString()
2123
{
2224
var message = new StringBuilder();
@@ -28,6 +30,8 @@ public override string ToString()
2830
message.AppendLine($"{nameof(NetworkTransport)}: {NetworkTransport}");
2931
message.AppendLine($"{nameof(EnableSceneManagement)}: {EnableSceneManagement}");
3032
message.AppendLine($"{nameof(TickRate)}: {TickRate}");
33+
message.AppendLine($"{nameof(NgoSpawnCount)}: {NgoSpawnCount}");
34+
message.AppendLine($"{nameof(HybridSpawnCount)}: {HybridSpawnCount}");
3135
return message.ToString();
3236
}
3337

@@ -40,6 +44,7 @@ public bool Equals(NetworkManagerAnalytics other)
4044
return IsDistributedAuthority == other.IsDistributedAuthority && WasServer == other.WasServer && WasClient == other.WasClient
4145
&& UsedCMBService == other.UsedCMBService && IsUsingMultiplayerSDK == other.IsUsingMultiplayerSDK
4246
&& EnableSceneManagement == other.EnableSceneManagement && TickRate == other.TickRate
47+
&& NgoSpawnCount == other.NgoSpawnCount && HybridSpawnCount == other.HybridSpawnCount
4348
&& NetworkTransport.Equals(other.NetworkTransport);
4449
}
4550
}

‎com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ public class NetworkSpawnManager
3434
/// </summary>
3535
public readonly HashSet<NetworkObject> SpawnedObjectsList = new HashSet<NetworkObject>();
3636

37+
#if UNITY_EDITOR
38+
// Spawns this peer made or received during the session, reported by the editor analytics.
39+
internal int SpawnCount;
40+
internal int HybridSpawnCount;
41+
#endif
42+
3743
/// <summary>
3844
/// Use to get all NetworkObjects owned by a client
3945
/// Ownership to Objects Table Format:
@@ -1313,11 +1319,17 @@ internal bool SpawnNetworkObjectLocallyCommon(NetworkObject networkObject, ulong
13131319
if (networkObject.HasGhost)
13141320
{
13151321
networkObject.NetworkObjectBridge.UpdateGhostOwner(NetworkManager, ownerClientId);
1322+
#if UNITY_EDITOR
1323+
HybridSpawnCount++;
1324+
#endif
13161325
}
13171326
#endif
13181327

13191328
SpawnedObjects.Add(networkObject.NetworkObjectId, networkObject);
13201329
SpawnedObjectsList.Add(networkObject);
1330+
#if UNITY_EDITOR
1331+
SpawnCount++;
1332+
#endif
13211333
networkObject.ApplyNetworkParenting();
13221334

13231335
NetworkObject.CheckOrphanChildren();
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#if UNITY_EDITOR
2+
using System.Collections;
3+
using NUnit.Framework;
4+
using Unity.Netcode.TestHelpers.Runtime;
5+
using UnityEngine;
6+
using UnityEngine.TestTools;
7+
8+
namespace Unity.Netcode.RuntimeTests
9+
{
10+
/// <summary>
11+
/// Validates the spawn counts the editor analytics reads from <see cref="NetworkSpawnManager"/>:<br />
12+
/// - Every peer counts each instance it spawns locally, whether it is the authority or received the spawn.<br />
13+
/// - Hybrid instances are also counted on their own.<br />
14+
/// </summary>
15+
[TestFixture(HostOrServer.Host)]
16+
[TestFixture(HostOrServer.UnifiedHost)]
17+
internal class SpawnCountAnalyticsTests : NetcodeIntegrationTest
18+
{
19+
private const int k_DefaultInstances = 3;
20+
private const int k_NgoInstances = 2;
21+
22+
protected override int NumberOfClients => 2;
23+
24+
// Hybrid during a unified test pass.
25+
private GameObject m_DefaultPrefab;
26+
private GameObject m_NgoPrefab;
27+
28+
public SpawnCountAnalyticsTests(HostOrServer hostOrServer) : base(hostOrServer)
29+
{
30+
}
31+
32+
protected override bool UseUnifiedTests()
33+
{
34+
return true;
35+
}
36+
37+
protected override void OnServerAndClientsCreated()
38+
{
39+
m_DefaultPrefab = CreateNetworkObjectPrefab("SpawnCountDefault");
40+
#if UNIFIED_NETCODE
41+
m_NgoPrefab = CreateNetworkObjectPrefab("SpawnCountNgo", false);
42+
#else
43+
m_NgoPrefab = CreateNetworkObjectPrefab("SpawnCountNgo");
44+
#endif
45+
base.OnServerAndClientsCreated();
46+
}
47+
48+
[UnityTest]
49+
public IEnumerator SpawnsAreCountedOnEveryPeer()
50+
{
51+
// Player objects are already spawned, so only the increase is checked.
52+
var spawnCounts = new int[m_NetworkManagers.Length];
53+
var hybridSpawnCounts = new int[m_NetworkManagers.Length];
54+
for (int i = 0; i < m_NetworkManagers.Length; i++)
55+
{
56+
spawnCounts[i] = m_NetworkManagers[i].SpawnManager.SpawnCount;
57+
hybridSpawnCounts[i] = m_NetworkManagers[i].SpawnManager.HybridSpawnCount;
58+
}
59+
60+
var authority = GetAuthorityNetworkManager();
61+
var instances = SpawnObjects(m_DefaultPrefab, authority, k_DefaultInstances);
62+
instances.AddRange(SpawnObjects(m_NgoPrefab, authority, k_NgoInstances));
63+
foreach (var instance in instances)
64+
{
65+
yield return WaitForSpawnedOnAllOrTimeOut(instance.GetComponent<NetworkObject>());
66+
AssertOnTimeout($"Failed to spawn {instance.name} on all clients!");
67+
}
68+
69+
var expectedHybridSpawns = m_UseUnifiedTests ? k_DefaultInstances : 0;
70+
for (int i = 0; i < m_NetworkManagers.Length; i++)
71+
{
72+
var spawnManager = m_NetworkManagers[i].SpawnManager;
73+
var clientId = m_NetworkManagers[i].LocalClientId;
74+
Assert.AreEqual(k_DefaultInstances + k_NgoInstances, spawnManager.SpawnCount - spawnCounts[i], $"Client-{clientId} counted the wrong number of spawns!");
75+
Assert.AreEqual(expectedHybridSpawns, spawnManager.HybridSpawnCount - hybridSpawnCounts[i], $"Client-{clientId} counted the wrong number of hybrid spawns!");
76+
}
77+
}
78+
}
79+
}
80+
#endif

‎com.unity.netcode.gameobjects/Tests/Runtime/NetworkObject/SpawnCountAnalyticsTests.cs.meta‎

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

0 commit comments

Comments
 (0)