@@ -25,6 +25,7 @@ public AttachableBehaviourTests(HostOrServer hostOrServer) : base(hostOrServer)
2525        /// <summary> 
2626        /// All of the below instances belong to the authority 
2727        /// </summary> 
28+         private  ulong  m_TargetInstanceId ; 
2829        private  NetworkObject  m_SourceInstance ; 
2930        private  NetworkObject  m_TargetInstance ; 
3031        private  NetworkObject  m_TargetInstanceB ; 
@@ -47,6 +48,7 @@ protected override void OnServerAndClientsCreated()
4748            // The source prefab contains the nested NetworkBehaviour that 
4849            // will be parented under the target prefab. 
4950            m_SourcePrefab  =  CreateNetworkObjectPrefab ( "Source" ) ; 
51+             m_SourcePrefab . GetComponent < NetworkObject > ( ) . DontDestroyWithOwner  =  true ; 
5052            // The target prefab that the source prefab will attach 
5153            // will be parented under the target prefab. 
5254            m_TargetPrefabA  =  CreateNetworkObjectPrefab ( "TargetA" ) ; 
@@ -94,8 +96,11 @@ private bool ResetAllStates()
9496        { 
9597            m_ErrorLog . Clear ( ) ; 
9698            var  target  =  GetTargetInstance ( ) ; 
99+ 
100+ 
97101            // The attachable can move between the two spawned instances. 
98102            var  currentAttachableRoot  =  m_AttachableBehaviourInstance . State  ==  AttachableBehaviour . AttachState . Attached  ?  target  :  m_SourceInstance ; 
103+ 
99104            foreach  ( var  networkManager  in  m_NetworkManagers ) 
100105            { 
101106                // Source 
@@ -110,7 +115,7 @@ private bool ResetAllStates()
110115                } 
111116
112117                // Target 
113-                 if  ( ! networkManager . SpawnManager . SpawnedObjects . ContainsKey ( m_TargetInstance . NetworkObjectId ) ) 
118+                 if  ( m_TargetInstance   &&   ! networkManager . SpawnManager . SpawnedObjects . ContainsKey ( m_TargetInstance . NetworkObjectId ) ) 
114119                { 
115120                    m_ErrorLog . AppendLine ( $ "[Client-{ networkManager . LocalClientId } ] Has no spawned instance of { m_TargetInstance . name } !") ; 
116121                } 
@@ -121,7 +126,7 @@ private bool ResetAllStates()
121126                } 
122127
123128                // Target B 
124-                 if  ( ! networkManager . SpawnManager . SpawnedObjects . ContainsKey ( m_TargetInstanceB . NetworkObjectId ) ) 
129+                 if  ( m_TargetInstanceB   &&   ! networkManager . SpawnManager . SpawnedObjects . ContainsKey ( m_TargetInstanceB . NetworkObjectId ) ) 
125130                { 
126131                    m_ErrorLog . AppendLine ( $ "[Client-{ networkManager . LocalClientId } ] Has no spawned instance of { m_TargetInstanceB . name } !") ; 
127132                } 
@@ -134,10 +139,11 @@ private bool ResetAllStates()
134139            return  m_ErrorLog . Length  ==  0 ; 
135140        } 
136141
137-         private  bool  AllInstancesAttachedStateChanged ( bool  checkAttached ) 
142+         private  bool  AllInstancesAttachedStateChanged ( bool  checkAttached ,   bool   ignoreIfDespawned   =   false ) 
138143        { 
139144            m_ErrorLog . Clear ( ) ; 
140145            var  target  =  GetTargetInstance ( ) ; 
146+             var  targetId  =  target  ==  null  ?  m_TargetInstanceId  :  target . NetworkObjectId ; 
141147            // The attachable can move between the two spawned instances so we have to use the appropriate one depending upon the authority's current state. 
142148            var  currentAttachableRoot  =  m_AttachableBehaviourInstance . State  ==  AttachableBehaviour . AttachState . Attached  ?  target  :  m_SourceInstance ; 
143149            var  attachable  =  ( TestAttachable ) null ; 
@@ -146,7 +152,10 @@ private bool AllInstancesAttachedStateChanged(bool checkAttached)
146152            { 
147153                if  ( ! networkManager . SpawnManager . SpawnedObjects . ContainsKey ( currentAttachableRoot . NetworkObjectId ) ) 
148154                { 
149-                     m_ErrorLog . AppendLine ( $ "[Client-{ networkManager . LocalClientId } ] Has no spawned instance of { currentAttachableRoot . name } !") ; 
155+                     if  ( ! ignoreIfDespawned ) 
156+                     { 
157+                         m_ErrorLog . AppendLine ( $ "[Client-{ networkManager . LocalClientId } ] Has no spawned instance of { currentAttachableRoot . name } !") ; 
158+                     } 
150159                    continue ; 
151160                } 
152161                else 
@@ -156,7 +165,7 @@ private bool AllInstancesAttachedStateChanged(bool checkAttached)
156165
157166                if  ( ! attachable ) 
158167                { 
159-                     attachable  =  networkManager . SpawnManager . SpawnedObjects [ m_TargetInstance . NetworkObjectId ] . GetComponentInChildren < TestAttachable > ( ) ; 
168+                     attachable  =  networkManager . SpawnManager . SpawnedObjects [ m_TargetInstanceId ] . GetComponentInChildren < TestAttachable > ( ) ; 
160169                    if  ( ! attachable ) 
161170                    { 
162171                        attachable  =  networkManager . SpawnManager . SpawnedObjects [ m_TargetInstanceB . NetworkObjectId ] . GetComponentInChildren < TestAttachable > ( ) ; 
@@ -168,14 +177,23 @@ private bool AllInstancesAttachedStateChanged(bool checkAttached)
168177                    continue ; 
169178                } 
170179
171-                 if  ( ! networkManager . SpawnManager . SpawnedObjects . ContainsKey ( target . NetworkObjectId ) ) 
180+                 if  ( ! networkManager . SpawnManager . SpawnedObjects . ContainsKey ( targetId ) ) 
172181                { 
173-                     m_ErrorLog . AppendLine ( $ "[Client-{ networkManager . LocalClientId } ] Has no spawned instance of { target . name } !") ; 
182+                     if  ( ! ignoreIfDespawned ) 
183+                     { 
184+                         m_ErrorLog . AppendLine ( $ "[Client-{ networkManager . LocalClientId } ] Has no spawned instance of { target . name } !") ; 
185+                     } 
174186                    continue ; 
175187                } 
176188                else 
177189                { 
178-                     node  =  networkManager . SpawnManager . SpawnedObjects [ target . NetworkObjectId ] . GetComponentInChildren < TestNode > ( ) ; 
190+                     node  =  networkManager . SpawnManager . SpawnedObjects [ targetId ] . GetComponentInChildren < TestNode > ( ) ; 
191+                 } 
192+ 
193+                 if  ( ! node  &&  ignoreIfDespawned ) 
194+                 { 
195+                     VerboseDebug ( "Skipping check during despawn." ) ; 
196+                     continue ; 
179197                } 
180198
181199                if  ( ! attachable . CheckStateChangedOverride ( checkAttached ,  false ,  node ) ) 
@@ -202,13 +220,26 @@ private bool AllInstancesAttachedStateChanged(bool checkAttached)
202220            return  m_ErrorLog . Length  ==  0 ; 
203221        } 
204222
223+         private  bool  AllInstancesDespawned ( ) 
224+         { 
225+             foreach  ( var  networkManager  in  m_NetworkManagers ) 
226+             { 
227+                 if  ( networkManager . SpawnManager  !=  null  &&  networkManager . SpawnManager . SpawnedObjects . ContainsKey ( m_TargetInstanceId ) ) 
228+                 { 
229+                     return  false ; 
230+                 } 
231+             } 
232+             return  true ; 
233+         } 
234+ 
205235        [ UnityTest ] 
206236        public  IEnumerator  AttachAndDetachTests ( ) 
207237        { 
208238            var  authority  =  GetAuthorityNetworkManager ( ) ; 
209239            m_SourceInstance  =  SpawnObject ( m_SourcePrefab ,  authority ) . GetComponent < NetworkObject > ( ) ; 
210240            m_TargetInstance  =  SpawnObject ( m_TargetPrefabA ,  authority ) . GetComponent < NetworkObject > ( ) ; 
211241            m_TargetInstanceB  =  SpawnObject ( m_TargetPrefabB ,  authority ) . GetComponent < NetworkObject > ( ) ; 
242+             m_TargetInstanceId  =  m_TargetInstance . NetworkObjectId ; 
212243            yield  return  WaitForConditionOrTimeOut ( AllClientsSpawnedInstances ) ; 
213244            AssertOnTimeout ( $ "Timed out waiting for all clients to spawn { m_SourceInstance . name }  and { m_TargetInstance . name } !\n  { m_ErrorLog } ") ; 
214245
@@ -262,6 +293,26 @@ public IEnumerator AttachAndDetachTests()
262293            m_AttachableBehaviourInstance . Detach ( ) ; 
263294            yield  return  WaitForConditionOrTimeOut ( ( )  =>  AllInstancesAttachedStateChanged ( false ) ) ; 
264295            AssertOnTimeout ( $ "Timed out waiting for all clients to detach { m_AttachableBehaviourInstance . name }  from { m_AttachableNodeInstance . name } !\n  { m_ErrorLog } ") ; 
296+ 
297+             // Finally, re-attach to the original spawned instance 
298+             Assert . True ( ResetAllStates ( ) ,  $ "Failed to reset all states!\n  { m_ErrorLog } ") ; 
299+             m_AttachableBehaviourInstance . Attach ( m_AttachableNodeInstance ) ; 
300+ 
301+             // Switch back to using the first target attachable node 
302+             m_UseTargetB  =  false ; 
303+ 
304+             yield  return  WaitForConditionOrTimeOut ( ( )  =>  AllInstancesAttachedStateChanged ( true ) ) ; 
305+             AssertOnTimeout ( $ "[Despawn Detach Phase] Timed out waiting for all clients to attach { m_AttachableBehaviourInstance . name }  to { m_AttachableNodeInstance . name } !\n  { m_ErrorLog } ") ; 
306+ 
307+             var  targetInstanceName  =  m_TargetInstance . name ; 
308+             VerboseDebug ( "======== DESPAWN & DETACH ========" ) ; 
309+             m_TargetInstance . Despawn ( ) ; 
310+             m_TargetInstance  =  null ; 
311+             yield  return  WaitForConditionOrTimeOut ( ( )  =>  AllInstancesAttachedStateChanged ( false ,  true ) ) ; 
312+             AssertOnTimeout ( $ "[Despawn Detach Phase] Timed out waiting for all clients to detach { m_AttachableBehaviourInstance . name }  from { targetInstanceName } !\n  { m_ErrorLog } ") ; 
313+ 
314+             yield  return  WaitForConditionOrTimeOut ( AllInstancesDespawned ) ; 
315+             AssertOnTimeout ( $ "[Despawn Detach Phase] Timed out waiting for all clients to despawn { targetInstanceName } !") ; 
265316        } 
266317
267318        /// <summary> 
@@ -317,7 +368,6 @@ public bool CheckStateChangedOverride(bool checkAttached, bool checkEvent, Attac
317368                var  tableToCheck  =  checkEvent  ?  m_StateUpdateEvents  :  m_StateUpdates ; 
318369                var  checkStatus  =  checkAttached  ?  ( tableToCheck . ContainsKey ( AttachState . Attaching )  &&  tableToCheck . ContainsKey ( AttachState . Attached ) )  : 
319370                    ( tableToCheck . ContainsKey ( AttachState . Detaching )  &&  tableToCheck . ContainsKey ( AttachState . Detached ) ) ; 
320- 
321371                if  ( checkStatus ) 
322372                { 
323373                    foreach  ( var  entry  in  tableToCheck ) 
@@ -341,7 +391,9 @@ public bool CheckStateChangedOverride(bool checkAttached, bool checkEvent, Attac
341391                        } 
342392                        else  if  ( entry . Value  !=  attachableNode ) 
343393                        { 
344-                             Log ( $ "[{ entry . Key } ][Value] The value { entry . Value . name }  is not the same as { attachableNode . name } !") ; 
394+                             var  attachableName  =  attachableNode  ==  null  ?  "null"  :  attachableNode . name ; 
395+                             var  entryName  =  entry . Value  ==  null  ?  "null"  :  entry . Value . name ; 
396+                             Log ( $ "[{ entry . Key } ][Value] The value { entryName }  is not the same as { attachableName } !") ; 
345397                            checkStatus  =  false ; 
346398                            break ; 
347399                        } 
0 commit comments