Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
public class NetworkingManagerEditor : Editor
{
// Properties
private SerializedProperty runInLoopbackModeProperty;
private SerializedProperty dontDestroyOnLoadProperty;
private SerializedProperty runInBackgroundProperty;
private SerializedProperty logLevelProperty;
Expand Down Expand Up @@ -96,7 +95,6 @@ private void Init()
networkingManager = (NetworkingManager)target;

// Base properties
runInLoopbackModeProperty = serializedObject.FindProperty("LoopbackEnabled");
dontDestroyOnLoadProperty = serializedObject.FindProperty("DontDestroy");
runInBackgroundProperty = serializedObject.FindProperty("RunInBackground");
logLevelProperty = serializedObject.FindProperty("LogLevel");
Expand Down Expand Up @@ -137,7 +135,6 @@ private void Init()
private void CheckNullProperties()
{
// Base properties
runInLoopbackModeProperty = serializedObject.FindProperty("LoopbackEnabled");
dontDestroyOnLoadProperty = serializedObject.FindProperty("DontDestroy");
runInBackgroundProperty = serializedObject.FindProperty("RunInBackground");
logLevelProperty = serializedObject.FindProperty("LogLevel");
Expand Down Expand Up @@ -251,7 +248,6 @@ public override void OnInspectorGUI()
if (!networkingManager.IsServer && !networkingManager.IsClient)
{
serializedObject.Update();
EditorGUILayout.PropertyField(runInLoopbackModeProperty);
EditorGUILayout.PropertyField(dontDestroyOnLoadProperty);
EditorGUILayout.PropertyField(runInBackgroundProperty);
EditorGUILayout.PropertyField(logLevelProperty);
Expand Down Expand Up @@ -313,7 +309,7 @@ public override void OnInspectorGUI()
{
EditorGUILayout.PropertyField(maxObjectUpdatesPerTickProperty);
}

EditorGUILayout.PropertyField(ensureNetworkedVarLengthSafetyProperty);
}

Expand Down
128 changes: 109 additions & 19 deletions com.unity.multiplayer.mlapi/Runtime/Core/NetworkedBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,24 +67,40 @@ public BitSerializer __beginSendServerRpc(ServerRpcParams serverRpcParams, bool
#endif
{
var rpcQueueContainer = NetworkingManager.Singleton.rpcQueueContainer;
var writer = rpcQueueContainer.BeginAddQueueItemToOutboundFrame(
RpcQueueContainer.QueueItemType.ServerRpc,
Time.realtimeSinceStartup,
Transport.MLAPI_STDRPC_CHANNEL,
/* sendFlags = */ 0,
NetworkingManager.Singleton.ServerClientId,
/* targetNetworkIds = */ null);
if (!rpcQueueContainer.IsUsingBatching())
PooledBitWriter writer;
var IsUsingBatching = rpcQueueContainer.IsUsingBatching();
if (IsHost)
{
if (serverRpcParams.Send.UpdateStage == NetworkUpdateManager.NetworkUpdateStage.Default)
{
serverRpcParams.Send.UpdateStage = NetworkUpdateManager.NetworkUpdateStage.Update;
}
writer = rpcQueueContainer.BeginAddQueueItemToFrame(RpcQueueContainer.QueueItemType.ServerRpc, Time.realtimeSinceStartup, Transport.MLAPI_STDRPC_CHANNEL, 0,
NetworkingManager.Singleton.ServerClientId, null, QueueHistoryFrame.QueueFrameType.Inbound,serverRpcParams.Send.UpdateStage );

//Under this condition we always treat this like there is no batching
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this because technically we don't need to batch when in host (vs. server) mode? Or because batching doesn't work in host mode? My thinking is, I really would like to avoid the host mode special case code in general because I think we tend to test one or the other leading to latent bugs. If we don't need to special case host mode then could we meld the if and else clauses into one?

writer.WriteBit(false); // Encrypted
writer.WriteBit(false); // Authenticated
writer.WriteBits(MLAPIConstants.MLAPI_SERVER_RPC, 6); // MessageType
}
else
{
writer = rpcQueueContainer.BeginAddQueueItemToFrame(RpcQueueContainer.QueueItemType.ServerRpc, Time.realtimeSinceStartup, Transport.MLAPI_STDRPC_CHANNEL, 0,
NetworkingManager.Singleton.ServerClientId, null, QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateManager.NetworkUpdateStage.LateUpdate);
if (!IsUsingBatching)
{
writer.WriteBit(false); // Encrypted
writer.WriteBit(false); // Authenticated
writer.WriteBits(MLAPIConstants.MLAPI_SERVER_RPC, 6); // MessageType
}
}



writer.WriteUInt64Packed(NetworkId); // NetworkObjectId
writer.WriteUInt16Packed(GetBehaviourId()); // NetworkBehaviourId

// Write the update stage in front of RPC related information
//Write the update stage in front of RPC related information
if (serverRpcParams.Send.UpdateStage == NetworkUpdateManager.NetworkUpdateStage.Default)
{
writer.WriteUInt16Packed((ushort)NetworkUpdateManager.NetworkUpdateStage.Update);
Expand All @@ -110,7 +126,15 @@ public void __endSendServerRpc(BitSerializer serializer, ServerRpcParams serverR
if (serializer == null) return;

var rpcQueueContainer = NetworkingManager.Singleton.rpcQueueContainer;
rpcQueueContainer.EndAddQueueItemToOutboundFrame(serializer.Writer);
if (IsHost)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, see my comment on host mode above

{
rpcQueueContainer.EndAddQueueItemToFrame(serializer.Writer, QueueHistoryFrame.QueueFrameType.Inbound, serverRpcParams.Send.UpdateStage == NetworkUpdateManager.NetworkUpdateStage.Default ? NetworkUpdateManager.NetworkUpdateStage.Update:serverRpcParams.Send.UpdateStage );
}
else
{
rpcQueueContainer.EndAddQueueItemToFrame(serializer.Writer, QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateManager.NetworkUpdateStage.LateUpdate);
}

}

[Browsable(false)]
Expand All @@ -125,18 +149,57 @@ public BitSerializer __beginSendClientRpc(ClientRpcParams clientRpcParams, bool
{
// This will start a new queue item entry and will then return the writer to the current frame's stream
var rpcQueueContainer = NetworkingManager.Singleton.rpcQueueContainer;
var writer = rpcQueueContainer.BeginAddQueueItemToOutboundFrame(
RpcQueueContainer.QueueItemType.ClientRpc,
Time.realtimeSinceStartup,
Transport.MLAPI_STDRPC_CHANNEL,
/* sendFlags = */ 0,
NetworkId,
clientRpcParams.Send.TargetClientIds ?? NetworkingManager.Singleton.ConnectedClientsList.Select(c => c.ClientId).ToArray());
if (!rpcQueueContainer.IsUsingBatching())

PooledBitWriter writer;
var IsUsingBatching = rpcQueueContainer.IsUsingBatching();

ulong[] ClientIds = clientRpcParams.Send.TargetClientIds ?? NetworkingManager.Singleton.ConnectedClientsList.Select(c => c.ClientId).ToArray();
if(clientRpcParams.Send.TargetClientIds != null && clientRpcParams.Send.TargetClientIds.Length == 0)
{
ClientIds = NetworkingManager.Singleton.ConnectedClientsList.Select(c => c.ClientId).ToArray();
}

var ContainsServerClientId = ClientIds.Contains(NetworkingManager.Singleton.ServerClientId);
if (IsHost && ContainsServerClientId)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto ditto on host mode

{
if(clientRpcParams.Send.UpdateStage == NetworkUpdateManager.NetworkUpdateStage.Default)
{
clientRpcParams.Send.UpdateStage = NetworkUpdateManager.NetworkUpdateStage.Update;
}

writer = rpcQueueContainer.BeginAddQueueItemToFrame(RpcQueueContainer.QueueItemType.ClientRpc, Time.realtimeSinceStartup, Transport.MLAPI_STDRPC_CHANNEL, 0,
NetworkingManager.Singleton.ServerClientId, null, QueueHistoryFrame.QueueFrameType.Inbound,clientRpcParams.Send.UpdateStage );

writer.WriteBit(false); // Encrypted
writer.WriteBit(false); // Authenticated
writer.WriteBits(MLAPIConstants.MLAPI_CLIENT_RPC, 6); // MessageType

//Handle sending to the other clients
if (ClientIds.Length > 1 )
{
rpcQueueContainer.SetLoopBackWriter(writer, QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateManager.NetworkUpdateStage.LateUpdate);
writer = rpcQueueContainer.BeginAddQueueItemToFrame(RpcQueueContainer.QueueItemType.ClientRpc, Time.realtimeSinceStartup, Transport.MLAPI_STDRPC_CHANNEL, 0, NetworkId,
ClientIds, QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateManager.NetworkUpdateStage.LateUpdate);

if (!IsUsingBatching)
{
writer.WriteBit(false); // Encrypted
writer.WriteBit(false); // Authenticated
writer.WriteBits(MLAPIConstants.MLAPI_CLIENT_RPC, 6); // MessageType
}
}
}
else
{
writer = rpcQueueContainer.BeginAddQueueItemToFrame(RpcQueueContainer.QueueItemType.ClientRpc, Time.realtimeSinceStartup, Transport.MLAPI_STDRPC_CHANNEL, 0, NetworkId,
ClientIds, QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateManager.NetworkUpdateStage.LateUpdate);

if (!IsUsingBatching)
{
writer.WriteBit(false); // Encrypted
writer.WriteBit(false); // Authenticated
writer.WriteBits(MLAPIConstants.MLAPI_CLIENT_RPC, 6); // MessageType
}
}

writer.WriteUInt64Packed(NetworkId); // NetworkObjectId
Expand All @@ -155,6 +218,7 @@ public BitSerializer __beginSendClientRpc(ClientRpcParams clientRpcParams, bool
return writer.Serializer;
}


[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
#if UNITY_2020_2_OR_NEWER
Expand All @@ -168,7 +232,33 @@ public void __endSendClientRpc(BitSerializer serializer, ClientRpcParams clientR
if (serializer == null) return;

var rpcQueueContainer = NetworkingManager.Singleton.rpcQueueContainer;
rpcQueueContainer.EndAddQueueItemToOutboundFrame(serializer.Writer);
ulong[] ClientIds = clientRpcParams.Send.TargetClientIds ?? NetworkingManager.Singleton.ConnectedClientsList.Select(c => c.ClientId).ToArray();
if(clientRpcParams.Send.TargetClientIds != null && clientRpcParams.Send.TargetClientIds.Length == 0)
{
ClientIds = NetworkingManager.Singleton.ConnectedClientsList.Select(c => c.ClientId).ToArray();
}
var ContainsServerClientId = ClientIds.Contains(NetworkingManager.Singleton.ServerClientId);

if (IsHost && ContainsServerClientId)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto ditto ditto on host mode :)

{
PooledBitWriter loopbackWriter = serializer.Writer as PooledBitWriter;
if (ClientIds.Length > 1 )
{
rpcQueueContainer.EndAddQueueItemToFrame(serializer.Writer, QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateManager.NetworkUpdateStage.LateUpdate);

loopbackWriter = rpcQueueContainer.GetLoopBackWriter(QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateManager.NetworkUpdateStage.LateUpdate);
rpcQueueContainer.ClearLoopBackWriter(QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateManager.NetworkUpdateStage.LateUpdate);
}

if(ContainsServerClientId)
{
rpcQueueContainer.EndAddQueueItemToFrame(loopbackWriter, QueueHistoryFrame.QueueFrameType.Inbound, clientRpcParams.Send.UpdateStage == NetworkUpdateManager.NetworkUpdateStage.Default ? NetworkUpdateManager.NetworkUpdateStage.Update:clientRpcParams.Send.UpdateStage );
}
}
else
{
rpcQueueContainer.EndAddQueueItemToFrame(serializer.Writer, QueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateManager.NetworkUpdateStage.LateUpdate);
}
}

/// <summary>
Expand Down
11 changes: 2 additions & 9 deletions com.unity.multiplayer.mlapi/Runtime/Core/NetworkingManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,6 @@ public class NetworkingManager : UpdateLoopBehaviour
static ProfilerMarker s_MLAPIClientSTDRPCQueued = new ProfilerMarker("MLAPIClientSTDRPCQueued");
static ProfilerMarker s_InvokeRPC = new ProfilerMarker("InvokeRPC");
#endif
[HideInInspector]
public bool LoopbackEnabled;

public RpcQueueContainer rpcQueueContainer { get; private set; }

/// <summary>
Expand Down Expand Up @@ -718,7 +715,7 @@ protected override Action InternalRegisterNetworkUpdateStage(NetworkUpdateManage
/// </summary>
private void Awake()
{
rpcQueueContainer = new RpcQueueContainer(false, LoopbackEnabled);
rpcQueueContainer = new RpcQueueContainer(false);
//Note: Since frame history is not being used, this is set to 0
//To test frame history, increase the number to (n) where n > 0
rpcQueueContainer.Initialize(0);
Expand All @@ -744,11 +741,7 @@ private void NetworkPreUpdate()
#if DEVELOPMENT_BUILD || UNITY_EDITOR
s_ReceiveTick.Begin();
#endif
bool IsLoopBack = false;
if (rpcQueueContainer != null)
{
IsLoopBack = rpcQueueContainer.IsLoopBack();
}
var IsLoopBack = false;

NetworkProfiler.StartTick(TickType.Receive);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ public enum QueueFrameType
Outbound,
}

public uint TotalSize;
public bool isDirty; //Used to determine if this queue history frame has been reset (cleaned) yet
public bool hasLoopbackData; //Used to determine if a dirt frame is dirty because rpcs are being looped back betwen HostClient and HostServer
public uint totalSize;
public List<uint> queueItemOffsets;

public PooledBitStream queueStream;
public PooledBitWriter queueWriter;
public PooledBitReader queueReader;
public PooledBitWriter queueWriterLoopback; //Temporary fix for Host mode loopback work around.


public PooledBitReader queueReader;

private int m_QueueItemOffsetIndex;
private FrameQueueItem m_CurrentQueueItem;
Expand Down
Loading