22using System . Collections . Generic ;
33using System . Linq ;
44using NUnit . Framework ;
5+ using Unity . Netcode . Components ;
56using Unity . Netcode . TestHelpers . Runtime ;
67using UnityEngine ;
78using UnityEngine . TestTools ;
@@ -23,11 +24,23 @@ public override void OnGainedOwnership()
2324 OnGainedOwnershipFired = true ;
2425 }
2526
27+ protected override void OnOwnershipChanged ( ulong previous , ulong current )
28+ {
29+ Assert . True ( previous != current , $ "[{ nameof ( OnOwnershipChanged ) } ][Invalid Parameters] Invoked and the previous ({ previous } ) equals the current ({ current } )!") ;
30+ base . OnOwnershipChanged ( previous , current ) ;
31+ }
32+
2633 public void ResetFlags ( )
2734 {
2835 OnLostOwnershipFired = false ;
2936 OnGainedOwnershipFired = false ;
3037 }
38+
39+ [ Rpc ( SendTo . Server ) ]
40+ public void ChangeOwnershipRpc ( RpcParams rpcParams = default )
41+ {
42+ NetworkObject . ChangeOwnership ( rpcParams . Receive . SenderClientId ) ;
43+ }
3144 }
3245
3346 [ TestFixture ( HostOrServer . Host ) ]
@@ -52,6 +65,7 @@ protected override void OnServerAndClientsCreated()
5265 {
5366 m_OwnershipPrefab = CreateNetworkObjectPrefab ( "OnwershipPrefab" ) ;
5467 m_OwnershipPrefab . AddComponent < NetworkObjectOwnershipComponent > ( ) ;
68+ m_OwnershipPrefab . AddComponent < NetworkTransform > ( ) ;
5569 base . OnServerAndClientsCreated ( ) ;
5670 }
5771
@@ -358,5 +372,75 @@ public IEnumerator TestOwnedObjectCounts()
358372 AssertOnTimeout ( $ "Server does not have the correct count for all clients spawned { k_NumberOfSpawnedObjects } { nameof ( NetworkObject ) } s!") ;
359373
360374 }
375+
376+ /// <summary>
377+ /// Validates that when changing ownership NetworkTransform does not enter into a bad state
378+ /// because the previous and current owner identifiers are the same. For client-server this
379+ /// ends up always being the server, but for distributed authority the authority changes when
380+ /// ownership changes.
381+ /// </summary>
382+ [ UnityTest ]
383+ public IEnumerator TestAuthorityChangingOwnership ( )
384+ {
385+ var authorityManager = m_ServerNetworkManager ; ;
386+ var allNetworkManagers = m_ClientNetworkManagers . ToList ( ) ;
387+ allNetworkManagers . Add ( m_ServerNetworkManager ) ;
388+
389+ m_OwnershipObject = SpawnObject ( m_OwnershipPrefab , m_ServerNetworkManager ) ;
390+ m_OwnershipNetworkObject = m_OwnershipObject . GetComponent < NetworkObject > ( ) ;
391+ var ownershipNetworkObjectId = m_OwnershipNetworkObject . NetworkObjectId ;
392+ bool WaitForClientsToSpawnNetworkObject ( )
393+ {
394+ foreach ( var clientNetworkManager in m_ClientNetworkManagers )
395+ {
396+ if ( ! clientNetworkManager . SpawnManager . SpawnedObjects . ContainsKey ( ownershipNetworkObjectId ) )
397+ {
398+ return false ;
399+ }
400+ }
401+ return true ;
402+ }
403+
404+ yield return WaitForConditionOrTimeOut ( WaitForClientsToSpawnNetworkObject ) ;
405+ AssertOnTimeout ( $ "Timed out waiting for all clients to spawn the { m_OwnershipNetworkObject . name } { nameof ( NetworkObject ) } instance!") ;
406+
407+ var currentTargetOwner = ( ulong ) 0 ;
408+ bool WaitForAllInstancesToChangeOwnership ( )
409+ {
410+ foreach ( var clientNetworkManager in m_ClientNetworkManagers )
411+ {
412+ if ( ! clientNetworkManager . SpawnManager . SpawnedObjects . ContainsKey ( ownershipNetworkObjectId ) )
413+ {
414+ return false ;
415+ }
416+ if ( clientNetworkManager . SpawnManager . SpawnedObjects [ ownershipNetworkObjectId ] . OwnerClientId != currentTargetOwner )
417+ {
418+ return false ;
419+ }
420+ }
421+ return true ;
422+ }
423+
424+ // Change ownership a few times and as long as the previous and current owners are not the same when
425+ // OnOwnershipChanged is invoked then the test passed.
426+ foreach ( var networkManager in allNetworkManagers )
427+ {
428+ if ( networkManager == authorityManager )
429+ {
430+ continue ;
431+ }
432+ var clonedObject = networkManager . SpawnManager . SpawnedObjects [ ownershipNetworkObjectId ] ;
433+
434+ if ( clonedObject . OwnerClientId == networkManager . LocalClientId )
435+ {
436+ continue ;
437+ }
438+
439+ var testComponent = clonedObject . GetComponent < NetworkObjectOwnershipComponent > ( ) ;
440+ testComponent . ChangeOwnershipRpc ( ) ;
441+ yield return WaitForAllInstancesToChangeOwnership ( ) ;
442+ AssertOnTimeout ( $ "Timed out waiting for all instances to change ownership to Client-{ networkManager . LocalClientId } !") ;
443+ }
444+ }
361445 }
362446}
0 commit comments