Skip to content

Commit 61af2b3

Browse files
feat: Improve access to simulator parameters (#1745)
* feat: Improve access to simulator parameters * Add PR number to CHANGELOG entry * Make standards check happy
1 parent 5972547 commit 61af2b3

File tree

3 files changed

+122
-42
lines changed

3 files changed

+122
-42
lines changed

com.unity.netcode.adapter.utp/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ All notable changes to this package will be documented in this file. The format
66

77
### Added
88

9+
- New parameters are available to simulate network conditions (delay, jitter, packet loss) in the editor and in development builds. The parameters are available under the 'Debug Simulator' section of the 'Unity Transport' component, or can be set with the `SetDebugSimulatorParameters` call. (#1745)
10+
911
### Changed
1012

1113
- Updated Unity Transport package to 1.0.0-pre.13. (#1696)

com.unity.netcode.adapter.utp/Runtime/UnityTransport.cs

Lines changed: 93 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,53 @@ public static implicit operator ConnectionAddressData(NetworkEndPoint d) =>
167167

168168
public ConnectionAddressData ConnectionData = s_DefaultConnectionAddressData;
169169

170+
[Serializable]
171+
public struct SimulatorParameters
172+
{
173+
[Tooltip("Delay to add to every send and received packet (in milliseconds). Only applies in the editor " +
174+
"and in development builds. The value is ignored in production builds.")]
175+
[SerializeField] public int PacketDelayMS;
176+
177+
[Tooltip("Jitter (random variation) to add/substract to the packet delay (in milliseconds). Only " +
178+
"applies in the editor and in development builds. The value is ignored in production builds.")]
179+
[SerializeField] public int PacketJitterMS;
180+
181+
[Tooltip("Percentage of sent and received packets to drop. Only applies in the editor and in the editor " +
182+
"and in developments builds.")]
183+
[SerializeField] public int PacketDropRate;
184+
}
185+
186+
public SimulatorParameters DebugSimulator = new SimulatorParameters
187+
{
188+
PacketDelayMS = 0,
189+
PacketJitterMS = 0,
190+
PacketDropRate = 0
191+
};
192+
193+
// Only for backward compatibility with how we used to handle simulator parameters.
194+
#if DEVELOPMENT_BUILD
195+
[Obsolete("Use SetDebugSimulatorParameters() instead.")]
196+
public int ClientPacketDelayMs
197+
{
198+
get => DebugSimulator.PacketDelayMS;
199+
set => DebugSimulator.PacketDelayMS = value;
200+
}
201+
202+
[Obsolete("Use SetDebugSimulatorParameters() instead.")]
203+
public int ClientPacketJitterMs
204+
{
205+
get => DebugSimulator.PacketJitterMS;
206+
set => DebugSimulator.PacketJitterMS = value;
207+
}
208+
209+
[Obsolete("Use SetDebugSimulatorParameters() instead.")]
210+
public int ClientPacketDropRate
211+
{
212+
get => DebugSimulator.PacketDropRate;
213+
set => DebugSimulator.PacketDropRate = value;
214+
}
215+
#endif
216+
170217
private State m_State = State.Disconnected;
171218
private NetworkDriver m_Driver;
172219
private NetworkSettings m_NetworkSettings;
@@ -184,43 +231,6 @@ public static implicit operator ConnectionAddressData(NetworkEndPoint d) =>
184231

185232
internal NetworkManager NetworkManager;
186233

187-
#if UNITY_EDITOR
188-
private static int ClientPacketDelayMs => UnityEditor.EditorPrefs.GetInt($"NetcodeGameObjects_{Application.productName}_ClientDelay");
189-
private static int ClientPacketJitterMs => UnityEditor.EditorPrefs.GetInt($"NetcodeGameObjects_{Application.productName}_ClientJitter");
190-
private static int ClientPacketDropRate => UnityEditor.EditorPrefs.GetInt($"NetcodeGameObjects_{Application.productName}_ClientDropRate");
191-
#elif DEVELOPMENT_BUILD
192-
public static int ClientPacketDelayMs = 0;
193-
public static int ClientPacketJitterMs = 0;
194-
public static int ClientPacketDropRate = 0;
195-
#endif
196-
#if UNITY_EDITOR || DEVELOPMENT_BUILD
197-
public SimulatorUtility.Parameters ClientSimulatorParameters
198-
{
199-
get
200-
{
201-
var packetDelay = ClientPacketDelayMs;
202-
var jitter = ClientPacketJitterMs;
203-
if (jitter > packetDelay)
204-
{
205-
jitter = packetDelay;
206-
}
207-
208-
var packetDrop = ClientPacketDropRate;
209-
int networkRate = 60; // TODO: read from some better place
210-
// All 3 packet types every frame stored for maximum delay, doubled for safety margin
211-
int maxPackets = 2 * (networkRate * 3 * packetDelay + 999) / 1000;
212-
return new SimulatorUtility.Parameters
213-
{
214-
MaxPacketSize = NetworkParameterConstants.MTU,
215-
MaxPacketCount = maxPackets,
216-
PacketDelayMs = packetDelay,
217-
PacketJitterMs = jitter,
218-
PacketDropPercentage = packetDrop
219-
};
220-
}
221-
}
222-
#endif
223-
224234
/// <summary>
225235
/// SendQueue dictionary is used to batch events instead of sending them immediately.
226236
/// </summary>
@@ -478,6 +488,26 @@ public void SetConnectionData(NetworkEndPoint endPoint, NetworkEndPoint listenEn
478488
SetConnectionData(serverAddress, endPoint.Port, listenAddress);
479489
}
480490

491+
/// <summary>Set the parameters for the debug simulator.</summary>
492+
/// <param name="packetDelay">Packet delay in milliseconds.</param>
493+
/// <param name="packetJitter">Packet jitter in milliseconds.</param>
494+
/// <param name="dropRate">Packet drop percentage.</param>
495+
public void SetDebugSimulatorParameters(int packetDelay, int packetJitter, int dropRate)
496+
{
497+
if (m_Driver.IsCreated)
498+
{
499+
Debug.LogError("SetDebugSimulatorParameters() must be called before StartClient() or StartServer().");
500+
return;
501+
}
502+
503+
DebugSimulator = new SimulatorParameters
504+
{
505+
PacketDelayMS = packetDelay,
506+
PacketJitterMS = packetJitter,
507+
PacketDropRate = dropRate
508+
};
509+
}
510+
481511
private bool StartRelayServer()
482512
{
483513
//This comparison is currently slow since RelayServerData does not implement a custom comparison operator that doesn't use
@@ -974,6 +1004,28 @@ public override void Shutdown()
9741004
m_ServerClientId = 0;
9751005
}
9761006

1007+
private void ConfigureSimulator()
1008+
{
1009+
#if UNITY_EDITOR
1010+
// Backward-compatibility with how we used to handle simulator parameters.
1011+
var packetDelay = UnityEditor.EditorPrefs.GetInt($"NetcodeGameObjects_{Application.productName}_ClientDelay", DebugSimulator.PacketDelayMS);
1012+
var packetJitter = UnityEditor.EditorPrefs.GetInt($"NetcodeGameObjects_{Application.productName}_ClientJitter", DebugSimulator.PacketJitterMS);
1013+
var dropRate = UnityEditor.EditorPrefs.GetInt($"NetcodeGameObjects_{Application.productName}_ClientDropRate", DebugSimulator.PacketDropRate);
1014+
#else
1015+
var packetDelay = DebugSimulator.PacketDelayMS;
1016+
var packetJitter = DebugSimulator.PacketJitterMS;
1017+
var dropRate = DebugSimulator.PacketDropRate;
1018+
#endif
1019+
1020+
m_NetworkSettings.WithSimulatorStageParameters(
1021+
maxPacketCount: 300, // TODO Is there any way to compute a better value?
1022+
maxPacketSize: NetworkParameterConstants.MTU,
1023+
packetDelayMs: packetDelay,
1024+
packetJitterMs: packetJitter,
1025+
packetDropPercentage: dropRate
1026+
);
1027+
}
1028+
9771029
public void CreateDriver(UnityTransport transport, out NetworkDriver driver,
9781030
out NetworkPipeline unreliableFragmentedPipeline,
9791031
out NetworkPipeline unreliableSequencedFragmentedPipeline,
@@ -986,11 +1038,9 @@ public void CreateDriver(UnityTransport transport, out NetworkDriver driver,
9861038

9871039
#if UNITY_EDITOR || DEVELOPMENT_BUILD
9881040
maxFrameTimeMS = 100;
989-
990-
var simulatorParams = ClientSimulatorParameters;
991-
992-
m_NetworkSettings.AddRawParameterStruct(ref simulatorParams);
1041+
ConfigureSimulator();
9931042
#endif
1043+
9941044
m_NetworkSettings.WithNetworkConfigParameters(
9951045
maxConnectAttempts: transport.m_MaxConnectAttempts,
9961046
connectTimeoutMS: transport.m_ConnectTimeoutMS,
@@ -999,8 +1049,9 @@ public void CreateDriver(UnityTransport transport, out NetworkDriver driver,
9991049
maxFrameTimeMS: maxFrameTimeMS);
10001050

10011051
driver = NetworkDriver.Create(m_NetworkSettings);
1052+
10021053
#if UNITY_EDITOR || DEVELOPMENT_BUILD
1003-
if (simulatorParams.PacketDelayMs > 0 || simulatorParams.PacketDropInterval > 0)
1054+
if (DebugSimulator.PacketDelayMS > 0 || DebugSimulator.PacketDropRate > 0)
10041055
{
10051056
unreliableFragmentedPipeline = driver.CreatePipeline(
10061057
typeof(FragmentationPipelineStage),

com.unity.netcode.adapter.utp/Tests/Runtime/TransportTests.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,33 @@ public IEnumerator SendCompletesOnUnreliableSendQueueOverflow()
334334

335335
yield return null;
336336
}
337+
338+
// Check that simulator parameters are effective. We only check with the drop rate, because
339+
// that's easy to check and we only really want to make sure the simulator parameters are
340+
// configured properly (the simulator pipeline stage is already well-tested in UTP).
341+
[UnityTest]
342+
[UnityPlatform(include = new[] { RuntimePlatform.OSXEditor, RuntimePlatform.WindowsEditor, RuntimePlatform.LinuxEditor })]
343+
public IEnumerator SimulatorParametersAreEffective()
344+
{
345+
InitializeTransport(out m_Server, out m_ServerEvents);
346+
InitializeTransport(out m_Client1, out m_Client1Events);
347+
348+
m_Server.SetDebugSimulatorParameters(0, 0, 100);
349+
350+
m_Server.StartServer();
351+
m_Client1.StartClient();
352+
353+
yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client1Events);
354+
355+
var data = new ArraySegment<byte>(new byte[] { 42 });
356+
m_Client1.Send(m_Client1.ServerClientId, data, NetworkDelivery.Reliable);
357+
358+
yield return new WaitForSeconds(MaxNetworkEventWaitTime);
359+
360+
Assert.AreEqual(1, m_ServerEvents.Count);
361+
362+
yield return null;
363+
}
337364
}
338365
}
339366
#endif

0 commit comments

Comments
 (0)