Multiplayer PIE debugging basics¶
Before you decide replication is broken, prove which Play In Editor world ran the graph, which actor copy you inspected, and whether the server ever changed the authoritative state.
The one-minute version¶
- Play In Editor (PIE) can run multiple networked worlds from the editor. Set Number of Players and Net Mode before testing multiplayer behavior.
- Test as a remote client early. Listen-server host testing hides many bugs because the host is both server authority and a local player.
- Window titles and PIE debug filters matter. You can choose which world and actor instance the Blueprint debugger is watching.
- Every multiplayer print should include net mode, authority, local control when relevant, actor name, and the value you care about.
- Use Play as Client or a dedicated server test to catch "this only works because the host has server state" bugs.
- PIE is fast iteration, not a perfect packaged-network simulation. For travel, sessions, process isolation, and timing-sensitive issues, test standalone or separate processes too.
What PIE is doing in multiplayer¶
Single-player PIE usually gives you one game world. Multiplayer PIE can spawn multiple worlds:
Editor process
-> Server world or listen-server world
-> Client 1 world
-> Client 2 world
-> more client worlds if requested
Each world has its own actor instances, player controllers, pawns, widgets, and
replicated copies. When you look at BP_PlayerCharacter_C_0, there may be
several objects with similar names in different PIE worlds.
That is why "I printed and it ran" is not enough. You need to know where it ran.
The settings that matter first¶
Open the Play dropdown near the editor Play button.
| Setting | Beginner meaning |
|---|---|
| Number of Players | Total player windows/clients to test. Use at least 2 for most replication checks. |
| Net Mode: Play as Listen Server | First player is both server and local player. Fast, but host-only bugs hide here. |
| Net Mode: Play as Client | Editor window is a client connected to a dedicated server running in the background. Good for remote-client bugs. |
| Run Dedicated Server | Launch a server with no local player. Catches code that assumes the server has UI/input/audio. |
| Run Under One Process / Use Single Process | Faster iteration with shared editor process; less representative than separate processes. |
| New Editor Window (PIE) | Gives each player a visible window instead of hiding one in the viewport. Easier to tell who is who. |
| Network Emulation | Adds latency/loss profiles so unreliable logic and prediction assumptions get tested. |
Good first configurations:
Basic remote-client check:
Number of Players = 1
Net Mode = Play as Client
Dedicated server runs in the background
Host vs client comparison:
Number of Players = 2
Net Mode = Play as Listen Server
two windows visible
Dedicated server plus clients:
Number of Players = 2
Run Dedicated Server = true
no host-player shortcut
If a feature works as listen-server host but fails in Play as Client, the code probably depends on server-only state, host-only local UI, or an ownership path the remote client does not have.
Label every print¶
A useful multiplayer print is not:
"Fire"
It is:
"Fire | Actor=BP_PlayerCharacter_2 | NetMode=Client | Authority=false | Local=true | Ammo=5"
Print these fields while debugging:
| Field | Why |
|---|---|
| Actor display name | Proves which instance printed. |
| Get Net Mode | Distinguishes Standalone, Client, Listen Server, Dedicated Server. |
| Has Authority | Shows whether this actor copy is authoritative. |
| Is Locally Controlled | For pawns, shows whether this is the local player's pawn. |
| PlayerState / Controller name | Helps catch wrong-player and unowned-RPC bugs. |
| Value before/after | Proves whether the state changed where you think it did. |
| World/client label if available | Helps separate Client 1, Client 2, and server windows. |
Use the Key pin on Print String when a value changes every frame, so one line
updates instead of flooding the screen.
Pick the right debug world and object¶
When multiple PIE worlds are running, the Blueprint debugger has to know which world and instance to watch.
Use the Blueprint editor's debug controls:
Debug world:
All Worlds
Server / Listen Server world
Client 1 world
Client 2 world
Debug object:
the specific actor instance in that world
If All Worlds is selected, a breakpoint may stop for any matching actor in any PIE world. That is useful for broad discovery and terrible when you think you are stepping the owning client.
Better loop:
1. Run PIE with multiple windows.
2. Note the window title: Server, Client 1, Client 2, or similar.
3. In the Blueprint editor, choose the matching debug world.
4. Pick the specific actor instance from that world.
5. Breakpoint the graph.
6. Trigger the action in the matching window.
If the breakpoint does not hit, do not move the breakpoint randomly. First confirm you selected the right world and actor.
What to test before blaming replication¶
For a replicated variable:
1. Did the server set the variable?
2. Is the actor replicated?
3. Is the variable Replicated or RepNotify?
4. Is the actor relevant to this client?
5. Did the client receive the actor before you read the value?
6. Did a local widget read the right actor copy?
For a Server RPC:
1. Did the owning client call it?
2. Is the target actor replicated?
3. Does the client own that actor or its owning connection?
4. Did the server-side print inside the RPC run?
5. Did the server validate and change state?
6. Did replicated state or a client RPC send the result back?
For a multicast:
1. Was it called by the server?
2. Is the actor replicated and relevant to the clients you expect?
3. Is the event transient enough that late clients do not need it?
4. Would RepNotify state be better?
Most beginner bugs fail one of these checks before you get to advanced network settings.
Listen server vs dedicated server¶
A listen server is server authority and a local player at the same time.
Good for:
- quick two-window iteration;
- local co-op/hosted game checks;
- seeing host and one remote client side by side.
Risk:
- host UI can read server-only state;
- Authority and Is Locally Controlled can both be true for the host;
- code that fails for remote clients may look correct.
A dedicated server has no local player screen.
Good for:
- proving server code does not create widgets, cameras, or local-only audio;
- proving all players are real clients;
- catching host-only shortcuts.
Risk:
- less convenient to inspect visually;
- some editor shortcuts feel different;
- session/travel flows may still need standalone process tests.
Use both. A feature is not "multiplayer safe" because it worked in the host window.
A first debugging pass for common features¶
Fire weapon¶
Client window:
Input Fire print:
NetMode=Client, Authority=false, Local=true
ServerFire called on owned pawn/controller
Server:
ServerFire print:
NetMode=ListenServer or DedicatedServer, Authority=true
validate ammo/cooldown
spawn replicated projectile or apply server trace
Clients:
projectile appears or replicated ammo/impact state updates
If only the host fires, check whether input was gated behind Authority. If the remote client prints input but the server RPC does not print on the server, check ownership.
Health bar¶
Server:
damage accepted
Health changes on authoritative actor or PlayerState
Client:
OnRep_Health print with new value
local widget reference valid
widget row belongs to correct player
If the value changes but UI does not, debug the local widget binding/event. If the UI updates locally but other clients do not see it, the server probably did not change replicated state.
Ready button¶
Owning client:
widget click print
ServerSetReady called through PlayerController/owned pawn
Server:
PlayerState.bReady set true
GameMode checks all PlayerStates
GameState.MatchPhase changes if ready
Clients:
PlayerState OnRep_Ready updates lobby rows
GameState OnRep_MatchPhase updates shared phase UI
If Client 1 ready toggles Client 2's row, you probably read the wrong PlayerState or reused one widget reference for multiple rows.
When PIE itself can fool you¶
- Single-process testing shares process-level conditions. It is fast, but not identical to separate game processes.
- Listen-server host is not a normal remote client. Always retest from a client window.
- Window focus affects input. You may be pressing keys into the wrong PIE window.
- Debug filter watches the wrong world. Breakpoints or watches can inspect a different actor copy.
- Travel and sessions have PIE limitations. Connection/session/travel flows often need Standalone or external process testing.
- Values read too early. GameState/PlayerState/pawn references can arrive after a widget or BeginPlay path first runs.
- Print spam hides order. Repeated Tick prints can bury the one print that mattered.
- Host-only authority hides remote ownership bugs. A Server RPC call path works from the host because the host is already the server.
The fix is not "never trust PIE." The fix is to choose the PIE mode that matches the question and label the world you are observing.
A compact multiplayer debug checklist¶
Use this before changing code:
For the graph I think is broken:
Which PIE window did I trigger?
Which debug world/object is selected?
Did the graph print on client, server, or both?
Does the actor have Authority there?
Is this pawn Locally Controlled there?
Who owns the actor for RPC purposes?
Did the server change the replicated value?
Did the client receive the value or event?
Did local UI/audio/VFX respond on the correct client?
If you cannot answer those questions, you do not yet know whether the bug is replication, ownership, timing, UI, or just the wrong PIE instance.
Lookalikes - which one do I want?¶
| Tool / setting | Use when | Not for |
|---|---|---|
| Print String | Fast proof of which graph ran and with what values. | Final logging or high-volume tick spam. |
| Output Log | Persistent text with categories and history. | Knowing which player saw an on-screen print unless you label it. |
| Blueprint Debugger / breakpoint | Pausing one graph and inspecting pins. | Assuming All Worlds means the owning client. |
| Number of Players | Creating multiple player/client worlds. | Testing dedicated-server behavior by itself. |
| Play as Listen Server | Host + client comparison. | Proving remote-client-only behavior is correct. |
| Play as Client | Remote client connected to background dedicated server. | Host-player camera/UI behavior. |
| Run Dedicated Server | No-local-player server checks. | Debugging local UI by looking at the server. |
| Network Emulation | Latency/loss behavior after the basic flow works. | Fixing ownership or missing replication setup. |
Going deeper¶
- Print String and the Output Log - screen/log output, keys, and development-only debug prints.
- Breakpoints and watch values - selecting the right instance and reading pins without guessing.
- Has Authority / Switch Has Authority / Is Locally Controlled - the values your multiplayer prints should include.
- Blueprint Custom Events as RPCs - debug why a Server RPC did or did not run.
- RepNotify variables and local presentation - debug why replicated state arrived but UI did not update.
- Official docs: Testing Multiplayer, Play In Editor Multiplayer Options, Testing and Debugging Networked Games, and Network Debugging.
- Engine/editor source (requires engine access - we do not reproduce it
here): PIE setup and multi-world play live in editor code under
Engine/Source/Editor/UnrealEd/Private/PlayLevel.cpp; networked PIE path remapping is referenced fromUEditorEngine::NetworkRemapPath; runtime net mode and role checks come from actor/controller code underEngine/Source/Runtime/Engine/Classes/GameFramework/andEngine/Source/Runtime/Engine/Private/.