Lobby
Discord’s Social SDK uses the term Lobby, but it doesn’t match the traditional idea of a multiplayer game lobby. Instead, think of a Lobby more like a temporary chat group or DM group that exists to facilitate chat and voice between a small set of users.
What is it?
More a Chat Group than a Game Lobby: Unlike conventional game lobbies, Discord lobbies don’t have built-in matchmaking, server connection info, or discovery. They’re primarily ephemeral chat spaces for voice, text, and presence.
Can Be Linked to a Server Channel: A lobby can be linked to a Discord server’s text or voice channel. This lets you bridge chat between your game and Discord, enabling cross-platform conversations.
Static Metadata Only at Creation: You can assign metadata key-value pairs to a lobby, but only when you create it. This metadata is static and cannot be updated afterwards through the Social SDK. No Matchmaking or Discovery: There’s no way to search, filter, or find lobbies. Joining is either by invitation or by requesting to join a friend’s lobby.
Lobby Members and Metadata
Members Can Have Dynamic Metadata: Each member in a lobby can store their metadata, which can be updated at runtime. This lets you track per-user info like status or preferences while they’re in the lobby.
Member Metadata Is Not Searchable: This data is purely key-value and doesn’t support matchmaking or discovery features.
Use Case
Discord Chat Integration
The core utility of Discord lobbies in the Social SDK is to expose Discord chat within your game, whether:
Creating temporary chat groups akin to Discord DMs, or
Linking to existing Discord server channels to enable seamless cross-platform chat.
Because lobbies lack matchmaking or server connection features, they function best as social spaces rather than game session hosts.
Examples
Create or Join
To create or join a Discord lobby, you need to know its secret.
What is a secret? It’s simply a string that identifies the lobby. Think of it as the lobby’s “name,” but it must be globally unique—typically a GUID or similarly complex identifier.
While you can use a human-friendly secret, be cautious: simpler or predictable strings increase the risk of abuse or unwanted joins. In practice, unique and complex secrets are far safer.
To make joining easier without sharing secrets manually, you can leverage Discord’s Invite and Request to Join features. These allow players to join each other’s lobbies seamlessly without needing to type or share the secret directly.
Code Free
Coming Soon
C#
For all asynchronous calls, we have exposed 3 approaches for you to work with. You can choose whichever suits you best; they all ultimately do the same thing.
If you wonder which is "best", the original "callback" approach is the most performant and flexible option.
DiscordSocialApp.CreateOrJoinLobby(secret, callback);
secret
A unique string that will be used to join this lobby by other users. It's generally best practice to make this a globally unique value.
callback
A delegate to be invoked when the process is complete. This can be a function name or a lambda expression.
Example:
Let's assume you have a function such as
void HanleLobbyCreated(ClientResult result, ulong lobbyId)
{
// Do something with your lobby
}
Then you could
string secret = Guid.NewGuid().ToString();
DiscordSocialApp.CreateOrJoinLobby(secret, HandleLobbyCreated);
Alternatively, we can do the same thing with an anonymous function.
string secret = Guid.NewGuid().ToString();
DiscordSocialApp.CreateOrJoinLobby(secret, (result, lobbyId) =>
{
// Do something with your lobby
});
Task Option
You can do the same using traditional threading tasks if you prefer that paradigm.
System.Task will cause a small amount of GC allocation. This is not generally a concern with infrequent things, such as creating a lobby, but it is worth knowing.
Using tasks in this manner also causes blocking.
string secret = Guid.NewGuid().ToString();
var (result, lobby) = await DiscordLobbyData.CreateOrJoinTask(secret);
UniTask Option
You can do the same using UniTask if you prefer that paradigm.
Cysharp.Threading.Tasks create fewer GC allocations, but will still cause GC allocations in some cases, depending on the data types being worked with.
Using tasks in this manner also causes blocking.
string secret = Guid.NewGuid().ToString();
var (result, lobby) = await DiscordLobbyData.CreateOrJoinUniTask(secret);
Invite User
To invite a user, you must have an Active Lobby; Discord will use that lobby as the target of the invite.
Code Free
Coming Soon
C#
Give the user you wish to invite to your Active Lobby.
DiscordUserData user;
You can invite them via
user.Invite(content, callback);
content
This is not currently used according to the SDK, but it is included, so we have added it. Just pass an empty string for now.
callback
This is a delegate that will be invoked when the process completes.
Example:
void HandleInviteSent(ClientResult result)
{
// The invite was sent, check the result for status
}
You can then do
user.Invite(string.Empty, HandleInviteSent);
or using lambda
user.Invite(string.Empty, result =>
{
// The invite was sent, check the result for status
});
Task
var result = await user.InviteTask(string.Empty);
UniTask
var result = await user.InviteUniTask(string.Empty);
Get and Set Active Lobby
Invite and Request features of lobby work with the "active" lobby being the one set on the user's Rich Presence for this application. A user may be a member of many lobbies, but only 1 will be "active".
Code Free
Coming Soon
C#
You can monitor the current active lobby via
bool hasActiveLobby = DiscordLobbyData.Active.HasValue;
DiscordLobbyData activeLobby = DiscordLobbyData.Active.Value;
You can set a lobby as active in a similar manner ...
ulong lobbyId; // If you only have the ID, you can get the data
DiscordLobbyData myLobby = lobbyId; // it implictly converts
myLobby.MakeActive(maxSize, message, platforms, callback);
maxSize
Lists the maximum number of users expected in the lobby
message
optional status message for the resulting Activity
platforms
An enum that lists the supported platforms for this activity
callback
A delegate to be invoked when the process is complete
Example:
void HandleMadeActive(ClientResult result)
{
//It's all done, use the result to check the status
}
You can then call
int maxSize = 42;
string message = "Hello World";
ActivityGamePlatforms platforms =
ActivityGamePlatforms.Desktop | ActivityGamePlatforms.Xbox | ActivityGamePlatforms.PS5;
myLobby.MakeActive(maxSize, message, platforms, HandleMadeActrive);
Or using lambda
myLobby.MakeActive(maxSize, message, platforms, result =>
{
//It's all done, use the result to check the status
});
Task
System.Task will cause a small amount of GC allocation. This is not generally a concern with infrequent things, such as creating a lobby, but it is worth knowing.
Using tasks in this manner also causes blocking.
var result = await myLobby.MakeActiveTask(maxSize, message, platforms);
UniTask
Cysharp.Threading.Tasks create fewer GC allocations, but will still cause GC allocations in some cases, depending on the data types being worked with.
Using tasks in this manner also causes blocking.
var result = await myLobby.MakeActiveUniTask(maxSize, message, platforms);
Request to Join
You can request to join a user assuming they have a valid Active Lobby.
Code Free
Coming Soon
C#
Assuming a user you wish to join
DiscordUserData user;
You can then
user.RequestToJoin(callback);
callback
This is a delegate to be invoked when the process is complete.
Example:
assuming
void HandleRequestToJoinSent(ClientResult result)
{
// The request was sent.
}
Then
user.RequestToJoin(HandleRequestToJoinSent);
or using lambda
user.RequestToJoin(result =>
{
// The request was sent.
});
Task
System.Task will cause a small amount of GC allocation. This is not generally a concern with infrequent things, such as creating a lobby, but it is worth knowing.
Using tasks in this manner also causes blocking.
var result = await user.RequestToJoinTask();
UniTask
Cysharp.Threading.Tasks create fewer GC allocations, but will still cause GC allocations in some cases, depending on the data types being worked with.
Using tasks in this manner also causes blocking.
var result = await user.RequestToJoinUniTask();
Last updated