Full guide to using Epic Online Services presence and social features with the Supabase UE5 Plugin. Covers the USupabaseEOSPresence API for querying player status, managing friend lists, setting rich presence, and receiving real-time presence change notifications.
EOS Presence & Social lets you track player online status, display rich presence information (e.g., current activity, map, or match state), and query friend lists. The plugin provides two approaches:
| Approach | Class | Complexity | Best For |
|---|---|---|---|
| Async Blueprint Nodes | UAsyncEOSPresenceSubscribe, UAsyncEOSQueryFriends |
Low | Blueprint-driven workflows. One-call subscription and friend queries. |
| Low-Level API | USupabaseEOSPresence |
Medium | C++ game modes or systems that need fine-grained control over subscriptions, caching, and delegate handling. |
All presence data is cached locally after the first query or subscription update, so you can call GetCachedPresence() or GetFriendsList() synchronously without waiting for a network round trip.
+----------------+ +----------------+ +-------------------+
| Initialize() | ----> | SubscribeTo | ----> | OnPresenceChanged |
| | | Presence() | | fires for each |
+----------------+ | (User IDs) | | subscribed user |
+----------------+ +-------------------+
|
v
+----------------+ +----------------+ +-------------------+
| GetCached | <---- | Internal cache | <---- | Presence update |
| Presence() | | updated | | received from EOS |
+----------------+ +----------------+ +-------------------+
--- Friends list flow: ---
+----------------+ +----------------+ +-------------------+
| QueryFriends | ----> | EOS Friends | ----> | OnFriendsList |
| List() | | API call | | Updated fires |
+----------------+ +----------------+ +-------------------+
|
v
+----------------+ +----------------+
| GetFriendsList | <---- | Friends cache |
| () | | populated |
+----------------+ +----------------+
--- Set own presence: ---
+----------------+ +----------------+ +-------------------+
| SetPresence() | ----> | EOS Presence | ----> | Other subscribed |
| (RichText, | | API call | | players receive |
| StateData) | | | | OnPresenceChanged |
+----------------+ +----------------+ +-------------------+
| Step | Action | Description |
|---|---|---|
| 1 | Initialize() |
Initializes the EOS presence subsystem. Must be called after EOS Platform init. |
| 2 | SubscribeToPresence() |
Subscribe to presence updates for an array of Product User IDs. Fires OnPresenceChanged when any subscribed user's status changes. |
| 3 | OnPresenceChanged |
Delegate fires with FEOSPresenceData containing the updated status, rich text, state data, and timestamp. |
| 4 | GetCachedPresence() |
Synchronously look up cached presence for any user whose update you have received. |
| 5 | QueryFriendsList() |
Query the authenticated user's EOS friends list. Fires OnFriendsListUpdated. |
| 6 | GetFriendsList() |
Returns the cached friends list as TArray<FEOSFriendEntry>. |
| 7 | SetPresence() |
Set the local user's rich presence text and optional state data JSON. Other players subscribed to your presence will be notified. |
| 8 | UnsubscribeFromPresence() |
Unsubscribe from all presence notifications. |
| 9 | Shutdown() |
Release all EOS presence interfaces and subscriptions. |
For most Blueprint workflows, use the async latent nodes provided by the plugin.
SelfSelfTArray<FEOSFriendEntry>DisplayName, Status, RichPresenceText, and bIsOnline from each entry to populate your friends UI #include "Async/AsyncEOSPresenceSubscribe.h"
#include "Async/AsyncEOSQueryFriends.h"
// Subscribe to a player's presence
TArray<FString> TargetUserIds;
TargetUserIds.Add(TEXT("00000000000000000000000000000000"));
UAsyncEOSPresenceSubscribe::SubscribeToPresence(this, TargetUserIds)
->OnSuccess.AddUObject(this, &AMyPlayerController::OnPresenceSubscribed);
// Query friends list
UAsyncEOSQueryFriends::QueryFriends(this)
->OnSuccess.AddUObject(this, &AMyPlayerController::OnFriendsQueried);
Use USupabaseEOSPresence when you need direct control over the presence lifecycle, want to manage subscriptions manually, or are building C++ systems that respond to presence changes in real time.
Call Initialize() once after EOS Platform init (e.g., after successful authentication). Call Shutdown() during cleanup.
#include "SupabaseEOSPresence.h"
USupabaseEOSPresence* PresenceSystem = NewObject<USupabaseEOSPresence>(this);
// Initialize the presence subsystem
if (!PresenceSystem->Initialize())
{
UE_LOG(LogTemp, Error, TEXT("Failed to initialize EOS presence"));
return;
}
UE_LOG(LogTemp, Log, TEXT("EOS presence initialized"));
Subscribe to one or more players to receive real-time presence updates:
// Bind the presence changed delegate
PresenceSystem->OnPresenceChanged.AddLambda(
[](const FEOSPresenceData& PresenceData)
{
UE_LOG(LogTemp, Log, TEXT("Presence update for %s: %s"),
*PresenceData.ProductUserId,
*UEnum::GetDisplayValueAsText(PresenceData.Status).ToString());
});
// Subscribe to an array of Product User IDs
TArray<FString> UserIds;
UserIds.Add(TEXT("00000000000000000000000000000000"));
UserIds.Add(TEXT("11111111111111111111111111111111"));
if (!PresenceSystem->SubscribeToPresence(UserIds))
{
UE_LOG(LogTemp, Error, TEXT("Failed to subscribe to presence"));
}
Broadcast your current activity to other players:
// Set rich presence text and optional state data
FString RichText = TEXT("Playing on Forest Map - Wave 12");
FString StateData = TEXT("{\"map\":\"forest\",\"wave\":12,\"score\":4500}");
if (!PresenceSystem->SetPresence(RichText, StateData))
{
UE_LOG(LogTemp, Error, TEXT("Failed to set presence"));
}
Retrieve and display the authenticated user's friend list:
// Bind the friends list updated delegate
PresenceSystem->OnFriendsListUpdated.AddLambda(
[](const TArray<FEOSFriendEntry>& Friends)
{
UE_LOG(LogTemp, Log, TEXT("Friends list updated: %d friends"), Friends.Num());
for (const FEOSFriendEntry& Friend : Friends)
{
UE_LOG(LogTemp, Log, TEXT(" %s (%s) - Online: %s"),
*Friend.DisplayName,
*Friend.ProductUserId,
Friend.bIsOnline ? TEXT("Yes") : TEXT("No"));
}
});
// Query the friends list
if (!PresenceSystem->QueryFriendsList())
{
UE_LOG(LogTemp, Error, TEXT("Failed to query friends list"));
}
Synchronously look up cached presence for any user you have received an update for:
FEOSPresenceData CachedPresence;
if (PresenceSystem->GetCachedPresence(TEXT("00000000000000000000000000000000"), CachedPresence))
{
UE_LOG(LogTemp, Log, TEXT("Cached status: %s"), *UEnum::GetDisplayValueAsText(CachedPresence.Status).ToString());
UE_LOG(LogTemp, Log, TEXT("Rich text: %s"), *CachedPresence.RichPresenceText);
UE_LOG(LogTemp, Log, TEXT("Last updated: %s"), *CachedPresence.LastUpdatedAt);
}
Note:
GetCachedPresence()returnsfalseif no presence data has been received for the given Product User ID yet. Ensure you have subscribed to that user or they have appeared in a friends list query.
The main class for interacting with EOS presence and social features.
| Function | Signature | Returns | Description |
|---|---|---|---|
Initialize |
bool Initialize() |
bool |
Initializes the EOS presence subsystem. Call after EOS Platform init. Returns true on success. |
Shutdown |
void Shutdown() |
void |
Shuts down presence subscriptions and releases interfaces. Call during cleanup. |
IsInitialized |
bool IsInitialized() |
bool |
Returns true if the presence system is initialized and ready. |
SubscribeToPresence |
bool SubscribeToPresence(const TArray<FString>& ProductUserIds) |
bool |
Subscribe to presence updates for an array of Product User IDs. Fires OnPresenceChanged when any subscribed user's status changes. Returns true if the subscription request was started. |
UnsubscribeFromPresence |
void UnsubscribeFromPresence() |
void |
Unsubscribe from all presence updates. No further OnPresenceChanged events will fire. |
SetPresence |
bool SetPresence(const FString& RichPresenceText, const FString& StateData) |
bool |
Set the local user's presence. RichPresenceText is the display string shown to other players. StateData is an optional JSON string for structured data. Returns true if the request was started. |
QueryFriendsList |
bool QueryFriendsList() |
bool |
Query the authenticated user's EOS friends list. Fires OnFriendsListUpdated with the results. Returns true if the query was started. |
GetFriendsList |
const TArray<FEOSFriendEntry>& GetFriendsList() |
const TArray<FEOSFriendEntry>& |
Returns the cached friends list. Empty until OnFriendsListUpdated has fired at least once. |
GetCachedPresence |
bool GetCachedPresence(const FString& ProductUserId, FEOSPresenceData& OutPresence) |
bool |
Look up cached presence data for a specific user. Returns true if cached data exists. |
| Delegate | Signature | Description |
|---|---|---|
OnPresenceChanged |
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(OnPresenceChanged, FEOSPresenceData, PresenceData) |
Fired when any subscribed user's presence changes. Contains the full FEOSPresenceData for the updated user. |
OnFriendsListUpdated |
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(OnFriendsListUpdated, const TArray<FEOSFriendEntry>&, Friends) |
Fired when the friends list query completes. Contains the full list of FEOSFriendEntry structs. |
OnEOSError |
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(OnEOSError, FString, Operation, FString, ErrorMessage) |
Fired when an EOS operation fails. Contains the operation name and human-readable error message. |
A struct containing presence information for a single user. Received via OnPresenceChanged or retrieved from GetCachedPresence().
| Property | Type | Description |
|---|---|---|
ProductUserId |
FString |
The EOS Product User ID this presence data belongs to. |
Status |
EEOSPresenceStatus |
The user's current online status (Online, Offline, Away, DoNotDisturb, ExtendedAway, Unknown). |
RichPresenceText |
FString |
The rich presence display string set by the user (e.g., "Playing on Forest Map - Wave 12"). |
ProductId |
FString |
The EOS Product ID associated with this presence data. |
StateData |
FString |
Optional JSON string containing structured state data set by the user. |
LastUpdatedAt |
FString |
Timestamp of when this presence was last updated. |
A struct representing a single friend in the authenticated user's friends list. Received via OnFriendsListUpdated.
| Property | Type | Description |
|---|---|---|
ProductUserId |
FString |
The EOS Product User ID of the friend. |
DisplayName |
FString |
The friend's display name from their EOS profile. |
Status |
EEOSPresenceStatus |
The friend's current online status. |
RichPresenceText |
FString |
The friend's current rich presence string. Empty if not set. |
bIsOnline |
bool |
Convenience flag: true if the friend is currently online. |
Enum representing a user's online presence status.
| Value | Description |
|---|---|
Offline |
User is offline or not reachable. |
Online |
User is online and active. |
Away |
User is away or idle. |
DoNotDisturb |
User has set their status to Do Not Disturb. |
ExtendedAway |
User has been idle for an extended period. |
Unknown |
Status could not be determined. |
This example demonstrates creating USupabaseEOSPresence, initializing it, and subscribing to a list of player IDs:
#include "SupabaseEOSPresence.h"
void AMyPlayerController::BeginPlay()
{
Super::BeginPlay();
#if WITH_EOS_SDK && SUPABASE_EOS_INTEGRATION
// Create and initialize the presence system
PresenceSystem = NewObject<USupabaseEOSPresence>(this);
if (!PresenceSystem->Initialize())
{
UE_LOG(LogTemp, Error, TEXT("Failed to initialize EOS presence"));
return;
}
// Bind presence change handler
PresenceSystem->OnPresenceChanged.AddUObject(
this, &AMyPlayerController::HandlePresenceChanged);
// Bind error handler
PresenceSystem->OnEOSError.AddUObject(
this, &AMyPlayerController::HandleEOSError);
// Subscribe to a set of players (e.g., from a match lobby)
TArray<FString> PlayersToTrack;
PlayersToTrack.Add(TEXT("00000000000000000000000000000000"));
PlayersToTrack.Add(TEXT("11111111111111111111111111111111"));
PlayersToTrack.Add(TEXT("22222222222222222222222222222222"));
if (!PresenceSystem->SubscribeToPresence(PlayersToTrack))
{
UE_LOG(LogTemp, Error, TEXT("Failed to subscribe to presence updates"));
}
#else
UE_LOG(LogTemp, Warning,
TEXT("EOS presence not available in this build."));
#endif
}
void AMyPlayerController::HandlePresenceChanged(const FEOSPresenceData& PresenceData)
{
UE_LOG(LogTemp, Log, TEXT("Presence changed: %s is now %s"),
*PresenceData.ProductUserId,
*UEnum::GetDisplayValueAsText(PresenceData.Status).ToString());
if (!PresenceData.RichPresenceText.IsEmpty())
{
UE_LOG(LogTemp, Log, TEXT(" Activity: %s"), *PresenceData.RichPresenceText);
}
if (!PresenceData.StateData.IsEmpty())
{
UE_LOG(LogTemp, Log, TEXT(" State: %s"), *PresenceData.StateData);
}
// Update your UI or game logic here
UpdatePlayerStatusUI(PresenceData);
}
void AMyPlayerController::HandleEOSError(const FString& Operation, const FString& ErrorMessage)
{
UE_LOG(LogTemp, Error, TEXT("EOS Error [%s]: %s"), *Operation, *ErrorMessage);
ShowNotification(FString::Printf(TEXT("Presence error: %s"), *ErrorMessage));
}
void AMyPlayerController::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
if (PresenceSystem && PresenceSystem->IsInitialized())
{
PresenceSystem->UnsubscribeFromPresence();
PresenceSystem->Shutdown();
}
Super::EndPlay(EndPlayReason);
}
This example queries the friends list and iterates over the results:
#include "SupabaseEOSPresence.h"
void AMySocialMenu::ShowFriendsList()
{
#if WITH_EOS_SDK && SUPABASE_EOS_INTEGRATION
USupabaseEOSPresence* PresenceSystem = NewObject<USupabaseEOSPresence>(this);
if (!PresenceSystem->Initialize())
{
UE_LOG(LogTemp, Error, TEXT("Failed to initialize presence for friends query"));
return;
}
// Bind the friends list callback
PresenceSystem->OnFriendsListUpdated.AddUObject(
this, &AMySocialMenu::OnFriendsListReceived);
// Start the friends list query
if (!PresenceSystem->QueryFriendsList())
{
UE_LOG(LogTemp, Error, TEXT("Failed to start friends list query"));
}
#endif
}
void AMySocialMenu::OnFriendsListReceived(const TArray<FEOSFriendEntry>& Friends)
{
UE_LOG(LogTemp, Log, TEXT("Received %d friends"), Friends.Num());
int32 OnlineCount = 0;
for (const FEOSFriendEntry& Friend : Friends)
{
if (Friend.bIsOnline)
{
OnlineCount++;
UE_LOG(LogTemp, Log, TEXT(" [ONLINE] %s - %s"),
*Friend.DisplayName, *Friend.RichPresenceText);
}
else
{
UE_LOG(LogTemp, Log, TEXT(" [OFFLINE] %s"), *Friend.DisplayName);
}
}
UE_LOG(LogTemp, Log, TEXT("Total: %d online / %d total"),
OnlineCount, Friends.Num());
// Populate your friends list widget
PopulateFriendsListWidget(Friends);
}
This example sets the local player's rich presence with structured state data:
#include "SupabaseEOSPresence.h"
void AMyGameMode::OnMatchStarted(const FString& MapName, int32 MaxPlayers)
{
#if WITH_EOS_SDK && SUPABASE_EOS_INTEGRATION
if (!PresenceSystem || !PresenceSystem->IsInitialized())
{
return;
}
// Build rich presence text
FString RichText = FString::Printf(
TEXT("In Match - %s (%d/%d players)"),
*MapName, GetCurrentPlayerCount(), MaxPlayers);
// Build structured state data as JSON
FString StateData = TEXT("{\"matchId\":\"") + CurrentMatchId + TEXT("\",") +
TEXT("\"map\":\"") + MapName + TEXT("\",") +
TEXT("\"mode\":\"competitive\",");
// Optional: include additional game-specific state
if (GetCurrentPlayerCount() >= MaxPlayers)
{
StateData += TEXT("\"status\":\"in_progress\"");
}
else
{
StateData += TEXT("\"status\":\"waiting_for_players\"");
}
StateData += TEXT("}");