@@ -174,7 +174,7 @@ internal void EndSendClientRpc(BitWriter writer, ClientRpcSendParams sendParams,
174174 /// <summary>
175175 /// Gets if we are executing as server
176176 /// </summary>
177- protected bool IsServer => IsRunning && NetworkingManager . Singleton . IsServer ;
177+ protected static bool IsServer => IsRunning && NetworkingManager . Singleton . IsServer ;
178178 /// <summary>
179179 /// Gets if we are executing as client
180180 /// </summary>
@@ -195,7 +195,7 @@ internal void EndSendClientRpc(BitWriter writer, ClientRpcSendParams sendParams,
195195 /// Gets if we are executing as Host, I.E Server and Client
196196 /// </summary>
197197 protected bool IsHost => IsRunning && NetworkingManager . Singleton . IsHost ;
198- private bool IsRunning => NetworkingManager . Singleton != null && NetworkingManager . Singleton . IsListening ;
198+ private static bool IsRunning => NetworkingManager . Singleton != null && NetworkingManager . Singleton . IsListening ;
199199 /// <summary>
200200 /// Gets Whether or not the object has a owner
201201 /// </summary>
@@ -330,6 +330,7 @@ protected NetworkedBehaviour GetBehaviour(ushort id)
330330 private readonly List < string > channelsForNetworkedVarGroups = new List < string > ( ) ;
331331 internal readonly List < INetworkedVar > networkedVarFields = new List < INetworkedVar > ( ) ;
332332
333+ private static HashSet < MLAPI . NetworkedObject > touched = new HashSet < MLAPI . NetworkedObject > ( ) ;
333334 private static readonly Dictionary < Type , FieldInfo [ ] > fieldTypes = new Dictionary < Type , FieldInfo [ ] > ( ) ;
334335
335336 private static FieldInfo [ ] GetFieldInfoForType ( Type type )
@@ -415,122 +416,194 @@ internal void InitializeVars()
415416 }
416417 }
417418
418- internal void VarUpdate ( )
419+ #if DEVELOPMENT_BUILD || UNITY_EDITOR
420+ public static ProfilerMarker s_NetworkedBehaviourUpdate = new ProfilerMarker ( "MLAPI.NetworkedObject.NetworkedBehaviourUpdate" ) ;
421+ #endif
422+
423+ internal static void NetworkedBehaviourUpdate ( )
424+ {
425+ #if DEVELOPMENT_BUILD || UNITY_EDITOR
426+ s_NetworkedBehaviourUpdate . Begin ( ) ;
427+ #endif
428+ try
429+ {
430+ if ( IsServer )
431+ {
432+ touched . Clear ( ) ;
433+ for ( int i = 0 ; i < NetworkingManager . Singleton . ConnectedClientsList . Count ; i ++ )
434+ {
435+ var client = NetworkingManager . Singleton . ConnectedClientsList [ i ] ;
436+ var spawnedObjs = SpawnManager . SpawnedObjectsList ;
437+ touched . UnionWith ( spawnedObjs ) ;
438+ foreach ( var sobj in spawnedObjs )
439+ {
440+ // Sync just the variables for just the objects this client sees
441+ for ( int k = 0 ; k < sobj . childNetworkedBehaviours . Count ; k ++ )
442+ {
443+ sobj . childNetworkedBehaviours [ k ] . VarUpdate ( client . ClientId ) ;
444+ }
445+ }
446+ }
447+
448+ // Now, reset all the no-longer-dirty variables
449+ foreach ( var sobj in touched )
450+ {
451+ for ( int k = 0 ; k < sobj . childNetworkedBehaviours . Count ; k ++ )
452+ {
453+ sobj . childNetworkedBehaviours [ k ] . PostNetworkVariableWrite ( ) ;
454+ }
455+ }
456+ }
457+ else
458+ {
459+
460+ // when client updates the sever, it tells it about all its objects
461+ foreach ( var sobj in SpawnManager . SpawnedObjectsList )
462+ {
463+ for ( int k = 0 ; k < sobj . childNetworkedBehaviours . Count ; k ++ )
464+ {
465+ sobj . childNetworkedBehaviours [ k ] . VarUpdate ( NetworkingManager . Singleton . ServerClientId ) ;
466+ }
467+ }
468+
469+ // Now, reset all the no-longer-dirty variables
470+ foreach ( var sobj in SpawnManager . SpawnedObjectsList )
471+ {
472+ for ( int k = 0 ; k < sobj . childNetworkedBehaviours . Count ; k ++ )
473+ {
474+ sobj . childNetworkedBehaviours [ k ] . PostNetworkVariableWrite ( ) ;
475+ }
476+ }
477+ }
478+
479+ }
480+ finally
481+ {
482+ #if DEVELOPMENT_BUILD || UNITY_EDITOR
483+ s_NetworkedBehaviourUpdate . End ( ) ;
484+ #endif
485+ }
486+ }
487+
488+
489+ internal void PreNetworkVariableWrite ( )
490+ {
491+ // reset our "which variables got written" data
492+ networkedVarIndexesToReset . Clear ( ) ;
493+ networkedVarIndexesToResetSet . Clear ( ) ;
494+ }
495+
496+ internal void PostNetworkVariableWrite ( )
497+ {
498+ // mark any variables we wrote as no longer dirty
499+ for ( int i = 0 ; i < networkedVarIndexesToReset . Count ; i ++ )
500+ {
501+ networkedVarFields [ networkedVarIndexesToReset [ i ] ] . ResetDirty ( ) ;
502+ }
503+ }
504+
505+ internal void VarUpdate ( ulong clientId )
419506 {
420507 if ( ! varInit )
421508 InitializeVars ( ) ;
422509
423- NetworkedVarUpdate ( ) ;
510+ PreNetworkVariableWrite ( ) ;
511+ NetworkedVarUpdate ( clientId ) ;
424512 }
425513
426514 private readonly List < int > networkedVarIndexesToReset = new List < int > ( ) ;
427515 private readonly HashSet < int > networkedVarIndexesToResetSet = new HashSet < int > ( ) ;
428516
429- private void NetworkedVarUpdate ( )
517+ private void NetworkedVarUpdate ( ulong clientId )
430518 {
431- if ( ! CouldHaveDirtyNetworkedVars ( ) )
432- return ;
519+ if ( ! CouldHaveDirtyNetworkedVars ( ) )
520+ return ;
433521
434- networkedVarIndexesToReset . Clear ( ) ;
435- networkedVarIndexesToResetSet . Clear ( ) ;
436-
437- for ( int i = 0 ; i < ( IsServer ? NetworkingManager . Singleton . ConnectedClientsList . Count : 1 ) ; i ++ )
522+ for ( int j = 0 ; j < channelMappedNetworkedVarIndexes . Count ; j ++ )
438523 {
439- // Do this check here to prevent doing all the expensive dirty checks
440- if ( ! IsServer || this . NetworkedObject . observers . Contains ( NetworkingManager . Singleton . ConnectedClientsList [ i ] . ClientId ) )
524+ using ( PooledBitStream stream = PooledBitStream . Get ( ) )
441525 {
442- // This iterates over every "channel group".
443- for ( int j = 0 ; j < channelMappedNetworkedVarIndexes . Count ; j ++ )
526+ using ( PooledBitWriter writer = PooledBitWriter . Get ( stream ) )
444527 {
445- using ( PooledBitStream stream = PooledBitStream . Get ( ) )
528+ writer . WriteUInt64Packed ( NetworkId ) ;
529+ writer . WriteUInt16Packed ( NetworkedObject . GetOrderIndex ( this ) ) ;
530+
531+ bool writtenAny = false ;
532+ for ( int k = 0 ; k < networkedVarFields . Count ; k ++ )
446533 {
447- using ( PooledBitWriter writer = PooledBitWriter . Get ( stream ) )
534+ if ( ! channelMappedNetworkedVarIndexes [ j ] . Contains ( k ) )
448535 {
449- writer . WriteUInt64Packed ( NetworkId ) ;
450- writer . WriteUInt16Packed ( NetworkedObject . GetOrderIndex ( this ) ) ;
536+ // This var does not belong to the currently iterating channel group.
537+ if ( NetworkingManager . Singleton . NetworkConfig . EnsureNetworkedVarLengthSafety )
538+ {
539+ writer . WriteUInt16Packed ( 0 ) ;
540+ }
541+ else
542+ {
543+ writer . WriteBool ( false ) ;
544+ }
545+ continue ;
546+ }
451547
452- ulong clientId = IsServer ? NetworkingManager . Singleton . ConnectedClientsList [ i ] . ClientId : NetworkingManager . Singleton . ServerClientId ;
453- bool writtenAny = false ;
454- for ( int k = 0 ; k < networkedVarFields . Count ; k ++ )
548+ bool isDirty = networkedVarFields [ k ] . IsDirty ( ) ; // cache this here. You never know what operations users will do in the dirty methods
549+
550+ // if I'm dirty AND a client, write (server always has all permissions)
551+ // if I'm dirty AND the server AND the client can read me, send.
552+ bool shouldWrite = isDirty && ( ! IsServer || networkedVarFields [ k ] . CanClientRead ( clientId ) ) ;
553+
554+ if ( NetworkingManager . Singleton . NetworkConfig . EnsureNetworkedVarLengthSafety )
555+ {
556+ if ( ! shouldWrite )
455557 {
456- if ( ! channelMappedNetworkedVarIndexes [ j ] . Contains ( k ) )
457- {
458- // This var does not belong to the currently iterating channel group.
459- if ( NetworkingManager . Singleton . NetworkConfig . EnsureNetworkedVarLengthSafety )
460- {
461- writer . WriteUInt16Packed ( 0 ) ;
462- }
463- else
464- {
465- writer . WriteBool ( false ) ;
466- }
467- continue ;
468- }
558+ writer . WriteUInt16Packed ( 0 ) ;
559+ }
560+ }
561+ else
562+ {
563+ writer . WriteBool ( shouldWrite ) ;
564+ }
469565
470- bool isDirty = networkedVarFields [ k ] . IsDirty ( ) ; // cache this here. You never know what operations users will do in the dirty methods
471- bool shouldWrite = isDirty && ( ! IsServer || networkedVarFields [ k ] . CanClientRead ( clientId ) ) ;
566+ if ( shouldWrite )
567+ {
568+ writtenAny = true ;
472569
473- if ( NetworkingManager . Singleton . NetworkConfig . EnsureNetworkedVarLengthSafety )
474- {
475- if ( ! shouldWrite )
476- {
477- writer . WriteUInt16Packed ( 0 ) ;
478- }
479- }
480- else
570+ if ( NetworkingManager . Singleton . NetworkConfig . EnsureNetworkedVarLengthSafety )
571+ {
572+ using ( PooledBitStream varStream = PooledBitStream . Get ( ) )
481573 {
482- writer . WriteBool ( shouldWrite ) ;
483- }
574+ networkedVarFields [ k ] . WriteDelta ( varStream ) ;
575+ varStream . PadStream ( ) ;
484576
485- if ( shouldWrite )
486- {
487- writtenAny = true ;
488-
489- if ( NetworkingManager . Singleton . NetworkConfig . EnsureNetworkedVarLengthSafety )
490- {
491- using ( PooledBitStream varStream = PooledBitStream . Get ( ) )
492- {
493- networkedVarFields [ k ] . WriteDelta ( varStream ) ;
494- varStream . PadStream ( ) ;
495-
496- writer . WriteUInt16Packed ( ( ushort ) varStream . Length ) ;
497- stream . CopyFrom ( varStream ) ;
498- }
499- }
500- else
501- {
502- networkedVarFields [ k ] . WriteDelta ( stream ) ;
503- }
504-
505- if ( ! networkedVarIndexesToResetSet . Contains ( k ) )
506- {
507- networkedVarIndexesToResetSet . Add ( k ) ;
508- networkedVarIndexesToReset . Add ( k ) ;
509- }
577+ writer . WriteUInt16Packed ( ( ushort ) varStream . Length ) ;
578+ stream . CopyFrom ( varStream ) ;
510579 }
511580 }
581+ else
582+ {
583+ networkedVarFields [ k ] . WriteDelta ( stream ) ;
584+ }
512585
513- if ( writtenAny )
586+ if ( ! networkedVarIndexesToResetSet . Contains ( k ) )
514587 {
515- if ( IsServer )
516- InternalMessageSender . Send ( clientId , MLAPIConstants . MLAPI_NETWORKED_VAR_DELTA , channelsForNetworkedVarGroups [ j ] , stream , SecuritySendFlags . None ) ;
517- else
518- InternalMessageSender . Send ( NetworkingManager . Singleton . ServerClientId , MLAPIConstants . MLAPI_NETWORKED_VAR_DELTA , channelsForNetworkedVarGroups [ j ] , stream , SecuritySendFlags . None ) ;
588+ networkedVarIndexesToResetSet . Add ( k ) ;
589+ networkedVarIndexesToReset . Add ( k ) ;
519590 }
520591 }
521592 }
593+
594+ if ( writtenAny )
595+ {
596+ InternalMessageSender . Send ( clientId ,
597+ MLAPIConstants . MLAPI_NETWORKED_VAR_DELTA ,
598+ channelsForNetworkedVarGroups [ j ] , stream , SecuritySendFlags . None ) ;
599+ }
522600 }
523601 }
524602 }
525-
526- for ( int i = 0 ; i < networkedVarIndexesToReset . Count ; i ++ )
527- {
528- networkedVarFields [ networkedVarIndexesToReset [ i ] ] . ResetDirty ( ) ;
529- }
530603 }
531-
532604 private bool CouldHaveDirtyNetworkedVars ( )
533605 {
606+ // TODO: There should be a better way by reading one dirty variable vs. 'n'
534607 for ( int i = 0 ; i < networkedVarFields . Count ; i ++ )
535608 {
536609 if ( networkedVarFields [ i ] . IsDirty ( ) )
@@ -561,7 +634,7 @@ internal static void HandleNetworkedVarDeltas(List<INetworkedVar> networkedVarLi
561634 continue ;
562635 }
563636
564- if ( NetworkingManager . Singleton . IsServer && ! networkedVarList [ i ] . CanClientWrite ( clientId ) )
637+ if ( IsServer && ! networkedVarList [ i ] . CanClientWrite ( clientId ) )
565638 {
566639 if ( NetworkingManager . Singleton . NetworkConfig . EnsureNetworkedVarLengthSafety )
567640 {
@@ -586,7 +659,7 @@ internal static void HandleNetworkedVarDeltas(List<INetworkedVar> networkedVarLi
586659
587660 long readStartPos = stream . Position ;
588661
589- networkedVarList [ i ] . ReadDelta ( stream , NetworkingManager . Singleton . IsServer ) ;
662+ networkedVarList [ i ] . ReadDelta ( stream , IsServer ) ;
590663 ProfilerStatManager . networkVarsRcvd . Record ( ) ;
591664
592665 if ( NetworkingManager . Singleton . NetworkConfig . EnsureNetworkedVarLengthSafety )
@@ -629,7 +702,7 @@ internal static void HandleNetworkedVarUpdate(List<INetworkedVar> networkedVarLi
629702 continue ;
630703 }
631704
632- if ( NetworkingManager . Singleton . IsServer && ! networkedVarList [ i ] . CanClientWrite ( clientId ) )
705+ if ( IsServer && ! networkedVarList [ i ] . CanClientWrite ( clientId ) )
633706 {
634707 if ( NetworkingManager . Singleton . NetworkConfig . EnsureNetworkedVarLengthSafety )
635708 {
0 commit comments