Skip to content

Commit 548280b

Browse files
Merge branch 'develop' into feature/networkupdate
2 parents 16cce8b + 29b1616 commit 548280b

4 files changed

Lines changed: 166 additions & 127 deletions

File tree

com.unity.multiplayer.mlapi/Runtime/Core/NetworkedBehaviour.cs

Lines changed: 159 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -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
{

com.unity.multiplayer.mlapi/Runtime/Core/NetworkedObject.cs

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@ namespace MLAPI
2121
[AddComponentMenu("MLAPI/NetworkedObject", -99)]
2222
public sealed class NetworkedObject : MonoBehaviour
2323
{
24-
#if DEVELOPMENT_BUILD || UNITY_EDITOR
25-
public static ProfilerMarker s_NetworkedBehaviourUpdate = new ProfilerMarker("MLAPI.NetworkedObject.NetworkedBehaviourUpdate");
26-
#endif
27-
2824
private void OnValidate()
2925
{
3026
// Set this so the hash can be serialized on Scene objects. For prefabs, they are generated at runtime.
@@ -550,36 +546,6 @@ internal List<NetworkedBehaviour> childNetworkedBehaviours
550546
}
551547
}
552548

553-
internal static void NetworkedBehaviourUpdate()
554-
{
555-
#if DEVELOPMENT_BUILD || UNITY_EDITOR
556-
s_NetworkedBehaviourUpdate.Begin();
557-
#endif
558-
559-
try
560-
{
561-
if (SpawnManager.SpawnedObjectsList.Count == 0)
562-
return;
563-
564-
foreach (var sobj in SpawnManager.SpawnedObjectsList)
565-
{
566-
// Sync all vars
567-
for (int j = 0;
568-
j < sobj.childNetworkedBehaviours.Count;
569-
j++)
570-
{
571-
sobj.childNetworkedBehaviours[j].VarUpdate();
572-
}
573-
}
574-
}
575-
finally
576-
{
577-
#if DEVELOPMENT_BUILD || UNITY_EDITOR
578-
s_NetworkedBehaviourUpdate.End();
579-
#endif
580-
}
581-
}
582-
583549
internal void WriteNetworkedVarData(Stream stream, ulong clientId)
584550
{
585551
for (int i = 0; i < childNetworkedBehaviours.Count; i++)

com.unity.multiplayer.mlapi/Runtime/Core/NetworkingManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,7 @@ private void NetworkUpdate()
808808
if (NetworkConfig.EnableNetworkedVar)
809809
{
810810
// Do NetworkedVar updates
811-
NetworkedObject.NetworkedBehaviourUpdate();
811+
NetworkedBehaviour.NetworkedBehaviourUpdate();
812812
}
813813

814814
if (!IsServer && NetworkConfig.EnableMessageBuffering)

0 commit comments

Comments
 (0)