@@ -168,7 +168,7 @@ internal void EndSendClientRpc(BitWriter writer, ClientRpcSendParams sendParams,
168168 /// <summary>
169169 /// Gets if we are executing as server
170170 /// </summary>
171- protected bool IsServer => IsRunning && NetworkingManager . Singleton . IsServer ;
171+ protected static bool IsServer => IsRunning && NetworkingManager . Singleton . IsServer ;
172172 /// <summary>
173173 /// Gets if we are executing as client
174174 /// </summary>
@@ -189,7 +189,7 @@ internal void EndSendClientRpc(BitWriter writer, ClientRpcSendParams sendParams,
189189 /// Gets if we are executing as Host, I.E Server and Client
190190 /// </summary>
191191 protected bool IsHost => IsRunning && NetworkingManager . Singleton . IsHost ;
192- private bool IsRunning => NetworkingManager . Singleton != null && NetworkingManager . Singleton . IsListening ;
192+ private static bool IsRunning => NetworkingManager . Singleton != null && NetworkingManager . Singleton . IsListening ;
193193 /// <summary>
194194 /// Gets Whether or not the object has a owner
195195 /// </summary>
@@ -324,6 +324,7 @@ protected NetworkedBehaviour GetBehaviour(ushort id)
324324 private readonly List < string > channelsForNetworkedVarGroups = new List < string > ( ) ;
325325 internal readonly List < INetworkedVar > networkedVarFields = new List < INetworkedVar > ( ) ;
326326
327+ private static HashSet < MLAPI . NetworkedObject > touched = new HashSet < MLAPI . NetworkedObject > ( ) ;
327328 private static readonly Dictionary < Type , FieldInfo [ ] > fieldTypes = new Dictionary < Type , FieldInfo [ ] > ( ) ;
328329
329330 private static FieldInfo [ ] GetFieldInfoForType ( Type type )
@@ -409,122 +410,194 @@ internal void InitializeVars()
409410 }
410411 }
411412
412- internal void VarUpdate ( )
413+ #if DEVELOPMENT_BUILD || UNITY_EDITOR
414+ public static ProfilerMarker s_NetworkedBehaviourUpdate = new ProfilerMarker ( "MLAPI.NetworkedObject.NetworkedBehaviourUpdate" ) ;
415+ #endif
416+
417+ internal static void NetworkedBehaviourUpdate ( )
418+ {
419+ #if DEVELOPMENT_BUILD || UNITY_EDITOR
420+ s_NetworkedBehaviourUpdate . Begin ( ) ;
421+ #endif
422+ try
423+ {
424+ if ( IsServer )
425+ {
426+ touched . Clear ( ) ;
427+ for ( int i = 0 ; i < NetworkingManager . Singleton . ConnectedClientsList . Count ; i ++ )
428+ {
429+ var client = NetworkingManager . Singleton . ConnectedClientsList [ i ] ;
430+ var spawnedObjs = SpawnManager . SpawnedObjectsList ;
431+ touched . UnionWith ( spawnedObjs ) ;
432+ foreach ( var sobj in spawnedObjs )
433+ {
434+ // Sync just the variables for just the objects this client sees
435+ for ( int k = 0 ; k < sobj . childNetworkedBehaviours . Count ; k ++ )
436+ {
437+ sobj . childNetworkedBehaviours [ k ] . VarUpdate ( client . ClientId ) ;
438+ }
439+ }
440+ }
441+
442+ // Now, reset all the no-longer-dirty variables
443+ foreach ( var sobj in touched )
444+ {
445+ for ( int k = 0 ; k < sobj . childNetworkedBehaviours . Count ; k ++ )
446+ {
447+ sobj . childNetworkedBehaviours [ k ] . PostNetworkVariableWrite ( ) ;
448+ }
449+ }
450+ }
451+ else
452+ {
453+
454+ // when client updates the sever, it tells it about all its objects
455+ foreach ( var sobj in SpawnManager . SpawnedObjectsList )
456+ {
457+ for ( int k = 0 ; k < sobj . childNetworkedBehaviours . Count ; k ++ )
458+ {
459+ sobj . childNetworkedBehaviours [ k ] . VarUpdate ( NetworkingManager . Singleton . ServerClientId ) ;
460+ }
461+ }
462+
463+ // Now, reset all the no-longer-dirty variables
464+ foreach ( var sobj in SpawnManager . SpawnedObjectsList )
465+ {
466+ for ( int k = 0 ; k < sobj . childNetworkedBehaviours . Count ; k ++ )
467+ {
468+ sobj . childNetworkedBehaviours [ k ] . PostNetworkVariableWrite ( ) ;
469+ }
470+ }
471+ }
472+
473+ }
474+ finally
475+ {
476+ #if DEVELOPMENT_BUILD || UNITY_EDITOR
477+ s_NetworkedBehaviourUpdate . End ( ) ;
478+ #endif
479+ }
480+ }
481+
482+
483+ internal void PreNetworkVariableWrite ( )
484+ {
485+ // reset our "which variables got written" data
486+ networkedVarIndexesToReset . Clear ( ) ;
487+ networkedVarIndexesToResetSet . Clear ( ) ;
488+ }
489+
490+ internal void PostNetworkVariableWrite ( )
491+ {
492+ // mark any variables we wrote as no longer dirty
493+ for ( int i = 0 ; i < networkedVarIndexesToReset . Count ; i ++ )
494+ {
495+ networkedVarFields [ networkedVarIndexesToReset [ i ] ] . ResetDirty ( ) ;
496+ }
497+ }
498+
499+ internal void VarUpdate ( ulong clientId )
413500 {
414501 if ( ! varInit )
415502 InitializeVars ( ) ;
416503
417- NetworkedVarUpdate ( ) ;
504+ PreNetworkVariableWrite ( ) ;
505+ NetworkedVarUpdate ( clientId ) ;
418506 }
419507
420508 private readonly List < int > networkedVarIndexesToReset = new List < int > ( ) ;
421509 private readonly HashSet < int > networkedVarIndexesToResetSet = new HashSet < int > ( ) ;
422510
423- private void NetworkedVarUpdate ( )
511+ private void NetworkedVarUpdate ( ulong clientId )
424512 {
425- if ( ! CouldHaveDirtyNetworkedVars ( ) )
426- return ;
513+ if ( ! CouldHaveDirtyNetworkedVars ( ) )
514+ return ;
427515
428- networkedVarIndexesToReset . Clear ( ) ;
429- networkedVarIndexesToResetSet . Clear ( ) ;
430-
431- for ( int i = 0 ; i < ( IsServer ? NetworkingManager . Singleton . ConnectedClientsList . Count : 1 ) ; i ++ )
516+ for ( int j = 0 ; j < channelMappedNetworkedVarIndexes . Count ; j ++ )
432517 {
433- // Do this check here to prevent doing all the expensive dirty checks
434- if ( ! IsServer || this . NetworkedObject . observers . Contains ( NetworkingManager . Singleton . ConnectedClientsList [ i ] . ClientId ) )
518+ using ( PooledBitStream stream = PooledBitStream . Get ( ) )
435519 {
436- // This iterates over every "channel group".
437- for ( int j = 0 ; j < channelMappedNetworkedVarIndexes . Count ; j ++ )
520+ using ( PooledBitWriter writer = PooledBitWriter . Get ( stream ) )
438521 {
439- using ( PooledBitStream stream = PooledBitStream . Get ( ) )
522+ writer . WriteUInt64Packed ( NetworkId ) ;
523+ writer . WriteUInt16Packed ( NetworkedObject . GetOrderIndex ( this ) ) ;
524+
525+ bool writtenAny = false ;
526+ for ( int k = 0 ; k < networkedVarFields . Count ; k ++ )
440527 {
441- using ( PooledBitWriter writer = PooledBitWriter . Get ( stream ) )
528+ if ( ! channelMappedNetworkedVarIndexes [ j ] . Contains ( k ) )
442529 {
443- writer . WriteUInt64Packed ( NetworkId ) ;
444- writer . WriteUInt16Packed ( NetworkedObject . GetOrderIndex ( this ) ) ;
530+ // This var does not belong to the currently iterating channel group.
531+ if ( NetworkingManager . Singleton . NetworkConfig . EnsureNetworkedVarLengthSafety )
532+ {
533+ writer . WriteUInt16Packed ( 0 ) ;
534+ }
535+ else
536+ {
537+ writer . WriteBool ( false ) ;
538+ }
539+ continue ;
540+ }
541+
542+ bool isDirty = networkedVarFields [ k ] . IsDirty ( ) ; // cache this here. You never know what operations users will do in the dirty methods
445543
446- ulong clientId = IsServer ? NetworkingManager . Singleton . ConnectedClientsList [ i ] . ClientId : NetworkingManager . Singleton . ServerClientId ;
447- bool writtenAny = false ;
448- for ( int k = 0 ; k < networkedVarFields . Count ; k ++ )
544+ // if I'm dirty AND a client, write (server always has all permissions)
545+ // if I'm dirty AND the server AND the client can read me, send.
546+ bool shouldWrite = isDirty && ( ! IsServer || networkedVarFields [ k ] . CanClientRead ( clientId ) ) ;
547+
548+ if ( NetworkingManager . Singleton . NetworkConfig . EnsureNetworkedVarLengthSafety )
549+ {
550+ if ( ! shouldWrite )
449551 {
450- if ( ! channelMappedNetworkedVarIndexes [ j ] . Contains ( k ) )
451- {
452- // This var does not belong to the currently iterating channel group.
453- if ( NetworkingManager . Singleton . NetworkConfig . EnsureNetworkedVarLengthSafety )
454- {
455- writer . WriteUInt16Packed ( 0 ) ;
456- }
457- else
458- {
459- writer . WriteBool ( false ) ;
460- }
461- continue ;
462- }
552+ writer . WriteUInt16Packed ( 0 ) ;
553+ }
554+ }
555+ else
556+ {
557+ writer . WriteBool ( shouldWrite ) ;
558+ }
463559
464- bool isDirty = networkedVarFields [ k ] . IsDirty ( ) ; // cache this here. You never know what operations users will do in the dirty methods
465- bool shouldWrite = isDirty && ( ! IsServer || networkedVarFields [ k ] . CanClientRead ( clientId ) ) ;
560+ if ( shouldWrite )
561+ {
562+ writtenAny = true ;
466563
467- if ( NetworkingManager . Singleton . NetworkConfig . EnsureNetworkedVarLengthSafety )
468- {
469- if ( ! shouldWrite )
470- {
471- writer . WriteUInt16Packed ( 0 ) ;
472- }
473- }
474- else
564+ if ( NetworkingManager . Singleton . NetworkConfig . EnsureNetworkedVarLengthSafety )
565+ {
566+ using ( PooledBitStream varStream = PooledBitStream . Get ( ) )
475567 {
476- writer . WriteBool ( shouldWrite ) ;
477- }
568+ networkedVarFields [ k ] . WriteDelta ( varStream ) ;
569+ varStream . PadStream ( ) ;
478570
479- if ( shouldWrite )
480- {
481- writtenAny = true ;
482-
483- if ( NetworkingManager . Singleton . NetworkConfig . EnsureNetworkedVarLengthSafety )
484- {
485- using ( PooledBitStream varStream = PooledBitStream . Get ( ) )
486- {
487- networkedVarFields [ k ] . WriteDelta ( varStream ) ;
488- varStream . PadStream ( ) ;
489-
490- writer . WriteUInt16Packed ( ( ushort ) varStream . Length ) ;
491- stream . CopyFrom ( varStream ) ;
492- }
493- }
494- else
495- {
496- networkedVarFields [ k ] . WriteDelta ( stream ) ;
497- }
498-
499- if ( ! networkedVarIndexesToResetSet . Contains ( k ) )
500- {
501- networkedVarIndexesToResetSet . Add ( k ) ;
502- networkedVarIndexesToReset . Add ( k ) ;
503- }
571+ writer . WriteUInt16Packed ( ( ushort ) varStream . Length ) ;
572+ stream . CopyFrom ( varStream ) ;
504573 }
505574 }
575+ else
576+ {
577+ networkedVarFields [ k ] . WriteDelta ( stream ) ;
578+ }
506579
507- if ( writtenAny )
580+ if ( ! networkedVarIndexesToResetSet . Contains ( k ) )
508581 {
509- if ( IsServer )
510- InternalMessageSender . Send ( clientId , MLAPIConstants . MLAPI_NETWORKED_VAR_DELTA , channelsForNetworkedVarGroups [ j ] , stream , SecuritySendFlags . None ) ;
511- else
512- InternalMessageSender . Send ( NetworkingManager . Singleton . ServerClientId , MLAPIConstants . MLAPI_NETWORKED_VAR_DELTA , channelsForNetworkedVarGroups [ j ] , stream , SecuritySendFlags . None ) ;
582+ networkedVarIndexesToResetSet . Add ( k ) ;
583+ networkedVarIndexesToReset . Add ( k ) ;
513584 }
514585 }
515586 }
587+
588+ if ( writtenAny )
589+ {
590+ InternalMessageSender . Send ( clientId ,
591+ MLAPIConstants . MLAPI_NETWORKED_VAR_DELTA ,
592+ channelsForNetworkedVarGroups [ j ] , stream , SecuritySendFlags . None ) ;
593+ }
516594 }
517595 }
518596 }
519-
520- for ( int i = 0 ; i < networkedVarIndexesToReset . Count ; i ++ )
521- {
522- networkedVarFields [ networkedVarIndexesToReset [ i ] ] . ResetDirty ( ) ;
523- }
524597 }
525-
526598 private bool CouldHaveDirtyNetworkedVars ( )
527599 {
600+ // TODO: There should be a better way by reading one dirty variable vs. 'n'
528601 for ( int i = 0 ; i < networkedVarFields . Count ; i ++ )
529602 {
530603 if ( networkedVarFields [ i ] . IsDirty ( ) )
@@ -555,7 +628,7 @@ internal static void HandleNetworkedVarDeltas(List<INetworkedVar> networkedVarLi
555628 continue ;
556629 }
557630
558- if ( NetworkingManager . Singleton . IsServer && ! networkedVarList [ i ] . CanClientWrite ( clientId ) )
631+ if ( IsServer && ! networkedVarList [ i ] . CanClientWrite ( clientId ) )
559632 {
560633 if ( NetworkingManager . Singleton . NetworkConfig . EnsureNetworkedVarLengthSafety )
561634 {
@@ -580,7 +653,7 @@ internal static void HandleNetworkedVarDeltas(List<INetworkedVar> networkedVarLi
580653
581654 long readStartPos = stream . Position ;
582655
583- networkedVarList [ i ] . ReadDelta ( stream , NetworkingManager . Singleton . IsServer ) ;
656+ networkedVarList [ i ] . ReadDelta ( stream , IsServer ) ;
584657 ProfilerStatManager . networkVarsRcvd . Record ( ) ;
585658
586659 if ( NetworkingManager . Singleton . NetworkConfig . EnsureNetworkedVarLengthSafety )
@@ -623,7 +696,7 @@ internal static void HandleNetworkedVarUpdate(List<INetworkedVar> networkedVarLi
623696 continue ;
624697 }
625698
626- if ( NetworkingManager . Singleton . IsServer && ! networkedVarList [ i ] . CanClientWrite ( clientId ) )
699+ if ( IsServer && ! networkedVarList [ i ] . CanClientWrite ( clientId ) )
627700 {
628701 if ( NetworkingManager . Singleton . NetworkConfig . EnsureNetworkedVarLengthSafety )
629702 {
0 commit comments