mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 02:50:32 +00:00
LatencySimulation: one Queue for all channels to simplify code and support more channels later
This commit is contained in:
parent
9d0a72da9c
commit
993983036a
@ -18,12 +18,14 @@ struct QueuedMessage
|
||||
public int connectionId;
|
||||
public byte[] bytes;
|
||||
public double time;
|
||||
public int channelId;
|
||||
|
||||
public QueuedMessage(int connectionId, byte[] bytes, double time)
|
||||
public QueuedMessage(int connectionId, byte[] bytes, double time, int channelId)
|
||||
{
|
||||
this.connectionId = connectionId;
|
||||
this.bytes = bytes;
|
||||
this.time = time;
|
||||
this.channelId = channelId;
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,10 +88,8 @@ public ushort Port
|
||||
|
||||
// message queues
|
||||
// list so we can insert randomly (scramble)
|
||||
readonly List<QueuedMessage> reliableClientToServer = new List<QueuedMessage>();
|
||||
readonly List<QueuedMessage> reliableServerToClient = new List<QueuedMessage>();
|
||||
readonly List<QueuedMessage> unreliableClientToServer = new List<QueuedMessage>();
|
||||
readonly List<QueuedMessage> unreliableServerToClient = new List<QueuedMessage>();
|
||||
readonly List<QueuedMessage> clientToServer = new List<QueuedMessage>();
|
||||
readonly List<QueuedMessage> serverToClient = new List<QueuedMessage>();
|
||||
|
||||
// random
|
||||
// UnityEngine.Random.value is [0, 1] with both upper and lower bounds inclusive
|
||||
@ -142,8 +142,7 @@ void SimulateSend(
|
||||
ArraySegment<byte> segment,
|
||||
int channelId,
|
||||
float latency,
|
||||
List<QueuedMessage> reliableQueue,
|
||||
List<QueuedMessage> unreliableQueue)
|
||||
List<QueuedMessage> messageQueue)
|
||||
{
|
||||
// segment is only valid after returning. copy it.
|
||||
// (allocates for now. it's only for testing anyway.)
|
||||
@ -156,30 +155,31 @@ void SimulateSend(
|
||||
connectionId,
|
||||
bytes,
|
||||
#if !UNITY_2020_3_OR_NEWER
|
||||
NetworkTime.localTime + latency
|
||||
NetworkTime.localTime + latency,
|
||||
#else
|
||||
Time.unscaledTimeAsDouble + latency
|
||||
Time.unscaledTimeAsDouble + latency,
|
||||
#endif
|
||||
channelId
|
||||
);
|
||||
|
||||
switch (channelId)
|
||||
{
|
||||
case Channels.Reliable:
|
||||
// simulate latency
|
||||
reliableQueue.Add(message);
|
||||
messageQueue.Add(message);
|
||||
break;
|
||||
case Channels.Unreliable:
|
||||
// simulate packet loss
|
||||
// simulate latency, drop, scramble
|
||||
bool drop = random.NextDouble() < unreliableLoss/100;
|
||||
if (!drop)
|
||||
{
|
||||
// simulate scramble (Random.Next is < max, so +1)
|
||||
bool scramble = random.NextDouble() < unreliableScramble/100;
|
||||
int last = unreliableQueue.Count;
|
||||
int last = messageQueue.Count;
|
||||
int index = scramble ? random.Next(0, last + 1) : last;
|
||||
|
||||
// simulate latency
|
||||
unreliableQueue.Insert(index, message);
|
||||
messageQueue.Insert(index, message);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -215,14 +215,13 @@ public override void ClientConnect(Uri uri)
|
||||
public override void ClientDisconnect()
|
||||
{
|
||||
wrap.ClientDisconnect();
|
||||
reliableClientToServer.Clear();
|
||||
unreliableClientToServer.Clear();
|
||||
clientToServer.Clear();
|
||||
}
|
||||
|
||||
public override void ClientSend(ArraySegment<byte> segment, int channelId)
|
||||
{
|
||||
float latency = SimulateLatency(channelId);
|
||||
SimulateSend(0, segment, channelId, latency, reliableClientToServer, unreliableClientToServer);
|
||||
SimulateSend(0, segment, channelId, latency, clientToServer);
|
||||
}
|
||||
|
||||
public override Uri ServerUri() => wrap.ServerUri();
|
||||
@ -236,7 +235,7 @@ public override void ClientSend(ArraySegment<byte> segment, int channelId)
|
||||
public override void ServerSend(int connectionId, ArraySegment<byte> segment, int channelId)
|
||||
{
|
||||
float latency = SimulateLatency(channelId);
|
||||
SimulateSend(connectionId, segment, channelId, latency, reliableServerToClient, unreliableServerToClient);
|
||||
SimulateSend(connectionId, segment, channelId, latency, serverToClient);
|
||||
}
|
||||
|
||||
public override void ServerStart()
|
||||
@ -252,20 +251,19 @@ public override void ServerStart()
|
||||
public override void ServerStop()
|
||||
{
|
||||
wrap.ServerStop();
|
||||
reliableServerToClient.Clear();
|
||||
unreliableServerToClient.Clear();
|
||||
serverToClient.Clear();
|
||||
}
|
||||
|
||||
public override void ClientEarlyUpdate() => wrap.ClientEarlyUpdate();
|
||||
public override void ServerEarlyUpdate() => wrap.ServerEarlyUpdate();
|
||||
public override void ClientLateUpdate()
|
||||
{
|
||||
// flush reliable messages after latency.
|
||||
// flush messages after latency.
|
||||
// need to iterate all, since queue isn't a sortedlist.
|
||||
for (int i = 0; i < reliableClientToServer.Count; ++i)
|
||||
for (int i = 0; i < clientToServer.Count; ++i)
|
||||
{
|
||||
// message ready to be sent?
|
||||
QueuedMessage message = reliableClientToServer[i];
|
||||
QueuedMessage message = clientToServer[i];
|
||||
#if !UNITY_2020_3_OR_NEWER
|
||||
if (message.time <= NetworkTime.localTime)
|
||||
#else
|
||||
@ -273,27 +271,8 @@ public override void ClientLateUpdate()
|
||||
#endif
|
||||
{
|
||||
// send and eat
|
||||
wrap.ClientSend(new ArraySegment<byte>(message.bytes), Channels.Reliable);
|
||||
reliableClientToServer.RemoveAt(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
// flush unreliable messages after latency.
|
||||
// need to iterate all, since queue isn't a sortedlist.
|
||||
for (int i = 0; i < unreliableClientToServer.Count; ++i)
|
||||
{
|
||||
// message ready to be sent?
|
||||
QueuedMessage message = unreliableClientToServer[i];
|
||||
#if !UNITY_2020_3_OR_NEWER
|
||||
if (message.time <= NetworkTime.localTime)
|
||||
#else
|
||||
if (message.time <= Time.unscaledTimeAsDouble)
|
||||
#endif
|
||||
{
|
||||
// send and eat
|
||||
wrap.ClientSend(new ArraySegment<byte>(message.bytes), Channels.Unreliable);
|
||||
unreliableClientToServer.RemoveAt(i);
|
||||
wrap.ClientSend(new ArraySegment<byte>(message.bytes), message.channelId);
|
||||
clientToServer.RemoveAt(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
@ -303,13 +282,12 @@ public override void ClientLateUpdate()
|
||||
}
|
||||
public override void ServerLateUpdate()
|
||||
{
|
||||
|
||||
// flush reliable messages after latency.
|
||||
// flush messages after latency.
|
||||
// need to iterate all, since queue isn't a sortedlist.
|
||||
for (int i = 0; i < reliableServerToClient.Count; ++i)
|
||||
for (int i = 0; i < serverToClient.Count; ++i)
|
||||
{
|
||||
// message ready to be sent?
|
||||
QueuedMessage message = reliableServerToClient[i];
|
||||
QueuedMessage message = serverToClient[i];
|
||||
#if !UNITY_2020_3_OR_NEWER
|
||||
if (message.time <= NetworkTime.localTime)
|
||||
#else
|
||||
@ -317,28 +295,8 @@ public override void ServerLateUpdate()
|
||||
#endif
|
||||
{
|
||||
// send and eat
|
||||
wrap.ServerSend(message.connectionId, new ArraySegment<byte>(message.bytes), Channels.Reliable);
|
||||
reliableServerToClient.RemoveAt(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// flush unreliable messages after latency.
|
||||
// need to iterate all, since queue isn't a sortedlist.
|
||||
for (int i = 0; i < unreliableServerToClient.Count; ++i)
|
||||
{
|
||||
// message ready to be sent?
|
||||
QueuedMessage message = unreliableServerToClient[i];
|
||||
#if !UNITY_2020_3_OR_NEWER
|
||||
if (message.time <= NetworkTime.localTime)
|
||||
#else
|
||||
if (message.time <= Time.unscaledTimeAsDouble)
|
||||
#endif
|
||||
{
|
||||
// send and eat
|
||||
wrap.ServerSend(message.connectionId, new ArraySegment<byte>(message.bytes), Channels.Unreliable);
|
||||
unreliableServerToClient.RemoveAt(i);
|
||||
wrap.ServerSend(message.connectionId, new ArraySegment<byte>(message.bytes), message.channelId);
|
||||
serverToClient.RemoveAt(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user