Let's talk

UE Latency Kit v0.2.0

Network emulation profiles and a PowerShell launcher that runs a packaged Unreal Engine 5 server and several clients at real-world latency and packet loss, then records and summarizes each client's round trip, packet loss and bandwidth, so bugs that hide in PIE show up before players find them.

The problem
Play In Editor runs every client on one machine with no lag, so desync, rubber-banding and double-fired abilities stay hidden until players find them.
What it replaces
Setting packet simulation flags by hand, launching and arranging each client yourself, and guessing whether the lag you set is the lag you got.
What it saves
Our estimate: about 15 minutes per test session, and the bugs a no-lag test never shows. One command runs a server and up to 8 clients at 60, 150 or 250 ms.
Who it is for
Anyone testing a UE5 multiplayer game before a playtest or release.

Your multiplayer works in Play In Editor with four clients on one machine. Players are 150 ms away and lose packets. This kit makes your packaged build feel what they feel, and measures what each client actually got.

Free, MIT licensed, no sign-up. Works with any Unreal Engine 5 project; no plugin to install. Tested on a UE 5.7 Development package (listen server plus two clients).

What is inside

FileWhat it does
Config/DefaultEngine.NetEmulation.iniThree packet simulation profiles (average, bad, awful) to paste into DefaultEngine.ini
Scripts/Run-Clients.ps1Starts a listen or dedicated server plus up to 8 clients in tiled windows, all with the same profile. Optionally records each process's network stats
Scripts/Summarize-NetCsv.ps1Turns those recordings into one row per process: round trip, packets per second, packet loss each way, bandwidth saturation

Quick start

  1. Package a Development build (packet simulation and the CSV profiler are compiled out of Shipping).
  2. Run:
PowerShell
.\Scripts\Run-Clients.ps1 -Game "D:\Builds\Windows\MyGame.exe" -Map "/Game/Maps/Arena" -Clients 3 -Preset bad
  1. Play the thing your players complain about. Then run it again with -Preset awful.

-Clients counts clients on top of the listen server, so -Clients 3 opens four windows. Pass -Server with your dedicated server executable to test the real topology.

PresetRound tripLossDuplicates
averageabout 60 ms1 %0 %
badabout 150 ms3 %1 %
awfulabout 250 ms8 %2 %

Measure it

Add -CaptureSeconds and every process records its network stats with the engine's CSV profiler. When the capture ends the script prints a summary and saves it next to the recordings in <Build>/<Project>/Saved/Profiling/CSV:

PowerShell
.\Scripts\Run-Clients.ps1 -Game "D:\Builds\Windows\MyGame.exe" -Map "/Game/Maps/Arena" -Clients 2 -Preset bad -CaptureSeconds 60
TEXT
Role    Seconds RTT avg ms RTT p95 ms RTT max ms In pkt/s Out pkt/s In loss % Out loss % Saturated frames
host         19 -          -          -              74.8      49.5       2.8        3.1                8
client1    19.4 200        231        562              35      57.5       3.9        2.3                0
client2    19.5 196        231        622            35.5        58       2.4        2.7                0

That is a real run of the bad preset. RTT is the engine's raw ping, which includes frame time on both ends, so expect the preset plus 30 to 60 ms at 60 fps. During a capture the frame rate is capped at -CaptureFps (default 60) so frames map to seconds. Network columns need UE 5.4 or later. You can also summarize any capture by hand:

PowerShell
.\Scripts\Summarize-NetCsv.ps1 -Path "D:\Builds\Windows\MyGame\Saved\Profiling\CSV\net-*.csv"

Gotchas this kit handles

  • PktOrder turns the lag off. In UE 5.3 to 5.8 a non-zero PktOrder sends each packet before the PktLag step runs. The presets keep it at 0; lag variance already shuffles timing.
  • PktLag is per process. Server and client each delay what they send, so the script gives each side half the round trip, and the INI profiles are already halved.
  • The packaged exe is a bootstrap. The script launches the real binary under <Project>/Binaries/Win64, so the process ids it prints are the game windows.
  • A busy port is silent. If 7777 is taken, Unreal listens on the next port while clients still join 7777. The script stops with the process that holds it.

What to look for

  • Abilities that fire twice, or fire on the client and never on the server
  • Montages that play on the owner and not on other clients
  • Health or ammo UI that jumps back after a hit
  • Doors, pickups or projectiles that snap

Full walkthrough: Test UE5 multiplayer at real latency.

Help

If the bad profile breaks things you cannot trace, a Diagnostic finds the ownership or prediction cause in two days.

Changelog

v0.2.0 (2026-10-31)

  • -CaptureSeconds: every process records its network stats to a CSV; the script prints a per-process summary when the capture ends.
  • New Summarize-NetCsv.ps1: round trip (avg, p95, max), packets per second, packet loss each way and bandwidth saturation per process.

v0.1.0 (2026-10-30)

  • First release: three packet simulation profiles and the Run-Clients.ps1 launcher.
  • Presets keep PktOrder 0: in UE 5.x a non-zero PktOrder turns PktLag off.
  • INI profiles are halved, because server and client both apply PktLag.
  • Launches <Project>/Binaries/Win64/<Name>.exe rather than the bootstrap exe, so the printed process ids close the game.
  • Stops if the port is already in use, instead of letting clients join a leftover game.

Tutorials that use it

Still desyncing in packaged builds?

Free code fixes one symptom. A Diagnostic finds the cause across your project in two days.