๐๏ธLobby
Understanding what a Steam lobby is and is not, getting started with Steam Lobby
Like what you're seeing?
Support us as a GitHub Sponsor and get instant access to all our assets, exclusive tools and assets, escalated support and issue tracking and our gratitude. These articles are made possible by our GitHub Sponsors ... become a sponsor today!
Introduction
While Steam Lobby is not a true multiplayer feature ... it is in reality nothing but a chat room with metadata ... even called "Chat" on Valve's backend. It is nonetheless most commonly used for player parties and session matchmaking for we have listed it under the Multiplayer guides section.
Steam Matchmaking is driven primarily through the Steam Lobby feature. In a nutshell, the concept is that players will create a "lobby". You can think of this a bit like a chat room. This lobby has "metadata" associated with it which can be used to search for lobbies, filtering the results to just those the player cares about.โ
The metadata concept of Steam Lobby is where most of the functionality comes into play. The owner or "host" of a lobby can set the metadata on a lobby and anyone else can read that data, and the Steam Lobby search system can use that data to refine search results. In addition, each member within a lobby has a set of metadata associated with them. Lobby member metadata can only be set by the member it is related to and can only be read by other members of that lobby.โ
In summary lobby metadata is for stating the intent of the session or the status of the session and is accessible by everyone. Member metadata is for stating the intent of a member or the status of a member and is writable only by that member and readable only by fellow members of the same lobby.โ
You can read more about Steam's Matchmaking system in Valve's developer documentation.
Key Concepts
Lobby?
The first and most important thing to understand is that a lobby is not a network feature or concept. That is being in a lobby does not require a network connection, a network connection does not require a lobby. Lobby and Networking are two completely independent concepts.
Please do not confuse a lobby with anything to do with a network or network connection.
Types
The following explains; as clearly as Steam documentation allows, the available lobby types and when and how you might use them.
Private
Classified as a "Normal" lobby by Steam.
The only way to join a private lobby is to be invited to it via the Lobby.InvitePlayer feature. This can be useful in coop games when your player wants to play with a specific friend but doesn't want to be bothered by requests to join or public searches.
This lobby will not appear in searches, it will not appear on the user's friends list or rich presence data.
Friends Only
Classified as a "Normal" lobby by Steam.
This lobby can only be joined by friends of the owner or by people directly invited to it. This lobby does appear on the user's friends list but does not appear in lobby lists or searches. This is useful when the player wants friends to be able to drop in / out but doesn't want to be bothered by random players.
Public
Classified as a "Normal" lobby by Steam.
This is the typical lobby you will see used in most games. It's the classic "Matchmaking" lobby that appears on the user's friends list and can be searched for and joined by any matching player.
Invisible
This is the lobby type that Valve/Steam allows a user to be a member of 2 of this type.
This lobby is not visible in the friends list but can be searched for. That might be confusing at first read.
A random user can search for this lobby as you would a public lobby but this lobby will not show up on the Steam Friends list hence "invisible"
Members
Every user that has joined the lobby is identified as a LobbyMember. Each member in a lobby has its own set of metadata which all other members can read but only the member itself can set. To clarify that means you can only set your lobby member metadata but you can read everyone else's data. You cannot however read lobby member metadata if you are not a member of the lobby.
Metadata
Metadata refers to data stored in the lobby or on a lobby member. Put simply it's a collection of key-value pairs where the key and value are a simple string. So you can think of it much like a
The metadata stored on the lobby can be seen by anyone able to see the lobby and can be used to filter results when searching for a lobby using Steam's matchmaking system.
In contrast, metadata stored on a lobby member can only be seen by members of the lobby and is used only to share for example user configuration.
When metadata is changed the Steam API will raise the lobby data changed event ... that event will indicate what object's data changed not what data field changed so for example if the event indicates the lobby data changed you should check all the lobby metadata whereas if it indicated a members data changed you should check that members metadata.
The event in question is exposed on the Lobby Manager as evtDataUpdated and in the Matchmaking API as EventLobbyDataUpdate.
As far as setting metadata you can use the indexers to set metadata for example if you have a Lobby
in memory such as from the lobby manager.
Then you can set a metadata field on it such as
Similarly if you have a LobbyMember
in memory you can do the same thus
To learn more check out the Lobby and LobbyMember articles describing the features of the lobby and lobbyMember structures.
Chat
While the developer-facing part of the Steam API calls it a "Lobby" the backend developer-facing calls it a chat, this is because in reality a "Lobby" is just a chat room. This chat room has its own metadata as noted above and each member within it has its own metadata and you can send and receive messages containing byte[] data between all members without a network connection. Our Lobby Chat Director can help you get started.
Invite to Lobby
You can invite friends to join a lobby you are a member of This works rather or not the friend is currently in the game. The general workflow for this process is
When User B clicks "Accept" That DOES NOT join User B to the lobby That simply notifies the game that User B has indicated they would like to join that lobby. It is up to you as a game developer to handle that event appropreatly for your game. Understand that the player could already be in a lobby, they could already be in a match, they could be in the process of exiting. The user that invited them might have invited a ton of other users and now the lobby is full, the user might have clicked Accept hours after the invite was sent ... there are SO MANY reasons why you do not just blindly join the lobby when you get that event.
Workflow
The user is currently In-Game
User A joins or creates a lobby
User A Invites User B to join the lobby
User B clicks the Accept button in the Steam Friends Chat panel (overlay)
Your game client invokes the GameLobbyJoinRequest event
Your game client handles the event validating the lobby and navigating to the appropriate location in the game
Your game client joins the indicated lobby
The user is not In-game but does own it
User A joins or creates a lobby
User A Invites User B to join the lobby
User B's clicks the Accept button in the Steam Friends Chat panel (overlay)
Steam launches the game passing the Lobby ID in on the command line
Your bootstrap scene loads first and is the place to detect command line arguments such as lobby ID.
Your game client handles the event validating the lobby and navigating to the appropriate location in the game
Your game client joins the indicated lobby
When the user has accepted a lobby invite the ID of the lobby will be made available to them but the lobby's data will not be updated in the local cash.
You should Request Lobby Data for the invited lobby before attempting to read any of its metadata. You can join the lobby without reading the data however if you are properly validating the lobby you will need to read its data before joining.
Unity Examples
Getting Started
Bobsi has a quick setup tutorial that goes through a basic simple setup using Heathen's Toolkit for Steamworks. The Working with Lobbies entry below goes into more details and other options you have available.
Working with Lobbies
You can work with Lobby in one of 3 main ways; (from lowest level to highest)
All of the functionality of lobby is defined in the Matchmaking API. No matter how you choose to work with Steam lobbies, it's this API that will be doing the real work. Using the Matchmaking API requires that you have a level of understanding of the underlying Steam API but it does still simplify working with the API by making it Unity-centric, handling boilerplate concepts such as the callbacks and simplifying common concepts in a Unity manager e.g. UnityEvents and Actions, simpler calls, etc..
LobbyData as in the object in Steamworks Complete is a struct which wraps around ulong and CSteamID. Fundamentally it acts as a lobby ID and is implicitly convertible between ulong and CSteamID meaning you can pass it along as if it were a ulong value or a CSteamID and you can assign it from a ulong value or a CSteamID. Beyond being a fancy wrapper around ulong it also has accessors and methods that make working with a specific lobby very easy. Using the lobby object you very likely won't need to touch the raw API at all.
As the name suggests this is a tool for managing a lobby. The lobby manager is the easiest way to manage a lobby and is a Unity component ... that is you can add it to a GameObject and configure it in Unity editor. The Lobby Manager does more than simply expose Matchmaking events to the Unity editor it handles common concepts for you and makes it easier to work with a lobby through designer-friendly tools such as Bolt and other visual scripting assets.
Player Join / Leave
Your first question when managing a lobby is how to know when the user joins or leaves a lobby and what lobby it was that they joined or left. From low level to high here are the notes!
Matchmaking API
EventLobbyEnterSuccess and EventLobbyEventFailed are raised when the local user tries and succeeds or fails respectively to enter a lobby. Both events return the LobbyEnter structure provided by Steam API.
Success
Failure
Lobby
The lobby object Join method takes a callback so for example
So we do a bit more work here so we can understand if it was a success or not, and if not why not. The EChatRoomEnterResponce tells us why.
In our example above we used expression to create an anon method. This is a style choice you can learn more about expression and anon methods in our other articles.
Lobby Manager
Lobby manager makes this super easy. Using Lobby Manager you don't need to use any code at all if you don't want. You will see right in the inspector an evtEnterSuccess and an evtEnterFailed event. These work just like the ones on Matchmaking API but of course are accessible from the Unity Editor and only raise for lobbies that were joined through this Lobby Manager.
The fact that Lobby Manager filters its events to only the events that were run through it makes it much easier when driving UI elements. Most games will have 2 lobbies, 1 for the session aka "matchmaking" and 1 for a player friend group or party. The Matchmaking API events raise for any event on any lobby that the local user is a member of so if a user is in a session lobby and a party lobby the events will raise for both leaving it up to you to sort out which lobby the event goes to.
Lobby Manager only handles events for the lobby that it is "managing" so it is filtering the events down for you. Thus when the "evtEnterSuccess" triggers on your MatchmakingObject's LobbyManagaer component you know it's related to the matchmaking lobby.
Yes, you can of course use the Lobby Manager from code as much or as little as you would like. Doing so is no different than using any other Unity component from code.
Others Join / Leave
This is how do you know when some other player joins or leaves the lobby that your in. In other words, how do you know when new "peers" come in or go out of the lobby?
Matchmaking API
This is actually handled via the EventLobbyChatUpdate event which is raised any time a chat event occurs ... including when members join or leave.
The handler for this event would look something like this, note the work is done in the EChatMemberStateChange data
Lobby object
There is no way to do this from the lobby object as the lobby object is a struct and doesn't define events.
Lobby Manager
As always the Lobby Manager makes it easier not just by filtering on the lobby for you but also by splitting the event into two. evtUserJoined and evtUserLeft invoke when someone joins or leaves respectively. These events are UserData events meaning they hand you the UserData of the member that joined or left.
Invited to Lobby
Gets data about a lobby, if you have been invited to a lobby you will probably want to get data about it before attempting to join it. This can be useful when preparing the lobby UI or to confirm that the lobby is a valid lobby for the local player.
Game Lobby Join Requested Event
This is the event that Valve's Steam will invoke when the user is currently in your game and accepts an invite to a lobby for your game. The event can be found on the Overlay.Client and on the Overlay Manager.
Command Arguments
In the event the user accepts an invite to a lobby in your game and is not currently playing your game then Steam will launch your game with the lobby ID on the command line. We have provided you with tools to make detecting this easy.
Steamworks Behaviour
Our Steamworks Behaviour script checks for this case on initialization and raises an event if found.
CommandLine
CommandLine is a tool available in the HeathenEngineering namespace. It can read common command line arguments for you including a Steam Lobby ID.
Metadata
You often need to know when data on the lobby or a given member has changed.
Matchmaking API
The EventLobbyDataUpdate event is raised when any sort of data is updated for the lobby or a member.
Lobby object
This cannot be done from the Lobby object alone as it is an event and the struct doesn't have any of the events.
Lobby Manager
Lobby Manager is much like the Matchmaking API for this one and uses the evtDataUpdated method to know when any kind of data has changed.
Metadata Read/Write
Writing lobby metadata data can only be done by the owner of the lobby. Metadata on the lobby is what is used when searching for a lobby and is what you would use to express configuration and settings of the session the lobby deals with. For example if you wanted to let all users know what map the session will be on then you would set a lobby metadata data field map = X.
Matchmaking API
Use the SetLobbyData method to apply lobby data. This can only be done if the user is the owner of the lobby.
Lobby Data
Using the lobby object its a step easier and you have a few options
Simple indexer
and we have exposed several common fields as fields on the struct
Lobby Manager
The lobby manager lets you use both approaches
Get the Lobby
We are often asked how do you "get" the lobby your in as in once you joined or created a lobby how to do you get to its LobbyData so you can use it for whatever it is you need to use it for.
The answer differs depending on context so here are some common cases.
Lobby Manager
or for that matter, Quick Match Lobby Control or Party Lobby Control or any similar lobby management tool.
In all cases these tools have a field on them named Lobby that returns the lobby they are managing ... similarly you can set the lobby you want them to manage by writing a value to this field.
Session and Group
If you use our tools we will mark lobby's by their type ... that is we will mark the lobby as the "group" lobby when you use the Party Lobby Control and we will mark it as the "session" lobby when you use the Quick Match Lobby Control. Note you can configure the Lobby Manager to set this for you if using it. And you can set this yourself if your creating lobby manually.
To set this your self after the creation of your lobby call
or
Note there should only be 1 group and 1 session lobby at a time, you can then get these special use case lobbies from anywhere in code
or
Look for it
Our system tracks every lobby the local user is a member of, a user cannot be a member of more than 3 lobbies and so it's trivial to just iterate over the lobbies they are a member of to choose the one you want.
or if you prefer Linq (we do)
Create a Lobby
For more information on lobby types see Valve's documentation https://partner.steamgames.com/doc/api/ISteamMatchmaking#typedefs
See the API.Matchmaking interface for details on creating a lobby. In addition the Lobby Manager, tools can help you create, join and manage a lobby for a specific function in your game.
Let's say for example you use 2 types of lobbies in your game
Party
This would be where you have your player gather a group of friends together to play together i.e. a group or party as seen in MMOs, MOBA or any game with a coop feature
Session Lobby
This would be where you have your players configure a gameplay session and wait for competitors to join or similar. This is the most typical use of a lobby and what drives matchmaking in your game.
In the above use case, you would attach a Lobby Manager to your Party UI and another to your Session UI. You would configure each accordingly and each can manage its own chat and metadata features. This helps you split functionality across concepts unique to your game.
Find and Join Lobbies
The easiest way to search for and join lobbies is through the Lobby Manager tool. Alternatively, you can use Heathen's API.Matchmaking directly to easily search for and join lobbies.
Aside from browsing for a lobby you can handle invites and joining of lobby invites. Inviting friends to Lobby can be done in several ways including from outside of your game via the Steam Friends list.
Internally to you're game you can use the User Data object to invite a specific player. You would have access to this object from various tools and interfaces including Friends, Clans and their related chat systems. When you send an invite it is up to that user to accept it and there are multiple use cases for how they might accept the invite
While In-game
In this case, the accepting user is already in-game so the Game Lobby Join Invite event will be raised on the Overlay Manger and its related API.Overlay interface.
While out of the game
In this case, the accepting user is not yet in the game so the Steam client will launch the game and pass as an argument on the command line the lobby connection information. It is up to you to handle this argument, navigate to the appropriate place in your game e.g. the lobby UI and then join the lobby ID indicated on that argument.
A crude example follows
Using Lobby Chat
Steam's Lobby system includes a simple chat system able to handle text or data. The easiest way to interact with lobby chat is via the Lobby Chat Director which needs to be added to the same object as your Lobby Manager.
You can also interact with lobby chat manually through the API.Matchmaking interface.
Notify "Connect to network"
This will set the Game Server information on the lobby and can be done in a number of ways. You are required to have either a Steam ID (which a UserData is) or an IP and Port or both, when you call the SetGameServer method with no input parameters it will assume the owner of the lobby is the Listen Server.
The typical purpose of a lobby is to gather players and settle on the rules and conditions of the multiplayer session. In most cases, you will at some point want to notify players that they should connect to a particular server be that a Peer in a P2P game or a dedicated server on the net.
The lobby system provides tools for this via the SetGameServer
method on the lobby
The SetGameServer method can only be called by the "Owner" of the lobby
When called Valve will record the information on the Steam Lobby metadata as shown below
Each member of the lobby (other than the owner) will be notified by a callback which raises the EventLobbyGameCreated
event located on the API.Matchmaking interface and exposed through the Lobby Manager.
All members of a lobby should upon joining the lobby register an event handler on the Lobby.evtGameServerSet
event
Go from Lobby to Network Session
Hopefully, you have read the above so you understand the fundamentals of a lobby and what features it has including how to notify the other members when it's time to connect to the network.
So your question then is how do you know when to transition from being in the lobby to starting the network session, and we can't answer that for you. This is entirely up to your game design but here are a couple of common use cases.
Lobby Full
In this case, you are simply assuming it is time to play when the lobby gets full e.g.
Players Ready
In this case, you were assuming it is time to play when the lobby is full and all players have indicated they are ready. Note this requires you to provide the players with a means to set
This sets the metadata on that user indicating it is ready to play, we use that in the following test
Then What?
Once you know when you want to start the network session it's time to ... start the network session ... exactly what you need to do to do that depends on the networking tool you chose to use but here is the usual workflow with the code snippets relevant to Steam lobby.
First, you probably want to set the lobby joinable as false. This will prevent newcomers from joining while you transition players over to the network session. Of course, if your game supports "drop-in/drop-out" you don't want to do this ... use your judgment with regards to your design.
You would then have the owner do whatever it is your networking tool needs you to do to start up the network session. Don't know what that is? consult your networking tool of choice ... it is usually something like loading up the appropriate scene and using the network manager to call StartHost() or similar.
Once the network session is ready you have the owner notify the other members that it's time to connect to the network session.
Notice in this case we do not provide any parameters to the SetGameServer call ... this is assuming your session will be P2P and that the owner is the host ... for more information please consult the article on LobbyData.
This will cause the GameServerSet event to be triggered as noted in the Notify "Connect to network" entry.
When users see that event they will use the GameServer information in the lobby to know who to connect to. You have options here and which you would use depends again on your game and your design. The following code simply highlights what's available in the LobbyGameServer information you read on the GameServer field of the lobby.