Skip to content

Step 09: Multiplayer

BavGames edited this page Jul 23, 2026 · 4 revisions

Works in Listen Server and Dedicated Server. Single player needs nothing from this page.

The model: server-authoritative

  • Only the server saves and loads. Save/Load called on a client is refused with a clean error. Gate your UI with Has Save Authority.
  • The save file lives on the server. Clients have no save files.
  • A client can ask the server by adding a Save Request Component to its PlayerController and calling Request Save / Request Load - the server decides.

What clients receive automatically

After a server load, the restored state is mirrored to every client - no setup:

  • Actor and component positions (including physics meshes)
  • SaveGame variable values at the moment of the load
  • Destroyed actors are destroyed on clients too
  • On Loaded fires on clients as well - update text renders, materials, visuals there
  • Late joiners receive the last loaded state when they connect

Delivery is bandwidth-safe: only changed entries are sent, in paced batches, with quantized transforms, and the sync actor costs zero network time between loads.

image

Joining and leaving: zero setup

Both directions are handled automatically - no BeginPlay logic, no component required (the Save Request Component only exists for Request Save / Request Load):

  • A player joins (or rejoins): the server restores their saved data (and, per the Pawn Policy from Step 06, their position/body), and the sync actor delivers the loaded world state over their new connection. Opt out with the Restore Late Joiners setting.
  • A player leaves (quit or connection loss): their state is snapshotted at that moment and written to the active slot, so a world save made later - or never - cannot lose their progress. Details in Step 06; opt out with the Save Players On Logout setting.

"Load finished" event on clients

Clients cannot bind to the Save Subsystem's load events (loads run on the server). For client UI ("Game Loaded" popup, fade-in), bind to On Load Complete Replicated on the USS Replication Controller actor (find it with Get Actor Of Class after joining). It fires on every machine once the loaded state has been delivered.

image

What still needs YOUR replication

The sync mirrors the moment of the load - it is a snapshot, not live replication. A variable that changes during play reaches clients only if you mark it Replicated (with RepNotify if you drive visuals from it). This is the standard Unreal rule; the save system does not change it.

Rule of thumb: loaded state = handled by the plugin; live gameplay state = your replication.

Two safety rules built in

  • Clients never locally move a replicated actor's root (server movement replication owns it).
  • Clients never touch player-controlled pawns (their movement is client-predicted).

Testing checklist

  1. Turn on Verbose Logging (Step 05) - the diagnostic lines below are silent without it.
  2. PIE settings: Net Mode = Play As Listen Server, Number of Players = 2. (Play Standalone starts two separate offline games - nothing can replicate.)
  3. Save and load in the server window.
  4. Both windows must show identical restored state.

Log lines to look for:

Server: Load 'Slot': syncing 12 actor transform(s) to 1 connected client(s).
Client: Replication controller ready on client (12 sync item(s) present).
Client: applied restored transforms for 12 of 12 actor(s).

If the "controller ready" line never appears in the client log, there is no replication in the session - check the PIE Net Mode first.

image image image

Next: Step 10: Persistent & Custom Objects

Clone this wiki locally