Example Project
The example project includes a Markdown file that shows the steps required to use it. Follow along with the instructions below to build a simple EOS Leaderboard integration in your Unreal Engine game.
What We'll Build
A minimal but complete EOS Leaderboard integration that:
- Initializes EOS on game start
- Logs the player in silently (persistent token) or via browser (fallback)
- Fetches the list of available leaderboards from the Dev Portal
- Queries the Top 10 entries and displays them in a UI widget
- Submits the player's score at the end of a match
- Re-queries the leaderboard to reflect the updated rank
Step 1 — Initialize EOS in GameInstance
Create (or open) your GameInstance Blueprint.
In Event Init:
Event Init
└─► Initialize EOS
├─► [true] ──► Print "EOS Ready"
└─► [false] ──► Print "EOS Init Failed — check DefaultEngine.ini"
Why GameInstance?UEOSCoreLeaderboardSubsystem is a GameInstanceSubsystem — it lives as long as the GameInstance. Initializing here ensures EOS is ready before any level loads.
Step 2 — Log In the Player
After EOS is initialized, you need two login steps:
- Auth Login → Epic Account identity
- Connect Login → Game identity (ProductUserId) — auto-triggered by leaderboard nodes if skipped
Create a function BP_LoginPlayer in your GameInstance:
BP_LoginPlayer
│
└─► EOS Auth Login (Epic Account)
PrimaryLoginType = AccountPortal
Policy = PersistentThenPortal
bDeletePersistentBeforeFallback = true
│
├─► OnSuccess
│ └─► EOS Connect Login (ProductUserId)
│ │
│ ├─► OnSuccess
│ │ └─► Print "Logged in as: " + Result.ProductUserId
│ │ ──► Call BP_LoadLeaderboards
│ │
│ └─► OnFailure
│ └─► Print "Connect Login failed: " + Result.ErrorMessage
│
└─► OnFailure
└─► Print "Auth Login failed: " + Result.ErrorMessage
Step 3 — Discover Available Leaderboards
Use EOS Get Leaderboard List to fetch all leaderboards configured in your Dev Portal. This is useful when you want to display multiple boards or build a dynamic leaderboard selector.
Create a function BP_LoadLeaderboards:
BP_LoadLeaderboards
│
└─► EOS Get Leaderboard List
│
├─► OnSuccess
│ └─► Result ──► [Store in variable: AvailableLeaderboards]
│ For Each Entry:
│ Print Entry.LeaderboardId + " → " + Entry.StatName
│ ──► Call BP_QueryTopLeaderboard with first entry
│
└─► OnFailure
└─► Print "Get Leaderboard List failed: " + ErrorMessage
If you only have one known leaderboard, you can skip this step and hardcode the
LeaderboardIdstring directly in the next step.
Step 4 — Query the Top 10
Use EOS Query Leaderboard Range to fetch only the entries you need.
Create a function BP_QueryTopLeaderboard(LeaderboardId: FString):
BP_QueryTopLeaderboard
│
└─► EOS Query Leaderboard Range
LeaderboardId = [LeaderboardId input]
RankFrom = 1
RankTo = 10
│
├─► OnSuccess
│ └─► Result ──► [Store in variable: TopEntries]
│ ──► Call BP_PopulateLeaderboardUI
│
└─► OnFailure
└─► Print "Query failed: " + ErrorMessage
RankFrom to the end of the board. For displaying a "near me" section, query with RankFrom = PlayerRank - 2, RankTo = PlayerRank + 2.Step 5 — Display the Leaderboard in a Widget
Create a Widget Blueprint WBP_Leaderboard.
Add a VerticalBox named EntriesContainer.
Create a child widget WBP_LeaderboardEntry with:
TextBlockfor rank (e.g.#1)TextBlockfor display nameTextBlockfor score
In WBP_Leaderboard, create a function PopulateList(Entries: TArray<FEOSLeaderboardEntry>):
PopulateList
└─► Clear Children (EntriesContainer)
└─► For Each Entry in Entries
└─► Create Widget WBP_LeaderboardEntry
Set RankText = "#" + Entry.Rank
Set NameText = (Entry.UserDisplayName.IsEmpty)
? "Unknown"
: Entry.UserDisplayName
Set ScoreText = Entry.Score
Add to EntriesContainer
Highlight the local player's row:
Compare Entry.UserId with Get Local Product User Id from the subsystem to identify which row belongs to the local player, then apply a different background or text color.
For Each Entry:
└─► Is Entry.UserId == GetEOSSubsystem.GetLocalProductUserId?
├─► true ──► Set row background to highlight color
└─► false ──► Set row background to default color
Step 6 — Submit a Score
Call EOS Ingest Stat at the end of a match (or on any score event) to update the player's leaderboard position.
[Game Event: Match ended — final score = 1500]
│
└─► EOS Ingest Stat (Leaderboard)
StatName = "score"
Amount = 1500
│
├─► OnSuccess
│ └─► Print "Score submitted!"
│ ──► Call BP_QueryTopLeaderboard [refresh the UI]
│
└─► OnFailure
└─► Print "Ingest failed: " + ErrorMessage
EOS processes the stat asynchronously on its servers. The new rank appears after a short delay. Calling
BP_QueryTopLeaderboardright afterOnSuccesswill show the updated leaderboard once EOS has applied it.
MAX aggregation, only the call with Amount > current best will change the rank. Calls with lower values are silently ignored by EOS — they still fire OnSuccess.Complete Flow Summary
GameInstance::Init
└─► Initialize EOS ──► BP_LoginPlayer
│
Auth Login (PersistentThenPortal)
│ OnSuccess
Connect Login
│ OnSuccess
BP_LoadLeaderboards
│
EOS Get Leaderboard List
│ OnSuccess
BP_QueryTopLeaderboard (Top 10)
│ OnSuccess
WBP_Leaderboard::PopulateList
│
[Match ends]
│
EOS Ingest Stat ("score", finalScore)
│ OnSuccess
BP_QueryTopLeaderboard ──► Refresh UI
Tips
Re-query after ingest
Always call BP_QueryTopLeaderboard after EOS Ingest Stat OnSuccess to keep the UI in sync. EOS may need a moment to process the new rank — a 1–2 second delay before querying can help on slow connections.
Display name missingUserDisplayName can be empty if EOS does not return it for a given player. Always fall back to a placeholder like "Player" or the truncated UserId.
Score formattingScore is an int64. Use ToString in Blueprint and add any visual formatting (commas, units) in your widget logic.
Leaderboard not updating If a submitted score does not appear, check:
- The stat name matches exactly (case-sensitive) what is configured in the Dev Portal
- The aggregation method (
MAX,SUM, etc.) is consistent with your expectations - The player's Product User ID is valid (check
Is Player Logged In)
Multiple leaderboards
Store the full AvailableLeaderboards array in your GameInstance. Display a tab or dropdown to let players switch between boards, and call BP_QueryTopLeaderboard with the selected LeaderboardId each time.
Offline / no connection
If EOS returns EOS_NoConnection on any node, show a friendly message and allow the player to retry. Do not block gameplay — scores can be submitted when the connection is restored.
Troubleshooting
| Symptom | Likely cause |
|---|---|
InitializeEOS returns false | Invalid credentials in DefaultEngine.ini |
| Auth Login browser does not open | AccountPortal requires a valid ClientId and ClientSecret |
EOS Get Leaderboard List returns empty array | No leaderboards configured in Dev Portal for this Sandbox/Deployment |
EOS Query Leaderboard returns empty Result | No entries yet — submit at least one stat ingest first |
EOS Ingest Stat fails with EOS_NotFound | StatName does not match the Dev Portal exactly (case-sensitive) |
| Score submitted but rank unchanged | Aggregation is MAX and the new score is lower than the current best |
UserDisplayName is always empty | Normal — EOS does not always return display names in leaderboard records |
| Connect Login fires automatically in nodes | Expected behavior — the nodes handle it for you |
Functions
Complete reference for every Blueprint node and utility function provided by EOS Leaderboard.
Introduction
EOS Achievements is a Blueprint-first plugin for Unreal Engine 5.4+ that integrates Epic Online Services Achievements into your game — authentication, progress tracking, unlock, and real-time listeners included.