11using System . Collections ;
2+ using System . Collections . Generic ;
3+ using System . Linq ;
24using NUnit . Framework ;
35using Unity . Netcode . TestHelpers . Runtime ;
46using UnityEngine ;
@@ -21,56 +23,91 @@ internal class NetworkObjectDestroyTests : NetcodeIntegrationTest
2123 {
2224 protected override int NumberOfClients => 2 ;
2325
24- // TODO: [CmbServiceTests] Adapt to run with the service
25- protected override bool UseCMBService ( )
26+ public class DestroyTestComponent : NetworkBehaviour
2627 {
27- return false ;
28+ public static List < string > ObjectsDestroyed = new List < string > ( ) ;
29+
30+ public override void OnDestroy ( )
31+ {
32+ ObjectsDestroyed . Add ( gameObject . name ) ;
33+ base . OnDestroy ( ) ;
34+ }
2835 }
2936
3037 public NetworkObjectDestroyTests ( NetworkTopologyTypes networkTopologyType ) : base ( networkTopologyType ) { }
3138
39+ protected override IEnumerator OnSetup ( )
40+ {
41+ // Re-apply the default for each test
42+ LogAssert . ignoreFailingMessages = false ;
43+ DestroyTestComponent . ObjectsDestroyed . Clear ( ) ;
44+ return base . OnSetup ( ) ;
45+ }
46+
3247 protected override void OnCreatePlayerPrefab ( )
3348 {
49+ m_PlayerPrefab . AddComponent < DestroyTestComponent > ( ) ;
3450 var playerNetworkObject = m_PlayerPrefab . GetComponent < NetworkObject > ( ) ;
3551 playerNetworkObject . SceneMigrationSynchronization = true ;
3652 base . OnCreatePlayerPrefab ( ) ;
3753 }
3854
55+ private NetworkManager GetAuthorityOfNetworkObject ( ulong networkObjectId )
56+ {
57+ foreach ( var networkManager in m_NetworkManagers )
58+ {
59+ if ( ! networkManager . SpawnManager . SpawnedObjects . ContainsKey ( networkObjectId ) )
60+ {
61+ continue ;
62+ }
63+
64+ if ( networkManager . SpawnManager . SpawnedObjects [ networkObjectId ] . HasAuthority )
65+ {
66+ return networkManager ;
67+ }
68+ }
69+ return null ;
70+ }
71+
72+ private bool NetworkObjectDoesNotExist ( ulong networkObjectId )
73+ {
74+ foreach ( var networkManager in m_NetworkManagers )
75+ {
76+ if ( networkManager . SpawnManager . SpawnedObjects . ContainsKey ( networkObjectId ) )
77+ {
78+ return false ;
79+ }
80+ }
81+ return true ;
82+ }
83+
3984 /// <summary>
40- /// Tests that a server can destroy a NetworkObject and that it gets despawned correctly .
85+ /// Tests that the authority NetworkManager instance of a NetworkObject is allowed to destroy it .
4186 /// </summary>
42- /// <returns></returns>
87+ /// <returns>IEnumerator </returns>
4388 [ UnityTest ]
4489 public IEnumerator TestNetworkObjectAuthorityDestroy ( )
4590 {
46- // This is the *SERVER VERSION* of the *CLIENT PLAYER*
47- var serverClientPlayerResult = new NetcodeIntegrationTestHelpers . ResultWrapper < NetworkObject > ( ) ;
48- yield return NetcodeIntegrationTestHelpers . GetNetworkObjectByRepresentation ( x => x . IsPlayerObject && x . OwnerClientId == m_ClientNetworkManagers [ 0 ] . LocalClientId , m_ServerNetworkManager , serverClientPlayerResult ) ;
4991
50- // This is the *CLIENT VERSION* of the *CLIENT PLAYER*
51- var clientClientPlayerResult = new NetcodeIntegrationTestHelpers . ResultWrapper < NetworkObject > ( ) ;
52- yield return NetcodeIntegrationTestHelpers . GetNetworkObjectByRepresentation ( x => x . IsPlayerObject && x . OwnerClientId == m_ClientNetworkManagers [ 0 ] . LocalClientId , m_ClientNetworkManagers [ 0 ] , clientClientPlayerResult ) ;
92+ var ownerNetworkManager = m_ClientNetworkManagers [ 1 ] ;
93+ var clientId = ownerNetworkManager . LocalClientId ;
94+ var localClientPlayer = ownerNetworkManager . LocalClient . PlayerObject ;
95+ var localNetworkObjectId = localClientPlayer . NetworkObjectId ;
5396
54- Assert . IsNotNull ( serverClientPlayerResult . Result . gameObject ) ;
55- Assert . IsNotNull ( clientClientPlayerResult . Result . gameObject ) ;
97+ var authorityNetworkManager = GetAuthorityOfNetworkObject ( localClientPlayer . NetworkObjectId ) ;
98+ Assert . True ( authorityNetworkManager != null , $ "Could not find the authority of { localClientPlayer } !" ) ;
5699
57- var targetNetworkManager = m_ClientNetworkManagers [ 0 ] ;
58- if ( m_DistributedAuthority )
59- {
60- targetNetworkManager = m_ClientNetworkManagers [ 1 ] ;
61- // destroy the authoritative player (distributed authority)
62- Object . Destroy ( clientClientPlayerResult . Result . gameObject ) ;
63- }
64- else
65- {
66- // destroy the authoritative player (client-server)
67- Object . Destroy ( serverClientPlayerResult . Result . gameObject ) ;
68- }
100+ var authorityPlayerClone = authorityNetworkManager . ConnectedClients [ clientId ] . PlayerObject ;
101+
102+ // Have the authority NetworkManager destroy the player instance
103+ Object . Destroy ( authorityPlayerClone . gameObject ) ;
104+
105+ var messageListener = m_DistributedAuthority ? m_ClientNetworkManagers [ 0 ] : m_ClientNetworkManagers [ 1 ] ;
69106
70- yield return NetcodeIntegrationTestHelpers . WaitForMessageOfTypeHandled < DestroyObjectMessage > ( targetNetworkManager ) ;
107+ yield return NetcodeIntegrationTestHelpers . WaitForMessageOfTypeHandled < DestroyObjectMessage > ( messageListener ) ;
71108
72- Assert . IsTrue ( serverClientPlayerResult . Result == null ) ; // Assert.IsNull doesn't work here
73- Assert . IsTrue ( clientClientPlayerResult . Result == null ) ;
109+ yield return WaitForConditionOrTimeOut ( ( ) => NetworkObjectDoesNotExist ( localNetworkObjectId ) ) ;
110+ AssertOnTimeout ( $ "Not all network managers despawned and destroyed player instance NetworkObjectId: { localNetworkObjectId } " ) ;
74111
75112 // validate that any unspawned networkobject can be destroyed
76113 var go = new GameObject ( ) ;
@@ -97,62 +134,47 @@ public enum ClientDestroyObject
97134 public IEnumerator TestNetworkObjectClientDestroy ( [ Values ] ClientDestroyObject clientDestroyObject )
98135 {
99136 var isShuttingDown = clientDestroyObject == ClientDestroyObject . ShuttingDown ;
100- var clientPlayer = m_ClientNetworkManagers [ 0 ] . LocalClient . PlayerObject ;
101- var clientId = clientPlayer . OwnerClientId ;
102137
103- //destroying a NetworkObject while shutting down is allowed
138+ var localNetworkManager = m_ClientNetworkManagers [ 1 ] ;
139+ var clientId = localNetworkManager . LocalClientId ;
140+ var localClientPlayer = localNetworkManager . LocalClient . PlayerObject ;
141+
142+ var nonAuthorityClient = m_ClientNetworkManagers [ 0 ] ;
143+ var clientPlayerClone = nonAuthorityClient . ConnectedClients [ clientId ] . PlayerObject ;
144+
104145 if ( isShuttingDown )
105146 {
106- if ( m_DistributedAuthority )
107- {
108- // Shutdown the 2nd client
109- m_ClientNetworkManagers [ 1 ] . Shutdown ( ) ;
110- }
111- else
112- {
113- // Shutdown the
114- m_ClientNetworkManagers [ 0 ] . Shutdown ( ) ;
115- }
147+ // The non-authority client is allowed to destroy any spawned object it does not
148+ // have authority over when it shuts down.
149+ nonAuthorityClient . Shutdown ( ) ;
116150 }
117151 else
118152 {
153+ // The non-authority client is =NOT= allowed to destroy any spawned object it does not
154+ // have authority over during runtime.
119155 LogAssert . ignoreFailingMessages = true ;
120- NetworkLog . NetworkManagerOverride = m_ClientNetworkManagers [ 0 ] ;
156+ NetworkLog . NetworkManagerOverride = nonAuthorityClient ;
157+ Object . Destroy ( clientPlayerClone . gameObject ) ;
121158 }
122159
123- m_ClientPlayerName = clientPlayer . gameObject . name ;
124- m_ClientNetworkObjectId = clientPlayer . NetworkObjectId ;
125- if ( m_DistributedAuthority )
126- {
127- m_ClientPlayerName = m_PlayerNetworkObjects [ m_ClientNetworkManagers [ 1 ] . LocalClientId ] [ m_ClientNetworkManagers [ 0 ] . LocalClientId ] . gameObject . name ;
128- m_ClientNetworkObjectId = m_PlayerNetworkObjects [ m_ClientNetworkManagers [ 1 ] . LocalClientId ] [ m_ClientNetworkManagers [ 0 ] . LocalClientId ] . NetworkObjectId ;
129-
130- if ( ! isShuttingDown )
131- {
132- NetworkLog . NetworkManagerOverride = m_ClientNetworkManagers [ 1 ] ;
133- }
134- // the 2nd client attempts to destroy the 1st client's player object (if shutting down then "ok" if not then not "ok")
135- Object . DestroyImmediate ( m_PlayerNetworkObjects [ m_ClientNetworkManagers [ 1 ] . LocalClientId ] [ m_ClientNetworkManagers [ 0 ] . LocalClientId ] . gameObject ) ;
136- }
137- else
138- {
139- // the 1st client attempts to destroy its own player object (if shutting down then "ok" if not then not "ok")
140- Object . DestroyImmediate ( m_ClientNetworkManagers [ 0 ] . LocalClient . PlayerObject . gameObject ) ;
141- }
160+ m_ClientPlayerName = clientPlayerClone . gameObject . name ;
161+ m_ClientNetworkObjectId = clientPlayerClone . NetworkObjectId ;
142162
143163 // destroying a NetworkObject while a session is active is not allowed
144164 if ( ! isShuttingDown )
145165 {
146166 yield return WaitForConditionOrTimeOut ( HaveLogsBeenReceived ) ;
147167 AssertOnTimeout ( $ "Not all expected logs were received when destroying a { nameof ( NetworkObject ) } on the client side during an active session!") ;
148168 }
149- if ( m_DistributedAuthority )
150- {
151- Assert . IsFalse ( m_ClientNetworkManagers [ 1 ] . SpawnManager . NetworkObjectsToSynchronizeSceneChanges . ContainsKey ( m_ClientNetworkObjectId ) , $ "Player object { m_ClientNetworkObjectId } still exists within { nameof ( NetworkSpawnManager . NetworkObjectsToSynchronizeSceneChanges ) } !") ;
152- }
153169 else
154170 {
155- Assert . IsFalse ( m_ClientNetworkManagers [ 0 ] . SpawnManager . NetworkObjectsToSynchronizeSceneChanges . ContainsKey ( m_ClientNetworkObjectId ) , $ "Player object { m_ClientNetworkObjectId } still exists within { nameof ( NetworkSpawnManager . NetworkObjectsToSynchronizeSceneChanges ) } !") ;
171+ bool NonAuthorityClientDestroyed ( )
172+ {
173+ return DestroyTestComponent . ObjectsDestroyed . Contains ( m_ClientPlayerName ) ;
174+ }
175+
176+ yield return WaitForConditionOrTimeOut ( NonAuthorityClientDestroyed ) ;
177+ AssertOnTimeout ( $ "Timed out waiting for player object { m_ClientNetworkObjectId } to no longer exist within { nameof ( NetworkSpawnManager . NetworkObjectsToSynchronizeSceneChanges ) } !") ;
156178 }
157179 }
158180
@@ -183,8 +205,14 @@ private bool HaveLogsBeenReceived()
183205 protected override IEnumerator OnTearDown ( )
184206 {
185207 NetworkLog . NetworkManagerOverride = null ;
186- LogAssert . ignoreFailingMessages = false ;
187208 return base . OnTearDown ( ) ;
188209 }
210+
211+ protected override void OnOneTimeTearDown ( )
212+ {
213+ // Re-apply the default as the last exiting action
214+ LogAssert . ignoreFailingMessages = false ;
215+ base . OnOneTimeTearDown ( ) ;
216+ }
189217 }
190218}
0 commit comments