11using System . Collections ;
22using System . Text ;
3+ using NUnit . Framework ;
34using Unity . Netcode . Components ;
45using Unity . Netcode . TestHelpers . Runtime ;
56using UnityEngine ;
67using UnityEngine . TestTools ;
78
89namespace Unity . Netcode . RuntimeTests
910{
11+ [ TestFixture ( HostOrServer . Host , NetworkTransform . AuthorityModes . Server ) ]
12+ [ TestFixture ( HostOrServer . Host , NetworkTransform . AuthorityModes . Owner ) ]
13+ [ TestFixture ( HostOrServer . Server , NetworkTransform . AuthorityModes . Server ) ]
14+ [ TestFixture ( HostOrServer . Server , NetworkTransform . AuthorityModes . Owner ) ]
1015 internal class NetworkTransformMixedAuthorityTests : IntegrationTestWithApproximation
1116 {
1217 private const float k_MotionMagnitude = 5.5f ;
1318 private const int k_Iterations = 4 ;
1419
1520 protected override int NumberOfClients => 2 ;
1621
22+ private readonly NetworkTransform . AuthorityModes m_RootAuthorityMode ;
23+ private readonly NetworkTransform . AuthorityModes m_ChildAuthorityMode ;
24+
1725 private StringBuilder m_ErrorMsg = new StringBuilder ( ) ;
1826
27+ public NetworkTransformMixedAuthorityTests ( HostOrServer hostOrServer , NetworkTransform . AuthorityModes rootAuthorityMode ) : base ( hostOrServer )
28+ {
29+ m_RootAuthorityMode = rootAuthorityMode ;
30+ m_ChildAuthorityMode = rootAuthorityMode == NetworkTransform . AuthorityModes . Server ? NetworkTransform . AuthorityModes . Owner : NetworkTransform . AuthorityModes . Server ;
31+ }
32+
1933 protected override void OnCreatePlayerPrefab ( )
2034 {
21- m_PlayerPrefab . AddComponent < NetworkTransform > ( ) ;
35+ m_PlayerPrefab . AddComponent < NetworkTransform > ( ) . AuthorityMode = m_RootAuthorityMode ;
2236
2337 var childGameObject = new GameObject ( ) ;
2438 childGameObject . transform . parent = m_PlayerPrefab . transform ;
2539 var childNetworkTransform = childGameObject . AddComponent < NetworkTransform > ( ) ;
26- childNetworkTransform . AuthorityMode = NetworkTransform . AuthorityModes . Owner ;
40+ childNetworkTransform . AuthorityMode = m_ChildAuthorityMode ;
2741 childNetworkTransform . InLocalSpace = true ;
2842
2943 base . OnCreatePlayerPrefab ( ) ;
3044 }
3145
46+ /// <summary>
47+ /// Returns the instance of <paramref name="player"/>'s player object that has authority over a
48+ /// <see cref="NetworkTransform"/> using the <paramref name="authorityMode"/> authority mode.
49+ /// </summary>
50+ private NetworkObject GetAuthorityInstance ( NetworkManager player , NetworkTransform . AuthorityModes authorityMode )
51+ {
52+ var authority = authorityMode == NetworkTransform . AuthorityModes . Server ? m_ServerNetworkManager : player ;
53+ return authority . SpawnManager . SpawnedObjects [ player . LocalClient . PlayerObject . NetworkObjectId ] ;
54+ }
55+
3256 private void MovePlayers ( )
3357 {
34- foreach ( var networkManager in m_NetworkManagers )
58+ foreach ( var networkManager in m_ClientNetworkManagers )
3559 {
3660 var direction = GetRandomVector3 ( - 1.0f , 1.0f ) ;
37- var playerObject = networkManager . LocalClient . PlayerObject ;
38- var playerObjectId = networkManager . LocalClient . PlayerObject . NetworkObjectId ;
39- // Server authoritative
40- var serverPlayerClone = m_ServerNetworkManager . SpawnManager . SpawnedObjects [ playerObjectId ] ;
41- serverPlayerClone . transform . position += direction * k_MotionMagnitude ;
42- // Owner authoritative
43- var childTransform = networkManager . LocalClient . PlayerObject . transform . GetChild ( 0 ) ;
44- childTransform . localPosition += direction * k_MotionMagnitude ;
61+ GetAuthorityInstance ( networkManager , m_RootAuthorityMode ) . transform . position += direction * k_MotionMagnitude ;
62+ GetAuthorityInstance ( networkManager , m_ChildAuthorityMode ) . transform . GetChild ( 0 ) . localPosition += direction * k_MotionMagnitude ;
4563 }
4664 }
4765
4866 private bool AllInstancePositionsMatch ( )
4967 {
5068 m_ErrorMsg . Clear ( ) ;
51- foreach ( var networkManager in m_NetworkManagers )
69+ foreach ( var networkManager in m_ClientNetworkManagers )
5270 {
53- var playerObject = networkManager . LocalClient . PlayerObject ;
5471 var playerObjectId = networkManager . LocalClient . PlayerObject . NetworkObjectId ;
55- var serverRootPosition = m_ServerNetworkManager . SpawnManager . SpawnedObjects [ playerObjectId ] . transform . position ;
56- var ownerChildPosition = networkManager . LocalClient . PlayerObject . transform . GetChild ( 0 ) . localPosition ;
72+ var authorityRootPosition = GetAuthorityInstance ( networkManager , m_RootAuthorityMode ) . transform . position ;
73+ var authorityChildPosition = GetAuthorityInstance ( networkManager , m_ChildAuthorityMode ) . transform . GetChild ( 0 ) . localPosition ;
74+
75+ // The authority instances are compared too, as an instance with authority over one nested
76+ // NetworkTransform is still non-authority for the other.
5777 foreach ( var client in m_NetworkManagers )
5878 {
59- if ( client == networkManager )
60- {
61- continue ;
62- }
6379 var playerClone = client . SpawnManager . SpawnedObjects [ playerObjectId ] ;
6480 var cloneRootPosition = playerClone . transform . position ;
6581 var cloneChildPosition = playerClone . transform . GetChild ( 0 ) . localPosition ;
6682
67- if ( ! Approximately ( serverRootPosition , cloneRootPosition ) )
83+ if ( ! Approximately ( authorityRootPosition , cloneRootPosition ) )
6884 {
69- m_ErrorMsg . AppendLine ( $ "[{ playerObject . name } ][{ playerClone . name } ] Root mismatch ({ GetVector3Values ( serverRootPosition ) } )({ GetVector3Values ( cloneRootPosition ) } )!") ;
85+ m_ErrorMsg . AppendLine ( $ "[Client- { client . LocalClientId } ][{ playerClone . name } ] Root mismatch ({ GetVector3Values ( authorityRootPosition ) } )({ GetVector3Values ( cloneRootPosition ) } )!") ;
7086 }
7187
72- if ( ! Approximately ( ownerChildPosition , cloneChildPosition ) )
88+ if ( ! Approximately ( authorityChildPosition , cloneChildPosition ) )
7389 {
74- m_ErrorMsg . AppendLine ( $ "[{ playerObject . name } ][{ playerClone . name } ] Child mismatch ({ GetVector3Values ( ownerChildPosition ) } )({ GetVector3Values ( cloneChildPosition ) } )!") ;
90+ m_ErrorMsg . AppendLine ( $ "[Client- { client . LocalClientId } ][{ playerClone . name } ] Child mismatch ({ GetVector3Values ( authorityChildPosition ) } )({ GetVector3Values ( cloneChildPosition ) } )!") ;
7591 }
7692 }
7793 }
@@ -81,8 +97,8 @@ private bool AllInstancePositionsMatch()
8197 /// <summary>
8298 /// Client-Server Only
8399 /// Validates that mixed authority is working properly
84- /// Root -- Server Authoritative
85- /// |--Child -- Owner Authoritative
100+ /// Root -- Server or Owner authoritative
101+ /// |--Child -- The inverse of the root's authority mode
86102 /// </summary>
87103 [ UnityTest ]
88104 public IEnumerator MixedAuthorityTest ( )
@@ -91,7 +107,31 @@ public IEnumerator MixedAuthorityTest()
91107 {
92108 MovePlayers ( ) ;
93109 yield return WaitForConditionOrTimeOut ( AllInstancePositionsMatch ) ;
94- AssertOnTimeout ( $ "Transforms failed to synchronize!") ;
110+ AssertOnTimeout ( $ "Transforms failed to synchronize!\n { m_ErrorMsg } ") ;
111+ }
112+ }
113+
114+ /// <summary>
115+ /// The update registration is per-NetworkObject while the authority motion model is per-NetworkTransform,
116+ /// so an instance stays registered for as long as any one of its nested NetworkTransform components is
117+ /// non-authority.
118+ /// </summary>
119+ [ Test ]
120+ public void MixedAuthorityUpdateRegistration ( )
121+ {
122+ foreach ( var networkManager in m_ClientNetworkManagers )
123+ {
124+ var playerObjectId = networkManager . LocalClient . PlayerObject . NetworkObjectId ;
125+ foreach ( var client in m_NetworkManagers )
126+ {
127+ var playerClone = client . SpawnManager . SpawnedObjects [ playerObjectId ] ;
128+ var hasNonAuthority = false ;
129+ foreach ( var networkTransform in playerClone . NetworkTransforms )
130+ {
131+ hasNonAuthority |= ! networkTransform . CanCommitToTransform ;
132+ }
133+ Assert . AreEqual ( hasNonAuthority , client . NetworkTransformUpdate . ContainsKey ( playerObjectId ) , $ "[Client-{ client . LocalClientId } ][{ playerClone . name } ] Unexpected update registration!") ;
134+ }
95135 }
96136 }
97137 }
0 commit comments