Skip to main content

Retrieving achievements

You can fetch and display a list of achievements, both those the user has obtained and those that are still locked. Achievements in Epic Online Services are awarded through stats, so if you want to grant an achievement to a user, see Updating stats instead.

Querying achievement definitions

To get the full list of achievements, including their descriptions and titles, call QueryAchievementDescriptions:

#include "OnlineSubsystem.h"
#include "OnlineSubsystemUtils.h"
#include "Interfaces/OnlineAchievementsInterface.h"

// ...

IOnlineSubsystem *Subsystem = Online::GetSubsystem(this->GetWorld());
IOnlineIdentityPtr Identity = Subsystem->GetIdentityInterface();
IOnlineAchievementsPtr AchievementsInterface = Subsystem->GetAchievementsInterface();

AchievementsInterface->QueryAchievementDescriptions(
// The user looking up achievements. Though the results from
// this call are the same between players, the query requires
// a user ID to authenticate the request.
*Identity->GetUniquePlayerId(0),
FOnQueryAchievementsCompleteDelegate::CreateLambda([](
const FUniqueNetId &UserId,
const bool bWasSuccessful)
{
// If bWasSuccessful, the achievement definitions are
// now cached. You should now call `QueryAchievements`
// to get the player-specific data (see below).
}));

Querying achievements

Once you've fetched achievement definitions, you can query the player-specific achievement data. All achievements are returned by this call; both locked and unlocked. While QueryAchievementDescriptions provides you with player independent data (such as the achievement title), QueryAchievements provides you with player specific data (such as the achievement progress).

To get the player-specific data for achievements, call QueryAchievements:

#include "OnlineSubsystem.h"
#include "OnlineSubsystemUtils.h"
#include "Interfaces/OnlineAchievementsInterface.h"

// ...

IOnlineSubsystem *Subsystem = Online::GetSubsystem(this->GetWorld());
IOnlineIdentityPtr Identity = Subsystem->GetIdentityInterface();
IOnlineAchievementsPtr AchievementsInterface = Subsystem->GetAchievementsInterface();

AchievementsInterface->QueryAchievements(
// The user looking up achievements. Though the results from
// this call are the same between players, the query requires
// a user ID to authenticate the request.
*Identity->GetUniquePlayerId(0),
FOnQueryAchievementsCompleteDelegate::CreateLambda([](
const FUniqueNetId &UserId,
const bool bWasSuccessful)
{
// If bWasSuccessful, the achievements are cached and you can
// iterate through them (see below)
}));

Iterating through achievements

Once you've cached both achievement definitions and the player-specific achievement data, you can iterate through the achievement data using GetCachedAchievements and GetCachedAchievementDescription:

#include "OnlineSubsystem.h"
#include "OnlineSubsystemUtils.h"
#include "Interfaces/OnlineAchievementsInterface.h"

// ...

IOnlineSubsystem *Subsystem = Online::GetSubsystem(this->GetWorld());
IOnlineIdentityPtr Identity = Subsystem->GetIdentityInterface();
IOnlineAchievementsPtr AchievementsInterface = Subsystem->GetAchievementsInterface();

// Get the achievement data for LocalUserNum 0.
TArray<FOnlineAchievement> AchievementsData;
verify(
AchievementsInterface->GetCachedAchievements(*Identity->GetUniquePlayerId(0), AchievementsData) ==
EOnlineCachedResult::Success);

// Iterate through the full list of achievements.
for (auto Data : AchievementsData)
{
// Data contains Id and Progress, e.g:
//
// Data.Id
// Data.Progress (0.0f to 100.0f)

// With the ID, you can call GetCachedAchievementDescription, e.g:
FOnlineAchievementDesc AchievementDesc;
verify(
AchievementsInterface->GetCachedAchievementDescription(Data.Id, AchievementDesc) ==
EOnlineCachedResult::Success);

// AchievementDesc contains fields such as Title, UnlockedDesc and LockedDesc
}