Skip to content

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

  1. Single-process testing shares process-level conditions. It is fast, but not identical to separate game processes.
  2. Listen-server host is not a normal remote client. Always retest from a client window.
  3. Window focus affects input. You may be pressing keys into the wrong PIE window.
  4. Debug filter watches the wrong world. Breakpoints or watches can inspect a different actor copy.
  5. Travel and sessions have PIE limitations. Connection/session/travel flows often need Standalone or external process testing.
  6. Values read too early. GameState/PlayerState/pawn references can arrive after a widget or BeginPlay path first runs.
  7. Print spam hides order. Repeated Tick prints can bury the one print that mattered.
  8. 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