How multiplayer works¶
MPFriendslopV2 runs as a listen server. One player hosts: their game is the server, and the other players join it as clients. The host plays like everyone else.
A run started with SOLO RUN opens the map without the listen option, so nobody can join it. Hosting goes through HOST RUN, which is covered in Sessions and the lobby.
What the server decides¶
The server holds the truth for everything that changes the game. A client asks, the server checks, and the result reaches every player.
| What | Decided by | What every player sees |
|---|---|---|
| Movement | The server, through Character Movement. The moving player predicts locally | Every player's position |
| Health and damage | The server applies damage and writes the vitals | The current health and stamina values |
| Doors, buttons and levers | The server, after checking that the player is in reach | The door in its current state |
| Grabbing | The server accepts or refuses the grab, and decides when it breaks | Who holds what, and where it is |
| Loot value, breaks and sales | The server measures every hit | The item's condition, its break, its sale |
| Quota and extracted value | The server, on the GameState | The same totals for everyone |
| Enemies | The enemy's brain runs on the server only | The enemy's body and state |
| Worn cosmetics | The server | Each player's outfit |
What each player draws for themselves¶
Some things never cross the network. Each machine builds them on its own, for its own player:
- the camera feel (bob, landing, crouch),
- the HUD, the interaction prompt and the highlight on what you look at,
- the walking and running footsteps, and the damage feedback,
- the key icons, and the key rebinding,
- the run clock, counted by each machine from one shared end time,
- the pieces of a broken item, which land in different places on each machine.
Credits and the cosmetics a player owns are saved on that player's own machine. What they wear is shared.
Players who join late¶
A player who joins in the middle of a run receives the state of the game, not its history. An open door, a damaged item, a dead player's head or an outfit reach them, because each one is a replicated value. A one-off event, like the flash and sound of an old impact, is not replayed. That is intended.
A player who joins late sees the loading screen until their own modules are visible. The run is not restarted for them.
A player who connects while the end-of-run recap is on screen does not spawn: they spectate until the next run. The same goes for a player who connects during the arena: they spectate until the recap.
The lobby holds four players by default. The cap is Max Players, chosen by the host before the lobby opens.
Rules for your own additions¶
- Change a state on the server. A value changed on a client stays on that client.
- A state that lasts is a
Replicatedvariable, not an event. AMulticastsent before a player joined never reaches that player. - A
Run on Serverevent checks what it receives. The template's own requests check distance and permission before acting. Do the same, or any client can call yours with anything.
On a listen server, the host is both the server and a locally controlled player. So Has Authority and Is Locally Controlled are both true there, and a mistake between the two never shows on the host.
For logic meant for one player only, check Is Locally Controlled at the moment the logic runs, not once in BeginPlay. A respawned pawn gets its controller after its BeginPlay.
Dispatcher tables in this manual have a Fires on column: server, every player, or owning player (the player who acted, on their own machine). Bind to the one that matches where your reaction must run.
Testing with two players¶
Always judge from the client window, never from the host's. The host is the server, so an authority mistake works there and breaks only on a client.
The quick test, in the run map:
- Open
L_Procedural(it is the editor startup map). - In the Play menu, set Number of Players to
2and Net Mode toPlay As Listen Server. - Press Play and look at the client window.
This skips the menu and the lobby. It is enough for everything that happens during a run.
The full test, from the menu:
- In the Play menu, open Advanced Settings and untick
Run Under One Process. - Open
L_MainMenuand press Play with two players. - Host with
HOST RUNin one window, join from the other.
Use this one for the private code, the shop terminal and anything saved. Two players in one process share the session search, the mouse focus on world screens and the save slot. In that setup clicks on the shop screen do nothing and credits look wrong.
On a single PC, with the default online subsystem, the browser of one window does not list the session hosted by another window, even in two processes. Join it with the console command open 127.0.0.1 instead, and test the browser itself on two PCs.
Starting L_MainMenu as a listen server does not put you in a lobby: you land on the main menu and host from there.
The dedicated server test:
- Open
L_Procedural. - In the Play menu, set Net Mode to
Play As Clientand Number of Players to2or more. - Press Play. The editor runs a dedicated server with no window, and every window is a client.
There is no host on a dedicated server. The RESTART button belongs to the crew leader, the player connected the longest, and passes to the next one when that player leaves. The server has no screen, so OnModulesVisible never fires on it.
In the editor, the dedicated server plays the map that is open. A server started without a map loads Server Default Map (Project Settings > Maps & Modes), which is L_Procedural. Packaging a dedicated server needs a source build of Unreal Engine and a C++ project with a Server target: see Setting Up Dedicated Servers in the Unreal documentation.
START THE RUN and RESTART change map with seamless travel, which the editor turns off in PIE by default. Config/DefaultEngine.ini turns it back on with net.AllowPIESeamlessTravel=1, under [ConsoleVariables], so the other players follow the host in PIE as they do in a packaged game. Keep that line if you move these maps into a project of your own.
Values on placed actors¶
Warning
A value typed on a placed actor wins over the class default. And a variable added to a component after that component was placed keeps the empty value of its type (0, false, None) on every copy already placed, with no error. After you change or add a field, open the Details of the placed actors and of each Blueprint that carries the component, and check the value.
Next, see The maps, and how a game starts and The controls, and adding an input.