Ali Şahan Yalçın
DocsSessions

Sessions

Sessions

A higher level layer over lobbies: host and travel in one node, with standard metadata.

The lobby pages give you the raw pieces. The session layer stacks a common arrangement of them into single nodes, so you do not have to design your own metadata keys or remember the order of the host steps.

A session is a lobby, with agreed keys on it. Everything on the lobby subsystem still works underneath.

Use sessions if you want a working host and join flow quickly. Use lobbies directly if you want full control over the metadata.

INFO: If you have not built an Unreal multiplayer flow before, work through the tutorial instead. It builds a host, a browser and a join that work, and explains the pieces as it goes. This page is the explanation underneath it.

What you need before hosting

Three things, and getting any of them wrong produces a failure that looks like something else:

RequirementWhyWhat goes wrong without it
A map to travel to, by asset nameThe host travels there and listens for connectionsHosting reports success and nothing happens
Steam reporting Available: yesEverything here is Steam matchmakingEvery node fails immediately
Two distinct Steam identities to test withTwo windows on one account are the same playerJoins appear to work and nothing is really tested

The third is the one people lose time to. See Testing with two players.

Hosting

Host Session And Travel does five things in the right order:

  1. Creates the lobby.
  2. Publishes your session settings as lobby data.
  3. Sets Rich Presence, so friends get a Join Game button.
  4. Travels to the map as a listen server.
  5. Publishes the connect string that travel produced, so joiners can reach it.

Missing step 3 is why invites often do nothing. Missing step 5 is why players sit together in a lobby while the host plays alone.

The last two cannot be swapped. The listen server does not exist until the map has loaded and a port is bound, so there is nothing to publish before travelling. SteamForge keeps trying after travel until the server is genuinely up, which is why the node's On Success fires before the session is joinable.

InputMeaning
SettingsThe session settings struct, below
TravelUntick to create the session and stay put, for a pre match lobby
WARNING: Travel is an advanced pin. Click the arrow at the bottom of the node to see it.

The two ways to host

Which one you want depends on whether players gather first.

TravelWhat you getUse it when
TickedThe host goes straight into the match. Anyone who joins later follows immediately.Drop in games, or a Play Now button
UntickedA pre match lobby. Everyone gathers, nobody travels.A ready up screen, team selection, map voting

With Travel unticked, call Start Match when the match begins. It travels the session you already have.

WARNING: Do not call Host Session And Travel a second time to start the match. It creates a new lobby every time, so the players in your pre match lobby stay in the old one and never follow.

What the joiners do

Nothing, in most cases. This is worth stating plainly because it is the part people write code for that they do not need.

  • Joining a session the host has already started: Join Session reads the published address and travels there. Done.
  • Joining a session the host has not started yet: the player stays in the lobby. When the host starts, SteamForge sees the address appear and travels them automatically.

Both paths are covered by one Join Session call with Travel ticked. Untick it if you want to handle travel yourself, and the automatic follow is disabled with it.

Session settings

FieldMeaning
Session NameShown in the browser
Map NameWhere to travel. Required when Travel is on.
Game ModeFree text, yours to interpret
Max PlayersIncluding the host
PrivateFriends only rather than publicly listed
PasswordOptional. See passwords.
Build IdOptional override for this session. Leave empty to use the project's.
Extra DataAny other keys you want published and searchable

Keeping incompatible builds apart

Two players on different builds can join each other and desync in ways that look like bugs in your game. Version gating stops that at the door.

It is off until you turn it on. Set Session Build Id in Project Settings > Plugins > SteamForge and three things start working at once:

WhereWhat happens
HostingThe value is published with the session automatically
JoiningA mismatch is refused with Version Mismatch before the player is in far enough to desync
SearchingResults carry Version Compatible, and Find Sessions can filter on it

An empty value on either side means opting out, so a project that never sets one is unaffected.

WARNING: Set it to something that changes when your netcode changes, like a build number or a protocol version. Pointing it at a marketing version splits your player base every time you ship a text fix.

Read the local value back with Get Local Build Id if you want to show it on a screen.

Finding sessions

Find Sessions returns results with their metadata already read:

FieldMeaning
Session Name, Map Name, Game ModeAs the host published them
Current Players, Max PlayersOccupancy
Host Steam IdWho is hosting
Password ProtectedWhether a password is needed
Version CompatibleWhether the host's Build Id matches yours
INFO: Grey out incompatible sessions rather than hiding them. A player who cannot see the session their friend is in assumes the game is broken, whereas a greyed out row with "different version" explains itself.

Joining

Join Session takes a session, an optional password, and whether to travel. It reports a full diagnosis rather than a bare true or false. See Join diagnostics.

Managing a live session

On the SteamForge Sessions subsystem:

NodeWhat it does
Is In SessionHosting or joined
Is Session HostThe local player is the host
Get Session SettingsWhat the session was created with
Update Session SettingsChange them. Host only.
Start MatchTake this session into its map, bringing its members with you. Host only.
Set Session JoinableStop accepting new players without ending the session
Publish Connect StringRepublish where the host is listening. Host only.
Get Session Connect StringThe URL joiners travel to, or empty while the host has not started
Get Session DiagnosticsEvery fact about the current session, as text you can put on screen
Destroy SessionLeave or end it

All of these survive changing level, because the subsystem outlives the world. Is In Session still answers correctly once you are on the match map.

You only need Publish Connect String by hand if you travel some way other than Start Match: your own ServerTravel, or a map change between rounds. Both give the listen server a new address, and joiners cannot find you at the old one.

How joining actually works

Worth knowing, because it is one value and not a negotiation.

The host resolves the URL joiners should travel to and publishes it as session data. It is the only machine that can: it knows its own address, its own Steam identity, and which net driver this build uses. Joiners travel to that string verbatim.

Direct IP192.168.1.33:7777
Steam relaysteam.76561198012345678:7777

Read it on any machine with Get Session Connect String. Empty means the host has not started.

INFO: The port is part of it in both cases. Under a Steam net driver it is the P2P virtual port, and a client that connects without one asks for port 0 while the host listens on 7777. Nothing connects, and neither side reports an error.
WARNING: Do not have clients work the URL out for themselves from their own settings. Every machine then has to reach the same conclusion independently, and two that disagree fail silently. One machine deciding and the rest obeying removes the whole class of problem.
INFO: Start Match already closes the session for you, so you only need Set Session Joinable by hand to close a lobby that is still gathering, or to reopen one mid match.

On OnlineSubsystem

Sessions publish as ordinary Steam lobby metadata, so anything that reads Steam lobbies can see a SteamForge session, including code using OnlineSubsystemSteam.

They do not route through the engine's IOnlineSession interface. Doing that would make the plugin depend on the OnlineSubsystem plugin, and working without it is the property SteamForge is built around. Interop happens at the data level, which is where Steam actually defines it.