11using System . Collections ;
2+ using System . Diagnostics ;
23using NUnit . Framework ;
34using Unity . Netcode . TestHelpers . Runtime ;
5+ using Unity . PerformanceTesting ;
46using UnityEngine ;
57using UnityEngine . TestTools ;
8+ using Debug = UnityEngine . Debug ;
69
710namespace Unity . Netcode . RuntimeTests
811{
@@ -16,23 +19,42 @@ internal class NetworkObjectSpawnManyObjectsTests : NetcodeIntegrationTest
1619
1720 private NetworkPrefab m_PrefabToSpawn ;
1821
19- public NetworkObjectSpawnManyObjectsTests ( NetworkTopologyTypes networkTopologyType ) : base ( networkTopologyType ) { }
22+ public NetworkObjectSpawnManyObjectsTests ( NetworkTopologyTypes topology ) : base ( topology )
23+ {
24+ }
25+
26+ private static void ResetTracking ( )
27+ {
28+ SpawnObjectTrackingComponent . SpawnedObjects = 0 ;
29+ SpawnObjectTrackingComponent . DespawnedObjects = 0 ;
30+ }
31+
2032 // Using this component assures we will know precisely how many prefabs were spawned on the client
2133 internal class SpawnObjectTrackingComponent : NetworkBehaviour
2234 {
2335 public static int SpawnedObjects ;
36+ public static int DespawnedObjects ;
37+
2438 public override void OnNetworkSpawn ( )
2539 {
2640 if ( ! IsOwner )
2741 {
2842 SpawnedObjects ++ ;
2943 }
3044 }
45+
46+ public override void OnNetworkDespawn ( )
47+ {
48+ if ( ! IsOwner )
49+ {
50+ DespawnedObjects ++ ;
51+ }
52+ }
3153 }
3254
3355 protected override void OnServerAndClientsCreated ( )
3456 {
35- SpawnObjectTrackingComponent . SpawnedObjects = 0 ;
57+ ResetTracking ( ) ;
3658 // create prefab
3759 var gameObject = new GameObject ( "TestObject" ) ;
3860 var networkObject = gameObject . AddComponent < NetworkObject > ( ) ;
@@ -44,14 +66,15 @@ protected override void OnServerAndClientsCreated()
4466
4567 foreach ( var client in m_NetworkManagers )
4668 {
69+ client . NetworkConfig . RecycleNetworkIds = true ;
70+ client . NetworkConfig . NetworkIdRecycleDelay = 0.01f ;
4771 client . NetworkConfig . Prefabs . Add ( m_PrefabToSpawn ) ;
4872 }
4973 }
5074
5175 [ UnityTest ]
5276 public IEnumerator WhenManyObjectsAreSpawnedAtOnce_AllAreReceived ( )
5377 {
54- var timeStarted = Time . realtimeSinceStartup ;
5578 var authority = GetAuthorityNetworkManager ( ) ;
5679 for ( int x = 0 ; x < k_SpawnedObjects ; x ++ )
5780 {
@@ -61,13 +84,66 @@ public IEnumerator WhenManyObjectsAreSpawnedAtOnce_AllAreReceived()
6184 serverObject . Spawn ( ) ;
6285 }
6386
64- var timeSpawned = Time . realtimeSinceStartup - timeStarted ;
65- // Provide plenty of time to spawn all 1500 objects in case the CI VM is running slow
6687 var timeoutHelper = new TimeoutHelper ( 30 ) ;
6788 // ensure all objects are replicated
6889 yield return WaitForConditionOrTimeOut ( ( ) => SpawnObjectTrackingComponent . SpawnedObjects == k_SpawnedObjects , timeoutHelper ) ;
90+ AssertOnTimeout ( $ "Timed out waiting for the client to spawn { k_SpawnedObjects } objects! expected: { k_SpawnedObjects } | have: { SpawnObjectTrackingComponent . SpawnedObjects } ", timeoutHelper ) ;
91+
92+ // Provide one full tick for all messages to finish being processed.
93+ // DANGO-TODO: Determine if this is only when testing against Rust server (i.e. messages still pending and clients shutting down before they are dequeued)
94+ // yield return s_DefaultWaitForTick;
95+ }
96+
97+ [ UnityTest , Performance ]
98+ public IEnumerator PerformanceWhenManyObjectsAreSpawnedAndDespawned ( )
99+ {
100+ var authority = GetAuthorityNetworkManager ( ) ;
101+ SampleGroup sampleGroup = new SampleGroup ( $ "ManyObjectsSpawnedAndDespawned") ;
102+ for ( var i = 0 ; i < 100 ; i ++ )
103+ {
104+ ResetTracking ( ) ;
105+ var objects = new NetworkObject [ k_SpawnedObjects ] ;
106+
107+ Stopwatch stopwatch = Stopwatch . StartNew ( ) ;
108+ for ( int x = 0 ; x < k_SpawnedObjects ; x ++ )
109+ {
110+ NetworkObject serverObject = Object . Instantiate ( m_PrefabToSpawn . Prefab ) . GetComponent < NetworkObject > ( ) ;
111+ serverObject . NetworkManagerOwner = authority ;
112+ serverObject . SpawnWithObservers = true ;
113+ serverObject . Spawn ( ) ;
114+ objects [ x ] = serverObject ;
115+
116+ if ( x % 100 == 0 )
117+ {
118+ yield return null ;
119+ }
120+ }
121+
122+ for ( int x = 0 ; x < k_SpawnedObjects ; x ++ )
123+ {
124+ var serverObject = objects [ x ] ;
125+ serverObject . Despawn ( ) ;
126+
127+ if ( x % 100 == 0 )
128+ {
129+ yield return null ;
130+ }
131+ }
132+
133+ // Provide plenty of time to spawn all objects in case the CI VM is running slow
134+ var timeoutHelper = new TimeoutHelper ( 30 ) ;
135+ // ensure all objects are replicated
136+ yield return WaitForConditionOrTimeOut ( ( ) => SpawnObjectTrackingComponent . SpawnedObjects == k_SpawnedObjects , timeoutHelper ) ;
137+ AssertOnTimeout ( $ "Timed out waiting for the client to spawn { k_SpawnedObjects } objects! expected: { k_SpawnedObjects } | have: { SpawnObjectTrackingComponent . SpawnedObjects } ", timeoutHelper ) ;
138+
139+ yield return WaitForConditionOrTimeOut ( ( ) => SpawnObjectTrackingComponent . DespawnedObjects == k_SpawnedObjects , timeoutHelper ) ;
140+ AssertOnTimeout ( $ "Timed out waiting for the client to despawn { k_SpawnedObjects } objects! expected: { k_SpawnedObjects } | have: { SpawnObjectTrackingComponent . DespawnedObjects } ", timeoutHelper ) ;
141+ stopwatch . Stop ( ) ;
142+ Measure . Custom ( sampleGroup , stopwatch . ElapsedMilliseconds ) ;
143+ yield return null ;
144+ }
69145
70- AssertOnTimeout ( $ "Timed out waiting for the client to spawn { k_SpawnedObjects } objects! Time to spawn: { timeSpawned } | Time to timeout: { timeStarted - Time . realtimeSinceStartup } " , timeoutHelper ) ;
146+ yield return s_DefaultWaitForTick ;
71147 }
72148 }
73149}
0 commit comments