Keep parties together
Invite friends, accept join codes, and move a party into a game.
Use a lobby as the party. Keep it while players choose a mode or wait for a match; your game owns ready states and party rules.
A Discord friend receives a Discord activity invite carrying the primary lobby’s secret, whether Discord is a social provider or a lobby mirror; accepting it in Discord raises On Lobby Join Requested with the primary lobby and UCIK joins it and its mirrors. Discord shows the invite itself, so On Lobby Invite Received does not fire for Discord. The join only works after the player has signed in; an invite accepted on the login screen is rejected until the game logs in and the player presses Join again.
Invite a player
Loading the interactive viewer.
Game module dependencies: UCIKCore, BetideCore.
#include "Engine/GameInstance.h"
#include "Lobbies/UCIKLobbySubsystem.h"
#include "UCIKCore.h"
void InviteToParty(UGameInstance &GameInstance, const FUCIK_PlayerHandle &Player)
{
auto *Service = GameInstance.GetSubsystem<UUCIKLobbySubsystem>();
if (!Service)
return;
Service->SendInvite(
TEXT("GameLobby"), Player, EUCIK_InvitePriority::Auto,
FBetideCallback<TMap<FBetideProviderId, bool>>::CreateWeakLambda(
&GameInstance, [](const TBetideResult<TMap<FBetideProviderId, bool>> &Result) {
if (!Result.bOk)
{
UE_LOG(LogUCIK, Warning, TEXT("%s"), *Result.Error.GetLogString());
return;
}
for (const TPair<FBetideProviderId, bool> &Receipt : Result.GetValue())
UE_LOG(LogUCIK, Log, TEXT("%s: %d"), *Receipt.Key.ToString(), Receipt.Value);
}));
}Use the player’s full handle from friends or profiles. Auto chooses a compatible invite route; a successful provider map may contain only some requested providers.
Accept an invite
Read pending party invites
Loading the interactive viewer.
Accept an invite
Loading the interactive viewer.
Game module dependencies: UCIKCore, BetideCore.
#include "Engine/GameInstance.h"
#include "Lobbies/UCIKLobbySubsystem.h"
#include "UCIKCore.h"
void ReadPartyInvites(UGameInstance &GameInstance)
{
if (auto *Service = GameInstance.GetSubsystem<UUCIKLobbySubsystem>())
{
for (const FUCIK_LobbyInvite &Invite : Service->GetPendingInvites())
UE_LOG(LogUCIK, Log, TEXT("%s"), *Invite.From.ToString());
}
}
void AcceptPartyInvite(UGameInstance &GameInstance, const FUCIK_LobbyHandle &InvitedLobby)
{
auto *Service = GameInstance.GetSubsystem<UUCIKLobbySubsystem>();
if (!Service)
return;
Service->AcceptInvite(
TEXT("GameLobby"), InvitedLobby, false,
FBetideCallback<FUCIK_Lobby>::CreateWeakLambda(
&GameInstance, [](const TBetideResult<FUCIK_Lobby> &Result) {
if (!Result.bOk)
{
UE_LOG(LogUCIK, Warning, TEXT("%s"), *Result.Error.GetLogString());
return;
}
UE_LOG(LogUCIK, Log, TEXT("Joined party: %s"), *Result.GetValue().Name.ToString());
}));
}Bind On Lobby Invite Received before showing the menu. Read pending invites when reopening it. Accepting joins the lobby and removes the pending invite; rejecting removes it and informs the service where supported.
Join with a code
Loading the interactive viewer.
Game module dependencies: UCIKCore, BetideCore.
#include "Engine/GameInstance.h"
#include "Lobbies/UCIKLobbySubsystem.h"
#include "UCIKCore.h"
void JoinPartyCode(UGameInstance &GameInstance, const FString &Code)
{
auto *Service = GameInstance.GetSubsystem<UUCIKLobbySubsystem>();
if (!Service)
return;
Service->JoinLobbyByCode(
TEXT("GameLobby"), Code, false,
FBetideCallback<FUCIK_Lobby>::CreateWeakLambda(
&GameInstance, [](const TBetideResult<FUCIK_Lobby> &Result) {
if (!Result.bOk)
{
UE_LOG(LogUCIK, Warning, TEXT("%s"), *Result.Error.GetLogString());
return;
}
UE_LOG(LogUCIK, Log, TEXT("Joined party: %s"), *Result.GetValue().Name.ToString());
}));
}Set Lobby Code when creating the lobby: 4–60 letters, digits, -, or _. Steam code discovery requires a public lobby. Treat codes as a way to find a party, not a secret access-control system.
Overlay and invite cleanup
Open the invite picker
Loading the interactive viewer.
Reject a party invite
Loading the interactive viewer.
Send a session invite
Loading the interactive viewer.
Accept a session invite
Loading the interactive viewer.
Game module dependencies: UCIKCore, BetideCore.
Open the invite picker
#include "Engine/GameInstance.h"
#include "Lobbies/UCIKLobbySubsystem.h"
#include "UCIKCore.h"
void ShowPartyInviteUI(UGameInstance &GameInstance)
{
auto *Service = GameInstance.GetSubsystem<UUCIKLobbySubsystem>();
if (!Service)
return;
Service->ShowInviteUI(
TEXT("GameLobby"),
FBetideCallback<bool>::CreateWeakLambda(&GameInstance, [](const TBetideResult<bool> &Result) {
if (!Result.bOk)
{
UE_LOG(LogUCIK, Warning, TEXT("%s"), *Result.Error.GetLogString());
return;
}
UE_LOG(LogUCIK, Log, TEXT("Operation completed: %d"), Result.GetValue());
}));
}Reject a party invite
#include "Engine/GameInstance.h"
#include "Lobbies/UCIKLobbySubsystem.h"
#include "UCIKCore.h"
void RejectPartyInvite(UGameInstance &GameInstance, const FUCIK_LobbyHandle &InvitedLobby)
{
auto *Service = GameInstance.GetSubsystem<UUCIKLobbySubsystem>();
if (!Service)
return;
Service->RejectInvite(
InvitedLobby,
FBetideCallback<bool>::CreateWeakLambda(&GameInstance, [](const TBetideResult<bool> &Result) {
if (!Result.bOk)
{
UE_LOG(LogUCIK, Warning, TEXT("%s"), *Result.Error.GetLogString());
return;
}
UE_LOG(LogUCIK, Log, TEXT("Operation completed: %d"), Result.GetValue());
}));
}Send a session invite
#include "Engine/GameInstance.h"
#include "Sessions/UCIKSessionSubsystem.h"
#include "UCIKCore.h"
void SendSessionInvite(UGameInstance &GameInstance, const FUCIK_PlayerHandle &Player)
{
auto *Service = GameInstance.GetSubsystem<UUCIKSessionSubsystem>();
if (!Service)
return;
Service->SendInvite(
TEXT("GameSession"), Player,
FBetideCallback<bool>::CreateWeakLambda(&GameInstance, [](const TBetideResult<bool> &Result) {
if (!Result.bOk)
{
UE_LOG(LogUCIK, Warning, TEXT("%s"), *Result.Error.GetLogString());
return;
}
UE_LOG(LogUCIK, Log, TEXT("Operation completed: %d"), Result.GetValue());
}));
}Accept a session invite
#include "Engine/GameInstance.h"
#include "Sessions/UCIKSessionSubsystem.h"
#include "UCIKCore.h"
void AcceptSessionInvite(UGameInstance &GameInstance, const FUCIK_SessionHandle &InvitedSession)
{
auto *Service = GameInstance.GetSubsystem<UUCIKSessionSubsystem>();
if (!Service)
return;
Service->AcceptInvite(TEXT("GameSession"), InvitedSession, true,
FBetideCallback<FUCIK_Session>::CreateWeakLambda(
&GameInstance, [](const TBetideResult<FUCIK_Session> &Result) {
if (!Result.bOk)
{
UE_LOG(LogUCIK, Warning, TEXT("%s"),
*Result.Error.GetLogString());
return;
}
UE_LOG(LogUCIK, Log, TEXT("Operation completed: %d"), true);
}));
}Session invites require a player on the session’s primary provider. Read the handle from On Session Invite Received or Get Pending Crossplay Session Invites; Reject Crossplay Session Invite declines it (EOS tells the sender, other providers only clear it locally). The accept example enables automatic travel; keep it in a GameInstance Blueprint so it survives the map change.
For parties that follow a host into a match, use lobby hosting and readiness. Do not trigger a second travel if Party Follows Host already handles it.