1
1
using System . Collections ;
2
+ using System . Collections . Generic ;
2
3
using NUnit . Framework ;
3
4
using Unity . Netcode . TestHelpers . Runtime ;
4
5
using UnityEngine ;
@@ -21,56 +22,91 @@ internal class NetworkObjectDestroyTests : NetcodeIntegrationTest
21
22
{
22
23
protected override int NumberOfClients => 2 ;
23
24
24
- // TODO: [CmbServiceTests] Adapt to run with the service
25
- protected override bool UseCMBService ( )
25
+ public class DestroyTestComponent : NetworkBehaviour
26
26
{
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
+ }
28
34
}
29
35
30
36
public NetworkObjectDestroyTests ( NetworkTopologyTypes networkTopologyType ) : base ( networkTopologyType ) { }
31
37
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
+
32
46
protected override void OnCreatePlayerPrefab ( )
33
47
{
48
+ m_PlayerPrefab . AddComponent < DestroyTestComponent > ( ) ;
34
49
var playerNetworkObject = m_PlayerPrefab . GetComponent < NetworkObject > ( ) ;
35
50
playerNetworkObject . SceneMigrationSynchronization = true ;
36
51
base . OnCreatePlayerPrefab ( ) ;
37
52
}
38
53
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
+
39
83
/// <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 .
41
85
/// </summary>
42
- /// <returns></returns>
86
+ /// <returns>IEnumerator </returns>
43
87
[ UnityTest ]
44
88
public IEnumerator TestNetworkObjectAuthorityDestroy ( )
45
89
{
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 ) ;
49
90
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 ;
53
95
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 } !" ) ;
56
98
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 ] ;
69
105
70
- yield return NetcodeIntegrationTestHelpers . WaitForMessageOfTypeHandled < DestroyObjectMessage > ( targetNetworkManager ) ;
106
+ yield return NetcodeIntegrationTestHelpers . WaitForMessageOfTypeHandled < DestroyObjectMessage > ( messageListener ) ;
71
107
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 } " ) ;
74
110
75
111
// validate that any unspawned networkobject can be destroyed
76
112
var go = new GameObject ( ) ;
@@ -97,62 +133,47 @@ public enum ClientDestroyObject
97
133
public IEnumerator TestNetworkObjectClientDestroy ( [ Values ] ClientDestroyObject clientDestroyObject )
98
134
{
99
135
var isShuttingDown = clientDestroyObject == ClientDestroyObject . ShuttingDown ;
100
- var clientPlayer = m_ClientNetworkManagers [ 0 ] . LocalClient . PlayerObject ;
101
- var clientId = clientPlayer . OwnerClientId ;
102
136
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
+
104
144
if ( isShuttingDown )
105
145
{
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 ( ) ;
116
149
}
117
150
else
118
151
{
152
+ // The non-authority client is =NOT= allowed to destroy any spawned object it does not
153
+ // have authority over during runtime.
119
154
LogAssert . ignoreFailingMessages = true ;
120
- NetworkLog . NetworkManagerOverride = m_ClientNetworkManagers [ 0 ] ;
155
+ NetworkLog . NetworkManagerOverride = nonAuthorityClient ;
156
+ Object . Destroy ( clientPlayerClone . gameObject ) ;
121
157
}
122
158
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 ;
142
161
143
162
// destroying a NetworkObject while a session is active is not allowed
144
163
if ( ! isShuttingDown )
145
164
{
146
165
yield return WaitForConditionOrTimeOut ( HaveLogsBeenReceived ) ;
147
166
AssertOnTimeout ( $ "Not all expected logs were received when destroying a { nameof ( NetworkObject ) } on the client side during an active session!") ;
148
167
}
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
- }
153
168
else
154
169
{
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 ) } !") ;
156
177
}
157
178
}
158
179
@@ -183,8 +204,14 @@ private bool HaveLogsBeenReceived()
183
204
protected override IEnumerator OnTearDown ( )
184
205
{
185
206
NetworkLog . NetworkManagerOverride = null ;
186
- LogAssert . ignoreFailingMessages = false ;
187
207
return base . OnTearDown ( ) ;
188
208
}
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
+ }
189
216
}
190
217
}
0 commit comments