EOS Integration KitAlpha
v5.0.1

Statistics

Track and query player statistics for analytics and progression systems

Statistics track player progress like kills, deaths, playtime, and scores. Stats can trigger achievements when thresholds are met.

Stat names must be UPPERCASE with no spaces or special characters. Example: ENEMIES_KILLED, TOTAL_PLAYTIME

Portal Setup

  1. Go to the EOS Developer Portal
  2. Navigate to Game ServicesStats
  3. Click + New Stat
  4. Provide Stat Name and choose Aggregation Type:
TypeBehavior
SumAdds ingested values together
LatestKeeps the most recent value
MaxKeeps the highest value
MinKeeps the lowest value

Use Sum for cumulative stats (total kills, total playtime). Use Max for high scores or best times.

Update Stats

Ingest stat values to update player statistics.

Update EIK Stats node
Copy and paste into Unreal Engine Blueprint editor

Pass an array of stat names and values to ingest. Values are processed according to the aggregation type configured in the portal.

#include "EIKCore/Public/Interfaces/IEIKStats.h"

void UMyClass::UpdateStats()
{
    TSharedPtr<IEIKStats> Stats = GetStatsInterface();
    if (!Stats.IsValid()) return;

    FEIKUpdateStatsParams Params;
    Params.Stats.Add(FEIKStatIngest{TEXT("ENEMIES_KILLED"), 1});
    Params.Stats.Add(FEIKStatIngest{TEXT("TOTAL_SCORE"), 500});

    Stats->UpdateStats(0, Params,
        FEIKAsyncCallbackVoid::CreateLambda(
            [](const TEIKAsyncResult<void>& Result)
            {
                if (Result.IsSuccessful())
                {
                    UE_LOG(LogTemp, Log, TEXT("Stats updated"));
                }
            }));
}
#include "Online/OnlineServices.h"
#include "Online/Stats.h"

using namespace UE::Online;

void UMyClass::UpdateStats()
{
    IOnlineServicesPtr Services = GetServices(EOnlineServices::Epic);
    IStatsPtr Stats = Services->GetStatsInterface();

    FUpdateStats::Params Params;
    Params.LocalAccountId = GetLocalAccountId();
    Params.UpdatedStats.Add(FUserStats{
        GetLocalAccountId(),
        {{FString(TEXT("ENEMIES_KILLED")), FStatValue(1)},
         {FString(TEXT("TOTAL_SCORE")), FStatValue(500)}}
    });

    Stats->UpdateStats(MoveTemp(Params))
        .OnComplete([](const TOnlineResult<FUpdateStats>& Result)
        {
            if (Result.IsOk())
            {
                UE_LOG(LogTemp, Log, TEXT("Stats updated"));
            }
        });
}
#include "OnlineSubsystem.h"
#include "Interfaces/OnlineStatsInterface.h"

void UMyClass::UpdateStats()
{
    IOnlineSubsystem* OnlineSub = IOnlineSubsystem::Get(FName(TEXT("EIK")));
    IOnlineStatsPtr Stats = OnlineSub->GetStatsInterface();
    FUniqueNetIdPtr UserId = OnlineSub->GetIdentityInterface()->GetUniquePlayerId(0);

    FOnlineStatsUserUpdatedStats UpdatedStats;
    UpdatedStats.AccountId = UserId;
    UpdatedStats.Stats.Add(TEXT("ENEMIES_KILLED"), FOnlineStatValue(1));
    UpdatedStats.Stats.Add(TEXT("TOTAL_SCORE"), FOnlineStatValue(500));

    Stats->UpdateStats(*UserId, {UpdatedStats},
        FOnlineStatsUpdateStatsComplete::CreateLambda(
            [](const FOnlineError& Error)
            {
                if (Error.WasSuccessful())
                {
                    UE_LOG(LogTemp, Log, TEXT("Stats updated"));
                }
            }));
}

Query Stats

Fetch player statistics from the server.

Query EIK Stats node
Copy and paste into Unreal Engine Blueprint editor
  • Stat Names: Array of stat names to query (empty = all stats)
  • Target Account Id: User to query (leave empty for local player)
void UMyClass::QueryStats()
{
    TSharedPtr<IEIKStats> Stats = GetStatsInterface();

    FEIKQueryStatsParams Params;
    Params.StatNames.Add(TEXT("ENEMIES_KILLED"));
    Params.StatNames.Add(TEXT("TOTAL_SCORE"));
    // Leave TargetAccountId invalid to query local player

    Stats->QueryStats(0, Params,
        FEIKAsyncCallback<FEIKQueryStatsResult>::CreateLambda(
            [](const TEIKAsyncResult<FEIKQueryStatsResult>& Result)
            {
                if (Result.IsSuccessful())
                {
                    const FEIKUserStats& UserStats = Result.GetValue().UserStats;
                    for (const auto& Pair : UserStats.Stats)
                    {
                        UE_LOG(LogTemp, Log, TEXT("%s: %d"), *Pair.Key, Pair.Value);
                    }
                }
            }));
}
void UMyClass::QueryStats()
{
    IStatsPtr Stats = GetStatsInterface();

    FQueryStats::Params Params;
    Params.LocalAccountId = GetLocalAccountId();
    Params.TargetAccountId = GetLocalAccountId();
    Params.StatNames.Add(TEXT("ENEMIES_KILLED"));
    Params.StatNames.Add(TEXT("TOTAL_SCORE"));

    Stats->QueryStats(MoveTemp(Params))
        .OnComplete([](const TOnlineResult<FQueryStats>& Result)
        {
            if (Result.IsOk())
            {
                for (const auto& Stat : Result.GetOkValue().Stats)
                {
                    UE_LOG(LogTemp, Log, TEXT("%s: %s"), *Stat.Key, *Stat.Value.ToString());
                }
            }
        });
}
void UMyClass::QueryStats()
{
    IOnlineSubsystem* OnlineSub = IOnlineSubsystem::Get(FName(TEXT("EIK")));
    IOnlineStatsPtr Stats = OnlineSub->GetStatsInterface();
    FUniqueNetIdPtr UserId = OnlineSub->GetIdentityInterface()->GetUniquePlayerId(0);

    TArray<FString> StatNames = {TEXT("ENEMIES_KILLED"), TEXT("TOTAL_SCORE")};

    Stats->QueryStats(*UserId, {UserId.ToSharedRef()}, StatNames,
        FOnlineStatsQueryUsersStatsComplete::CreateLambda(
            [this, Stats, UserId](const FOnlineError& Error,
                const TArray<TSharedRef<const FOnlineStatsUserStats>>& UsersStats)
            {
                if (Error.WasSuccessful() && UsersStats.Num() > 0)
                {
                    for (const auto& Stat : UsersStats[0]->Stats)
                    {
                        UE_LOG(LogTemp, Log, TEXT("%s: %s"),
                            *Stat.Key, *Stat.Value.ToString());
                    }
                }
            }));
}

On this page