Skip to content
pluginv2.1Blueprint only

ScarMultiSession

Plug-and-play multiplayer session plugin.

ScarMultiSession handles the full multiplayer flow: hosting, smart matchmaking, a replicated lobby with a live player count and countdown, and travel to your playable map. You focus on your game instead of Online Subsystem plumbing. In version 2.1 the whole plugin is configured from a single Project Settings page, and a built-in Setup Doctor checks your project the moment you press Play.

Engine support
Unreal Engine 5.2 and newer
Version
2.1
Backends
Steam, EOS, LAN (NULL), Any OSS

What you get

  • One Project Settings page configures maps, match size, match type and widgets
  • Required Players is a single number that sizes the session and starts the match
  • Replicated lobby with live player count, countdown and optional host-only Force Start
  • Setup Doctor validates your project on Play and tells you exactly what to fix
  • Backend agnostic: Steam, EOS, LAN or any OSS with no code changes
  • Optional loading screen so players never see a frozen frame during travel

Introduction and overview

ScarMultiSession is a plug-and-play multiplayer session management plugin for Unreal Engine 5. It handles the full flow, from hosting and smart matchmaking to a replicated lobby with a live player count and countdown, and travel to your playable map.

In version 2.1 the plugin is configured from a single Project Settings page. You set your three maps, the match size, the match type and your lobby widget once, and the menu and lobby read everything from there. A built-in Setup Doctor checks your project the moment you press Play and tells you exactly what to fix.

What the plugin provides

ClassWhat it does
UScarMultiSessionSettingsNew. A Project Settings page (Plugins > Scar MultiSession), the single place to configure maps, match size, match type, lobby widget and an optional loading screen.
UMultiplayerSessionsSubsystemAuto-initialising GameInstance subsystem exposing Create, Find, Join, Destroy and Start session operations with dynamic multicast delegates.
UQuickJoinMenuSingle-button smart matchmaking widget. Finds an open session, or hosts one if none exists. This is the entry menu.
ULobbyMenuLobby waiting-room widget: live player count, optional host-only Force Start, and a synced countdown. Auto-destroyed when the match starts.
AScarLobbyGameModeLobby GameMode. Spawns the lobby UI on each player own client, replicates the count to everyone, and auto-travels to the game map when the lobby is full.
AScarLobbyPlayerControllerNew. Spawns the lobby widget on the owning client, which fixes the "Only Local Player Controllers can be assigned to widgets" error, and relays Force Start.
AScarLobbyGameStateNew. Replicates the live player count, required count and countdown to every client.
AScarMultiSessionGameModeBase GameMode for your game level. Subclass it for team assignment, pawn customisation and so on.
FScarSetupDoctorNew. Development-time validation that reports misconfigurations with clear fix-it guidance.

Who is this plugin for

ScarMultiSession is for Unreal developers who want a working session and lobby layer without spending days fighting the Online Subsystem API.

  • Indie developers who need a working host, join and lobby system in under an hour.
  • Prototypers and game-jam teams who need multiplayer running fast, with near-zero configuration.
  • Intermediate Unreal developers comfortable with Blueprints but new to the OSS API.
  • Commercial studios wanting a backend-agnostic session layer (Steam, EOS, LAN) with no vendor lock-in.
  • Educators, since the source is fully commented and ASCII-clean for readability.
  • Plugin and system authors who need session awareness without rebuilding the session layer.

Supported backends

The plugin is built on the abstract Unreal Online Subsystem interface, so it works with any OSS provider with no code changes. Switching backends is a DefaultEngine.ini edit.

Steam (OnlineSubsystemSteam)

The common choice for PC. Real lobby matchmaking, friend sessions, presence and invites. Needs the OnlineSubsystemSteam plugin enabled and a Steam App ID. App ID 480 (Spacewar) works for testing.

Epic Online Services (OnlineSubsystemEOS)

Free cross-platform services: matchmaking, lobbies, voice and achievements. Needs the OnlineSubsystemEOS plugin and an Epic Developer Portal product. The plugin enables the lobby path EOS requires.

LAN and NULL (OnlineSubsystemNull)

Zero-configuration local play. No accounts, SDKs or internet. LAN mode is detected and enabled automatically when the NULL subsystem is active.

Any custom OSS (IOnlineSession)

Because the plugin only talks to the IOnlineSession interface, any compliant custom or third-party OSS works automatically.

You can have several OSS plugins installed. Only DefaultPlatformService in DefaultEngine.ini decides which one is active at runtime. The rest of the plugin is identical.

Installation

Install and enable

  1. 01Purchase ScarMultiSession on Fab or the Epic Games Marketplace; it appears in your library.
  2. 02In the Epic Games Launcher, install it to your engine version (5.2 or newer).
  3. 03Open your project, go to Edit > Plugins, search ScarMultiSession, tick Enabled, and restart.
  4. 04ScarMultiSession declares OnlineSubsystem and OnlineSubsystemUtils as dependencies, so they are enabled for you.

Manual (zip) install

  1. 01Extract the zip. It contains a folder named ScarMultiSession_UE5_X.
  2. 02Rename it to ScarMultiSession, dropping the version suffix.
  3. 03Copy it to [YourProject]/Plugins/ScarMultiSession/.
  4. 04Reopen the project. If prompted to rebuild, click Yes. Enable it via Edit > Plugins.

If your project is Blueprint-only, there is nothing else to link. The plugin modules load automatically.

DefaultEngine.ini backend configuration

Pick the backend you are shipping. The file is at [YourProject]/Config/DefaultEngine.ini.

Keep every .ini entry on ONE line. Never split +NetDriverDefinitions=(...) or +Artifacts=(...) across lines, or Unreal reports "Missing closing parenthesis", the GameNetDriver never builds, and Play as Client fails.

Steam

[OnlineSubsystem]
DefaultPlatformService=Steam

[OnlineSubsystemSteam]        ; replace 480 with your real App ID to ship
bEnabled=true
SteamDevAppId=480

[/Script/Engine.Engine]
!NetDriverDefinitions=ClearArray
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")

Epic Online Services (EOS)

[OnlineSubsystem]
DefaultPlatformService=EOS

[OnlineSubsystemEOS]
bEnabled=true

[/Script/OnlineSubsystemEOS.EOSSettings]
CacheDir=EOSCache
DefaultArtifactName=MyProduct
+Artifacts=(ArtifactName="MyProduct",ClientId="...",ClientSecret="...",ProductId="...",SandboxId="...",DeploymentId="...",EncryptionKey="")

Never commit your EOS Client Secret to source control. Use environment variables or a secrets manager in your build pipeline.

LAN / local testing (NULL)

[OnlineSubsystem]
DefaultPlatformService=NULL

[OnlineSubsystemNull]
bEnabled=true

[/Script/OnlineSubsystemUtils.IpNetDriver]
NetServerMaxTickRate=60

For LAN and NULL you do not need any NetDriverDefinitions. To test on one PC, package the game (or use Standalone with "Run Under One Process" unchecked) and launch two copies. Single-process PIE will not discover NULL sessions.

Central configuration (Project Settings)

This is the one place you configure the plugin. Open Edit > Project Settings > Plugins > Scar MultiSession. The menu and lobby read everything from here, so you never set the same value twice.

SettingWhat it does
Main Menu MapMap the Leave button returns to. Pick your menu level.
Lobby MapWaiting-room map hosted as a listen server after Quick Join.
Game MapPlayable map travelled to once the lobby is full.
Required PlayersThe match size, one number. Sizes the session and starts the match when this many gather.
Countdown DurationSeconds before travelling once the lobby is full. 0 means instant.
Lobby Widget ClassYour WBP_LobbyMenu, parented to ULobbyMenu.
Match TypeTag that keeps different modes from matching together, for example FreeForAll.
Loading Screen Widget ClassOptional. Shown during travel so players never see a frozen frame.

One number for player count. Required Players is the only count you set. The session is sized to hold exactly that many, and the match auto-starts the moment they are gathered. Set 2 for a two-player match, 4 for four.

The three maps are picked as asset references, so selecting them here also makes them cook into packaged builds automatically. No more "missing map" travel failures.

Widget setup

Create Widget Blueprint subclasses of the plugin widget classes and add the required named widgets. Names are case-sensitive.

WBP_LobbyMenu (parent: ULobbyMenu)

  • Create a Widget Blueprint with parent class ULobbyMenu and name it WBP_LobbyMenu.
  • Required: StatusText (TextBlock) and LeaveButton (Button).
  • Optional: ForceStartButton (Button, auto-hidden on clients) and CountdownText (TextBlock).
  • No properties to set. The menu map for Leave comes from Project Settings.
  • Assign this widget to Lobby Widget Class in Project Settings.

WBP_QuickJoinMenu (parent: UQuickJoinMenu)

  • Create a Widget Blueprint with parent class UQuickJoinMenu and name it WBP_QuickJoinMenu.
  • Required: QuickJoinButton (Button). Optional: StatusText (TextBlock).

WBP_LoadingScreen (optional, any UUserWidget)

  • Create any Widget Blueprint. A full-screen image or "Loading..." text is enough.
  • Assign it to Loading Screen Widget Class in Project Settings to enable it. Leave blank to disable.
  • Editor PIE skips loading screens by design. It is visible in Standalone and packaged builds.

Game mode and map setup

Lobby GameMode (BP_LobbyGameMode)

  • Content Browser > Blueprint Class, search ScarLobbyGameMode, name it BP_LobbyGameMode.
  • There is nothing to configure on it. All lobby settings live in Project Settings.
  • Open your Lobby map > World Settings > set GameMode Override to BP_LobbyGameMode.

Do not override Player Controller Class or Game State Class on BP_LobbyGameMode. The plugin sets AScarLobbyPlayerController and AScarLobbyGameState automatically, and overriding them breaks the client-side lobby UI.

Game-level GameMode (BP_GameGameMode)

  • Blueprint Class > ScarMultiSessionGameMode, name it BP_GameGameMode. Optional but recommended.
  • Set its Default Pawn Class to your character, and override PostLogin / Logout for game logic.
  • Open your Game map > World Settings > set GameMode Override to BP_GameGameMode.

The three maps

MapGameModeNotes
Main MenuAny (or None)Hosts your WBP_QuickJoinMenu. Set as Main Menu Map in settings.
LobbyBP_LobbyGameModeWaiting room. Set as Lobby Map in settings.
GameBP_GameGameModeYour gameplay map. Set as Game Map in settings.

Blueprint integration

The entire entry flow is one node. In the Level Blueprint of your Main Menu map (or a menu Actor), on BeginPlay:

  1. 01Create Widget (Class = WBP_QuickJoinMenu).
  2. 02Call Quick Join Menu Setup on it. It takes no parameters: match type, lobby map and match size all come from Project Settings.
  3. 03Add to Viewport. Clicking the button finds or hosts a game and walks the player through the lobby into the match.

On NULL and LAN, have player 1 reach the lobby before player 2 clicks. If both search at the exact same instant, each hosts its own lobby, the classic matchmaking race. Steam and EOS resolve this with real matchmaking.

Calling the subsystem directly (advanced)

  • Get Game Instance > Get Subsystem (Class = MultiplayerSessionsSubsystem).
  • Call CreateSession / FindSessions / JoinSession / DestroySession / StartSession.
  • Bind the matching delegate (for example MultiplayerOnFindSessionsComplete) BEFORE calling the function.

Setup Doctor and debugging

Development builds include a self-check that catches the things that silently break multiplayer.

Setup Doctor

  • Runs automatically when your Main Menu map loads, at the start of every play session.
  • Checks: Online Subsystem active, all three maps set and cooked, lobby widget set, and a sane player count.
  • Prints a PASS / FIX report to the screen and to the Output Log under category LogScarSession.
  • Run it any time from the console (press ~): scar.RunDoctor
==== Scar MultiSession Setup Doctor (map: menu_map) ====
[Setup Doctor] PASS: Online Subsystem 'NULL' is active.
[Setup Doctor] PASS: Lobby map '/Game/Maps/Lobby' is present.
[Setup Doctor] PASS: Lobby Widget Class is set.
[Setup Doctor] PASS: Required Players = 2.
[Setup Doctor] All checks passed.

Logging and debug toggle

  • LogScarSession (Output Log, or the packaged Saved/Logs/*.log) traces the full flow: create, find, join, the resolved connect address, and travel.
  • On-screen status messages are gated by a console variable. Ship clean with scar.ShowDebug 0. The default is 1, meaning on.

Plugin classes reference

UScarMultiSessionSettings (UDeveloperSettings, Project Settings)

  • MainMenuMap / LobbyMap / GameMap (soft map references)
  • RequiredPlayers, CountdownDuration, MatchType
  • LobbyWidgetClass, LoadingScreenWidgetClass
  • Get(), GetLobbyURL() / GetGameURL() / GetMainMenuURL()

UMultiplayerSessionsSubsystem (GameInstanceSubsystem, auto-init)

  • CreateSession(int32 NumPublicConnections, FString MatchType)
  • FindSessions(int32 Max), JoinSession(Result)
  • QuickJoinOrHost(int32 NumPublicConnections, FString MatchType)
  • DestroySession(), StartSession(), IsSessionInterfaceValid()
  • Delegates: OnCreate / OnFind / OnJoin / OnDestroy / OnStart Complete

UQuickJoinMenu (UUserWidget, entry menu)

  • QuickJoinMenuSetup(), no parameters; reads Project Settings
  • Bound button: QuickJoinButton

ULobbyMenu (UUserWidget, lobby waiting room)

  • No public API; driven by the lobby GameState
  • Bound: StatusText, LeaveButton, ForceStartButton (optional), CountdownText (optional)

AScarLobbyGameMode (AGameModeBase, lobby levels)

  • ForceStartMatch() (host only)
  • GetCurrentPlayerCount(), GetRequiredPlayerCount()
  • OnPlayerCountChanged(Current, Required)

AScarLobbyPlayerController (APlayerController, lobby)

  • Client_SetupLobbyUI(WidgetClass), spawns UI on the owning client
  • Server_RequestForceStart(), host-validated

AScarLobbyGameState (AGameStateBase, lobby)

  • Replicated: CurrentPlayers, RequiredPlayers, bMatchStarting, CountdownEndServerTime

AScarMultiSessionGameMode (AGameModeBase, game levels)

  • Subclass in Blueprint or C++; override PostLogin / Logout

FScarSetupDoctor (C++ helper, development)

  • Run(UWorld*), validates project setup; also via "scar.RunDoctor"

Common issues and fixes

First, run the Setup Doctor. Press ~ and type scar.RunDoctor, or read the screen and Output Log on Play. It pinpoints most setup problems (missing maps, OSS not active, unset lobby widget) in one report.

Match never starts, or both players host their own lobby

On NULL and LAN both players searched before either advertised. Let player 1 reach the lobby first, then have player 2 click. Always test NULL with two separate processes (packaged or Standalone, not single-process PIE).

Travel fails, or "missing map" in a packaged build

Make sure the three maps are picked in Project Settings; they are soft references and cook automatically. You can also add them under Project Settings > Packaging > List of Maps to Include.

"Only Local Player Controllers can be assigned to widgets"

Resolved in 2.1. The lobby UI is created on each client by AScarLobbyPlayerController. Ensure BP_LobbyGameMode does not override Player Controller Class.

Cannot move after entering the game map

Resolved in 2.1. Input is restored to Game mode on lobby exit. If you use a custom pawn or controller, ensure it sets Game input mode on BeginPlay.

"Couldn't Launch PIE Client" or NetDriver failure

Your +NetDriverDefinitions line is split across multiple lines in DefaultEngine.ini. Put it back on one line under [/Script/Engine.Engine], or delete it for LAN and NULL. Restart the editor afterwards.

Find Sessions returns zero results

Steam and EOS: both machines must be online and on the same backend. LAN: same network, separate processes. MatchType must match between create and find, and since it comes from settings, it will.

ForceStartButton shows on clients

Host detection uses authority on the owning controller. Confirm Lobby Widget Class points to WBP_LobbyMenu and that ForceStartButton exists with that exact name.

Quick reference card

ItemValue / action
Plugin folder nameScarMultiSession
Enable viaEdit > Plugins > search ScarMultiSession
Configure everything inProject Settings > Plugins > Scar MultiSession
Entry widget parentUQuickJoinMenu (call QuickJoinMenuSetup(), no params)
Lobby widget parentULobbyMenu
Lobby GameMode parentAScarLobbyGameMode (no per-map config)
Game GameMode parentAScarMultiSessionGameMode
Match sizeRequired Players (one number = session size plus start)
Validate setupconsole: scar.RunDoctor
Silence on-screen debugconsole: scar.ShowDebug 0
Diagnostic log categoryLogScarSession
Pick backendDefaultEngine.ini DefaultPlatformService = NULL / Steam / EOS

Stuck on something?

We answer every serious message ourselves. Discord is the fastest way to get an answer from the person who built the plugin.