@@ -15,27 +15,30 @@ namespace Unity.Netcode.RuntimeTests
1515 public static class MultiInstanceHelpers
1616 {
1717 public const int DefaultMinFrames = 1 ;
18- public const int DefaultMaxFrames = 64 ;
18+ public const float DefaultTimeout = 1f ;
1919 private static List < NetworkManager > s_NetworkManagerInstances = new List < NetworkManager > ( ) ;
2020 private static Dictionary < NetworkManager , MultiInstanceHooks > s_Hooks = new Dictionary < NetworkManager , MultiInstanceHooks > ( ) ;
2121 private static bool s_IsStarted ;
2222 private static int s_ClientCount ;
2323 private static int s_OriginalTargetFrameRate = - 1 ;
2424
25- public delegate bool MessageReceiptCheck ( object receivedMessage ) ;
25+ public delegate bool MessageHandleCheck ( object receivedMessage ) ;
2626
27- private class MultiInstanceHooks : INetworkHooks
27+ internal class MessageHandleCheckWithResult
2828 {
29- public bool IsWaiting ;
29+ public MessageHandleCheck Check ;
30+ public bool Result ;
31+ }
3032
31- public MessageReceiptCheck ReceiptCheck ;
33+ private class MultiInstanceHooks : INetworkHooks
34+ {
35+ public Dictionary < Type , List < MessageHandleCheckWithResult > > HandleChecks = new Dictionary < Type , List < MessageHandleCheckWithResult > > ( ) ;
3236
3337 public static bool CheckForMessageOfType < T > ( object receivedMessage ) where T : INetworkMessage
3438 {
35- return receivedMessage is T ;
39+ return receivedMessage . GetType ( ) == typeof ( T ) ;
3640 }
3741
38-
3942 public void OnBeforeSendMessage < T > ( ulong clientId , ref T message , NetworkDelivery delivery ) where T : INetworkMessage
4043 {
4144 }
@@ -84,9 +87,17 @@ public void OnBeforeHandleMessage<T>(ref T message, ref NetworkContext context)
8487
8588 public void OnAfterHandleMessage < T > ( ref T message , ref NetworkContext context ) where T : INetworkMessage
8689 {
87- if ( IsWaiting && ( ReceiptCheck == null || ReceiptCheck . Invoke ( message ) ) )
90+ if ( HandleChecks . ContainsKey ( typeof ( T ) ) )
8891 {
89- IsWaiting = false ;
92+ foreach ( var check in HandleChecks [ typeof ( T ) ] )
93+ {
94+ if ( check . Check ( message ) )
95+ {
96+ check . Result = true ;
97+ HandleChecks [ typeof ( T ) ] . Remove ( check ) ;
98+ break ;
99+ }
100+ }
90101 }
91102 }
92103 }
@@ -471,9 +482,9 @@ public static void MarkAsSceneObjectRoot(GameObject networkObjectRoot, NetworkMa
471482 /// <param name="client">The client</param>
472483 /// <param name="result">The result. If null, it will automatically assert</param>
473484 /// <param name="maxFrames">The max frames to wait for</param>
474- public static IEnumerator WaitForClientConnected ( NetworkManager client , CoroutineResultWrapper < bool > result = null , int maxFrames = DefaultMaxFrames )
485+ public static IEnumerator WaitForClientConnected ( NetworkManager client , CoroutineResultWrapper < bool > result = null , float timeout = DefaultTimeout )
475486 {
476- yield return WaitForClientsConnected ( new NetworkManager [ ] { client } , result , maxFrames ) ;
487+ yield return WaitForClientsConnected ( new NetworkManager [ ] { client } , result , timeout ) ;
477488 }
478489
479490 /// <summary>
@@ -483,7 +494,7 @@ public static IEnumerator WaitForClientConnected(NetworkManager client, Coroutin
483494 /// <param name="result">The result. If null, it will automatically assert<</param>
484495 /// <param name="maxFrames">The max frames to wait for</param>
485496 /// <returns></returns>
486- public static IEnumerator WaitForClientsConnected ( NetworkManager [ ] clients , CoroutineResultWrapper < bool > result = null , int maxFrames = DefaultMaxFrames )
497+ public static IEnumerator WaitForClientsConnected ( NetworkManager [ ] clients , CoroutineResultWrapper < bool > result = null , float timeout = DefaultTimeout )
487498 {
488499 // Make sure none are the host client
489500 foreach ( var client in clients )
@@ -494,9 +505,10 @@ public static IEnumerator WaitForClientsConnected(NetworkManager[] clients, Coro
494505 }
495506 }
496507
497- var startFrameNumber = Time . frameCount ;
498508 var allConnected = true ;
499- while ( Time . frameCount - startFrameNumber <= maxFrames )
509+ var startTime = Time . realtimeSinceStartup ;
510+
511+ while ( Time . realtimeSinceStartup - startTime < timeout )
500512 {
501513 allConnected = true ;
502514 foreach ( var client in clients )
@@ -537,9 +549,9 @@ public static IEnumerator WaitForClientsConnected(NetworkManager[] clients, Coro
537549 /// <param name="server">The server</param>
538550 /// <param name="result">The result. If null, it will automatically assert</param>
539551 /// <param name="maxFrames">The max frames to wait for</param>
540- public static IEnumerator WaitForClientConnectedToServer ( NetworkManager server , CoroutineResultWrapper < bool > result = null , int maxFrames = DefaultMaxFrames )
552+ public static IEnumerator WaitForClientConnectedToServer ( NetworkManager server , CoroutineResultWrapper < bool > result = null , float timeout = DefaultTimeout )
541553 {
542- yield return WaitForClientsConnectedToServer ( server , server . IsHost ? s_ClientCount + 1 : s_ClientCount , result , maxFrames ) ;
554+ yield return WaitForClientsConnectedToServer ( server , server . IsHost ? s_ClientCount + 1 : s_ClientCount , result , timeout ) ;
543555 }
544556
545557 /// <summary>
@@ -548,16 +560,16 @@ public static IEnumerator WaitForClientConnectedToServer(NetworkManager server,
548560 /// <param name="server">The server</param>
549561 /// <param name="result">The result. If null, it will automatically assert</param>
550562 /// <param name="maxFrames">The max frames to wait for</param>
551- public static IEnumerator WaitForClientsConnectedToServer ( NetworkManager server , int clientCount = 1 , CoroutineResultWrapper < bool > result = null , int maxFrames = DefaultMaxFrames )
563+ public static IEnumerator WaitForClientsConnectedToServer ( NetworkManager server , int clientCount = 1 , CoroutineResultWrapper < bool > result = null , float timeout = DefaultTimeout )
552564 {
553565 if ( ! server . IsServer )
554566 {
555567 throw new InvalidOperationException ( "Cannot wait for connected as client" ) ;
556568 }
557569
558- var startFrameNumber = Time . frameCount ;
570+ var startTime = Time . realtimeSinceStartup ;
559571
560- while ( Time . frameCount - startFrameNumber <= maxFrames && server . ConnectedClients . Count != clientCount )
572+ while ( Time . realtimeSinceStartup - startTime < timeout && server . ConnectedClients . Count != clientCount )
561573 {
562574 var nextFrameNumber = Time . frameCount + 1 ;
563575 yield return new WaitUntil ( ( ) => Time . frameCount >= nextFrameNumber ) ;
@@ -583,16 +595,16 @@ public static IEnumerator WaitForClientsConnectedToServer(NetworkManager server,
583595 /// <param name="result">The result</param>
584596 /// <param name="failIfNull">Whether or not to fail if no object is found and result is null</param>
585597 /// <param name="maxFrames">The max frames to wait for</param>
586- public static IEnumerator GetNetworkObjectByRepresentation ( ulong networkObjectId , NetworkManager representation , CoroutineResultWrapper < NetworkObject > result , bool failIfNull = true , int maxFrames = DefaultMaxFrames )
598+ public static IEnumerator GetNetworkObjectByRepresentation ( ulong networkObjectId , NetworkManager representation , CoroutineResultWrapper < NetworkObject > result , bool failIfNull = true , float timeout = DefaultTimeout )
587599 {
588600 if ( result == null )
589601 {
590602 throw new ArgumentNullException ( "Result cannot be null" ) ;
591603 }
592604
593- var startFrameNumber = Time . frameCount ;
605+ var startTime = Time . realtimeSinceStartup ;
594606
595- while ( Time . frameCount - startFrameNumber <= maxFrames && representation . SpawnManager . SpawnedObjects . All ( x => x . Value . NetworkObjectId != networkObjectId ) )
607+ while ( Time . realtimeSinceStartup - startTime < timeout && representation . SpawnManager . SpawnedObjects . All ( x => x . Value . NetworkObjectId != networkObjectId ) )
596608 {
597609 var nextFrameNumber = Time . frameCount + 1 ;
598610 yield return new WaitUntil ( ( ) => Time . frameCount >= nextFrameNumber ) ;
@@ -614,7 +626,7 @@ public static IEnumerator GetNetworkObjectByRepresentation(ulong networkObjectId
614626 /// <param name="result">The result</param>
615627 /// <param name="failIfNull">Whether or not to fail if no object is found and result is null</param>
616628 /// <param name="maxFrames">The max frames to wait for</param>
617- public static IEnumerator GetNetworkObjectByRepresentation ( Func < NetworkObject , bool > predicate , NetworkManager representation , CoroutineResultWrapper < NetworkObject > result , bool failIfNull = true , int maxFrames = DefaultMaxFrames )
629+ public static IEnumerator GetNetworkObjectByRepresentation ( Func < NetworkObject , bool > predicate , NetworkManager representation , CoroutineResultWrapper < NetworkObject > result , bool failIfNull = true , float timeout = DefaultTimeout )
618630 {
619631 if ( result == null )
620632 {
@@ -626,9 +638,9 @@ public static IEnumerator GetNetworkObjectByRepresentation(Func<NetworkObject, b
626638 throw new ArgumentNullException ( "Predicate cannot be null" ) ;
627639 }
628640
629- var startFrame = Time . frameCount ;
641+ var startTime = Time . realtimeSinceStartup ;
630642
631- while ( Time . frameCount - startFrame <= maxFrames && ! representation . SpawnManager . SpawnedObjects . Any ( x => predicate ( x . Value ) ) )
643+ while ( Time . realtimeSinceStartup - startTime < timeout && ! representation . SpawnManager . SpawnedObjects . Any ( x => predicate ( x . Value ) ) )
632644 {
633645 var nextFrameNumber = Time . frameCount + 1 ;
634646 yield return new WaitUntil ( ( ) => Time . frameCount >= nextFrameNumber ) ;
@@ -648,15 +660,15 @@ public static IEnumerator GetNetworkObjectByRepresentation(Func<NetworkObject, b
648660 /// <param name="workload">Action / code to run</param>
649661 /// <param name="predicate">The predicate to wait for</param>
650662 /// <param name="maxFrames">The max frames to wait for</param>
651- public static IEnumerator RunAndWaitForCondition ( Action workload , Func < bool > predicate , int maxFrames = DefaultMaxFrames , int minFrames = DefaultMinFrames )
663+ public static IEnumerator RunAndWaitForCondition ( Action workload , Func < bool > predicate , float timeout = DefaultTimeout , int minFrames = DefaultMinFrames )
652664 {
653665 var waitResult = new CoroutineResultWrapper < bool > ( ) ;
654666 workload ( ) ;
655667
656668 yield return Run ( WaitForCondition (
657669 predicate ,
658670 waitResult ,
659- maxFrames : maxFrames ,
671+ timeout : timeout ,
660672 minFrames : minFrames ) ) ;
661673
662674 if ( ! waitResult . Result )
@@ -672,33 +684,26 @@ public static IEnumerator RunAndWaitForCondition(Action workload, Func<bool> pre
672684 /// <param name="result">The result. If null, it will fail if the predicate is not met</param>
673685 /// <param name="minFrames">The min frames to wait for</param>
674686 /// <param name="maxFrames">The max frames to wait for</param>
675- public static IEnumerator WaitForCondition ( Func < bool > predicate , CoroutineResultWrapper < bool > result = null , int maxFrames = DefaultMaxFrames , int minFrames = DefaultMinFrames )
687+ public static IEnumerator WaitForCondition ( Func < bool > predicate , CoroutineResultWrapper < bool > result = null , float timeout = DefaultTimeout , int minFrames = DefaultMinFrames )
676688 {
677689 if ( predicate == null )
678690 {
679691 throw new ArgumentNullException ( "Predicate cannot be null" ) ;
680692 }
681693
682- var startFrameNumber = Time . frameCount ;
694+ var startTime = Time . realtimeSinceStartup ;
683695
684696 if ( minFrames > 0 )
685697 {
686- yield return new WaitUntil ( ( ) =>
687- {
688- return Time . frameCount >= minFrames ;
689- } ) ;
698+ yield return new WaitUntil ( ( ) => Time . frameCount >= minFrames ) ;
690699 }
691700
692- while ( Time . frameCount - startFrameNumber <= maxFrames &&
693- ! predicate ( ) )
701+ while ( Time . realtimeSinceStartup - startTime < timeout && ! predicate ( ) )
694702 {
695703 // Changed to 2 frames to avoid the scenario where it would take 1+ frames to
696704 // see a value change (i.e. discovered in the NetworkTransformTests)
697705 var nextFrameNumber = Time . frameCount + 2 ;
698- yield return new WaitUntil ( ( ) =>
699- {
700- return Time . frameCount >= nextFrameNumber ;
701- } ) ;
706+ yield return new WaitUntil ( ( ) => Time . frameCount >= nextFrameNumber ) ;
702707 }
703708
704709 var res = predicate ( ) ;
@@ -721,12 +726,17 @@ public static IEnumerator WaitForCondition(Func<bool> predicate, CoroutineResult
721726 internal static IEnumerator WaitForMessageOfType < T > ( NetworkManager toBeReceivedBy , CoroutineResultWrapper < bool > result = null , float timeout = 0.5f ) where T : INetworkMessage
722727 {
723728 var hooks = s_Hooks [ toBeReceivedBy ] ;
724- hooks . ReceiptCheck = MultiInstanceHooks . CheckForMessageOfType < T > ;
729+ if ( ! hooks . HandleChecks . ContainsKey ( typeof ( T ) ) )
730+ {
731+ hooks . HandleChecks . Add ( typeof ( T ) , new List < MessageHandleCheckWithResult > ( ) ) ;
732+ }
733+ var check = new MessageHandleCheckWithResult { Check = MultiInstanceHooks . CheckForMessageOfType < T > } ;
734+ hooks . HandleChecks [ typeof ( T ) ] . Add ( check ) ;
725735 if ( result == null )
726736 {
727737 result = new CoroutineResultWrapper < bool > ( ) ;
728738 }
729- yield return ExecuteWaitForHook ( hooks , result , timeout ) ;
739+ yield return ExecuteWaitForHook ( check , result , timeout ) ;
730740
731741 Assert . True ( result . Result , $ "Expected message { typeof ( T ) . Name } was not received within { timeout } s.") ;
732742 }
@@ -737,33 +747,34 @@ internal static IEnumerator WaitForMessageOfType<T>(NetworkManager toBeReceivedB
737747 /// <param name="requirement">Called for each received message to check if it's the right one</param>
738748 /// <param name="result">The result. If null, it will fail if the predicate is not met</param>
739749 /// <param name="timeout">The max time in seconds to wait for</param>
740- internal static IEnumerator WaitForMessageMeetingRequirement ( NetworkManager toBeReceivedBy , MessageReceiptCheck requirement , CoroutineResultWrapper < bool > result = null , float timeout = 0.5f )
750+ internal static IEnumerator WaitForMessageMeetingRequirement < T > ( NetworkManager toBeReceivedBy , MessageHandleCheck requirement , CoroutineResultWrapper < bool > result = null , float timeout = DefaultTimeout )
741751 {
742752 var hooks = s_Hooks [ toBeReceivedBy ] ;
743- hooks . ReceiptCheck = requirement ;
753+ if ( ! hooks . HandleChecks . ContainsKey ( typeof ( T ) ) )
754+ {
755+ hooks . HandleChecks . Add ( typeof ( T ) , new List < MessageHandleCheckWithResult > ( ) ) ;
756+ }
757+ var check = new MessageHandleCheckWithResult { Check = requirement } ;
758+ hooks . HandleChecks [ typeof ( T ) ] . Add ( check ) ;
744759 if ( result == null )
745760 {
746761 result = new CoroutineResultWrapper < bool > ( ) ;
747762 }
748- yield return ExecuteWaitForHook ( hooks , result , timeout ) ;
763+ yield return ExecuteWaitForHook ( check , result , timeout ) ;
749764
750765 Assert . True ( result . Result , $ "Expected message meeting user requirements was not received within { timeout } s.") ;
751766 }
752767
753- private static IEnumerator ExecuteWaitForHook ( MultiInstanceHooks hooks , CoroutineResultWrapper < bool > result , float timeout )
768+ private static IEnumerator ExecuteWaitForHook ( MessageHandleCheckWithResult check , CoroutineResultWrapper < bool > result , float timeout )
754769 {
755- hooks . IsWaiting = true ;
756-
757770 var startTime = Time . realtimeSinceStartup ;
758771
759- while ( hooks . IsWaiting && Time . realtimeSinceStartup - startTime < timeout )
772+ while ( ! check . Result && Time . realtimeSinceStartup - startTime < timeout )
760773 {
761774 yield return null ;
762775 }
763776
764- var res = ! hooks . IsWaiting ;
765- hooks . IsWaiting = false ;
766- hooks . ReceiptCheck = null ;
777+ var res = check . Result ;
767778 result . Result = res ;
768779 }
769780
0 commit comments