11using System . Collections ;
2+ using System . Collections . Generic ;
23using NUnit . Framework ;
34using Unity . Netcode . TestHelpers . Runtime ;
45using UnityEngine ;
@@ -21,56 +22,91 @@ internal class NetworkObjectDestroyTests : NetcodeIntegrationTest
2122 {
2223 protected override int NumberOfClients => 2 ;
2324
24- // TODO: [CmbServiceTests] Adapt to run with the service
25- protected override bool UseCMBService ( )
25+ public class DestroyTestComponent : NetworkBehaviour
2626 {
27- return false ;
27+ public static List < string > ObjectsDestroyed = new List < string > ( ) ;
28+
29+ public override void OnDestroy ( )
30+ {
31+ ObjectsDestroyed . Add ( gameObject . name ) ;
32+ base . OnDestroy ( ) ;
33+ }
2834 }
2935
3036 public NetworkObjectDestroyTests ( NetworkTopologyTypes networkTopologyType ) : base ( networkTopologyType ) { }
3137
38+ protected override IEnumerator OnSetup ( )
39+ {
40+ // Re-apply the default for each test
41+ LogAssert . ignoreFailingMessages = false ;
42+ DestroyTestComponent . ObjectsDestroyed . Clear ( ) ;
43+ return base . OnSetup ( ) ;
44+ }
45+
3246 protected override void OnCreatePlayerPrefab ( )
3347 {
48+ m_PlayerPrefab . AddComponent < DestroyTestComponent > ( ) ;
3449 var playerNetworkObject = m_PlayerPrefab . GetComponent < NetworkObject > ( ) ;
3550 playerNetworkObject . SceneMigrationSynchronization = true ;
3651 base . OnCreatePlayerPrefab ( ) ;
3752 }
3853
54+ private NetworkManager GetAuthorityOfNetworkObject ( ulong networkObjectId )
55+ {
56+ foreach ( var networkManager in m_NetworkManagers )
57+ {
58+ if ( ! networkManager . SpawnManager . SpawnedObjects . ContainsKey ( networkObjectId ) )
59+ {
60+ continue ;
61+ }
62+
63+ if ( networkManager . SpawnManager . SpawnedObjects [ networkObjectId ] . HasAuthority )
64+ {
65+ return networkManager ;
66+ }
67+ }
68+ return null ;
69+ }
70+
71+ private bool NetworkObjectDoesNotExist ( ulong networkObjectId )
72+ {
73+ foreach ( var networkManager in m_NetworkManagers )
74+ {
75+ if ( networkManager . SpawnManager . SpawnedObjects . ContainsKey ( networkObjectId ) )
76+ {
77+ return false ;
78+ }
79+ }
80+ return true ;
81+ }
82+
3983 /// <summary>
40- /// Tests that a server can destroy a NetworkObject and that it gets despawned correctly .
84+ /// Tests that the authority NetworkManager instance of a NetworkObject is allowed to destroy it .
4185 /// </summary>
42- /// <returns></returns>
86+ /// <returns>IEnumerator </returns>
4387 [ UnityTest ]
4488 public IEnumerator TestNetworkObjectAuthorityDestroy ( )
4589 {
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 ) ;
4990
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 ) ;
91+ var ownerNetworkManager = m_ClientNetworkManagers [ 1 ] ;
92+ var clientId = ownerNetworkManager . LocalClientId ;
93+ var localClientPlayer = ownerNetworkManager . LocalClient . PlayerObject ;
94+ var localNetworkObjectId = localClientPlayer . NetworkObjectId ;
5395
54- Assert . IsNotNull ( serverClientPlayerResult . Result . gameObject ) ;
55- Assert . IsNotNull ( clientClientPlayerResult . Result . gameObject ) ;
96+ var authorityNetworkManager = GetAuthorityOfNetworkObject ( localClientPlayer . NetworkObjectId ) ;
97+ Assert . True ( authorityNetworkManager != null , $ "Could not find the authority of { localClientPlayer } !" ) ;
5698
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- }
99+ var authorityPlayerClone = authorityNetworkManager . ConnectedClients [ clientId ] . PlayerObject ;
100+
101+ // Have the authority NetworkManager destroy the player instance
102+ Object . Destroy ( authorityPlayerClone . gameObject ) ;
103+
104+ var messageListener = m_DistributedAuthority ? m_ClientNetworkManagers [ 0 ] : m_ClientNetworkManagers [ 1 ] ;
69105
70- yield return NetcodeIntegrationTestHelpers . WaitForMessageOfTypeHandled < DestroyObjectMessage > ( targetNetworkManager ) ;
106+ yield return NetcodeIntegrationTestHelpers . WaitForMessageOfTypeHandled < DestroyObjectMessage > ( messageListener ) ;
71107
72- Assert . IsTrue ( serverClientPlayerResult . Result == null ) ; // Assert.IsNull doesn't work here
73- Assert . IsTrue ( clientClientPlayerResult . Result == null ) ;
108+ yield return WaitForConditionOrTimeOut ( ( ) => NetworkObjectDoesNotExist ( localNetworkObjectId ) ) ;
109+ AssertOnTimeout ( $ "Not all network managers despawned and destroyed player instance NetworkObjectId: { localNetworkObjectId } " ) ;
74110
75111 // validate that any unspawned networkobject can be destroyed
76112 var go = new GameObject ( ) ;
@@ -97,62 +133,47 @@ public enum ClientDestroyObject
97133 public IEnumerator TestNetworkObjectClientDestroy ( [ Values ] ClientDestroyObject clientDestroyObject )
98134 {
99135 var isShuttingDown = clientDestroyObject == ClientDestroyObject . ShuttingDown ;
100- var clientPlayer = m_ClientNetworkManagers [ 0 ] . LocalClient . PlayerObject ;
101- var clientId = clientPlayer . OwnerClientId ;
102136
103- //destroying a NetworkObject while shutting down is allowed
137+ var localNetworkManager = m_ClientNetworkManagers [ 1 ] ;
138+ var clientId = localNetworkManager . LocalClientId ;
139+ var localClientPlayer = localNetworkManager . LocalClient . PlayerObject ;
140+
141+ var nonAuthorityClient = m_ClientNetworkManagers [ 0 ] ;
142+ var clientPlayerClone = nonAuthorityClient . ConnectedClients [ clientId ] . PlayerObject ;
143+
104144 if ( isShuttingDown )
105145 {
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- }
146+ // The non-authority client is allowed to destroy any spawned object it does not
147+ // have authority over when it shuts down.
148+ nonAuthorityClient . Shutdown ( ) ;
116149 }
117150 else
118151 {
152+ // The non-authority client is =NOT= allowed to destroy any spawned object it does not
153+ // have authority over during runtime.
119154 LogAssert . ignoreFailingMessages = true ;
120- NetworkLog . NetworkManagerOverride = m_ClientNetworkManagers [ 0 ] ;
155+ NetworkLog . NetworkManagerOverride = nonAuthorityClient ;
156+ Object . Destroy ( clientPlayerClone . gameObject ) ;
121157 }
122158
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- }
159+ m_ClientPlayerName = clientPlayerClone . gameObject . name ;
160+ m_ClientNetworkObjectId = clientPlayerClone . NetworkObjectId ;
142161
143162 // destroying a NetworkObject while a session is active is not allowed
144163 if ( ! isShuttingDown )
145164 {
146165 yield return WaitForConditionOrTimeOut ( HaveLogsBeenReceived ) ;
147166 AssertOnTimeout ( $ "Not all expected logs were received when destroying a { nameof ( NetworkObject ) } on the client side during an active session!") ;
148167 }
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- }
153168 else
154169 {
155- Assert . IsFalse ( m_ClientNetworkManagers [ 0 ] . SpawnManager . NetworkObjectsToSynchronizeSceneChanges . ContainsKey ( m_ClientNetworkObjectId ) , $ "Player object { m_ClientNetworkObjectId } still exists within { nameof ( NetworkSpawnManager . NetworkObjectsToSynchronizeSceneChanges ) } !") ;
170+ bool NonAuthorityClientDestroyed ( )
171+ {
172+ return DestroyTestComponent . ObjectsDestroyed . Contains ( m_ClientPlayerName ) ;
173+ }
174+
175+ yield return WaitForConditionOrTimeOut ( NonAuthorityClientDestroyed ) ;
176+ AssertOnTimeout ( $ "Timed out waiting for player object { m_ClientNetworkObjectId } to no longer exist within { nameof ( NetworkSpawnManager . NetworkObjectsToSynchronizeSceneChanges ) } !") ;
156177 }
157178 }
158179
@@ -183,8 +204,14 @@ private bool HaveLogsBeenReceived()
183204 protected override IEnumerator OnTearDown ( )
184205 {
185206 NetworkLog . NetworkManagerOverride = null ;
186- LogAssert . ignoreFailingMessages = false ;
187207 return base . OnTearDown ( ) ;
188208 }
209+
210+ protected override void OnOneTimeTearDown ( )
211+ {
212+ // Re-apply the default as the last exiting action
213+ LogAssert . ignoreFailingMessages = false ;
214+ base . OnOneTimeTearDown ( ) ;
215+ }
189216 }
190217}
0 commit comments