Skip to content

C++ Usage

The Steam plugin provides a native C++ API with full parity to the Blueprint layer. All functionality available in Blueprints can also be accessed from C++ using the same Steam data types and behavior.

The C++ API is modular. Each Steam feature area is exposed through its own dedicated *CPPLibrary.


C++ API Structure

Each Steam feature area is represented by a separate *CPPLibrary header. Libraries are independent and can be included and used in any combination.

This means:

  • There is no central entry point for all Steam functionality
  • Each library corresponds to one Steam feature area
  • Only the required headers need to be included
  • The C++ API mirrors the Blueprint API for the same feature

Available C++ Libraries

The plugin provides the following C++ libraries:

Header file Feature
SteamAchievementsCPPLibrary.h Achievements
SteamCloudSavesCPPLibrary.h Cloud Saves
SteamDLCCPPLibrary.h DLC
SteamFriendsCPPLibrary.h Friends
SteamInputCPPLibrary.h Steam Input
SteamLeaderboardsCPPLibrary.h Leaderboards
SteamLobbiesCPPLibrary.h Lobbies
SteamMultiplayerCPPLibrary.h Multiplayer
SteamOverlayCPPLibrary.h Overlay
SteamPresenceCPPLibrary.h Rich Presence
SteamScreenshotsCPPLibrary.h Screenshots
SteamStatsCPPLibrary.h Stats
SteamUserCPPLibrary.h User
SteamUtilityCPPLibrary.h Utilities
SteamVoiceChatCPPLibrary.h Voice Chat

Enable C++ Access

To access the Steam plugin from C++ code, add the plugin module to your project's Build.cs file.

Open your project's *.Build.cs file and add "PloxToolsSteam" to the dependency modules:

PublicDependencyModuleNames.AddRange(
    new string[]
    {
        "Core",
        "CoreUObject",
        "Engine",
        "PloxToolsSteam"
    }
);

Once the module is added, include the library header for the Steam feature you want to use:

#include "SteamAchievementsCPPLibrary.h"

You can include any *CPPLibrary.h header depending on the functionality required by your class.


General Usage Pattern

The C++ libraries follow the same three general usage patterns as the Blueprint API:

  • Synchronous functions return their result immediately
  • Asynchronous functions report their result through native Unreal delegates
  • Persistent event subscriptions return a handle and continue receiving events until explicitly unsubscribed

Synchronous Functions

Synchronous functions execute immediately and return their result directly.

They are commonly used for:

  • State checks
  • Cached data access
  • Local queries
  • Simple utility operations

For example, checking whether an achievement is unlocked:

#include "SteamAchievementsCPPLibrary.h"

bool UMyClass::IsAchievementUnlocked(const FString& AchievementID)
{
    return USteamAchievementsCPPLibrary::IsSteamAchievementUnlocked(AchievementID);
}

Synchronous functions may also return Steam data structures directly.

For example, reading cached friend information:

#include "SteamFriendsCPPLibrary.h"

void UMyClass::CacheFriendInfo(int32 Index)
{
    FSteamFriend Friend = USteamFriendsCPPLibrary::GetSteamFriend(Index);

    if (!Friend.UserID.IsValid())
    {
        return;
    }

    CachedFriendUserID = Friend.UserID;
    CachedFriendName = Friend.PersonaName;
    CachedFriendIsOnline = Friend.bIsOnline;
}

Asynchronous Functions

Operations that need to communicate with Steam may complete later and return their result through native Unreal delegates.

The usual pattern is:

  1. Create the required delegate
  2. Bind a function or lambda to it
  3. Pass the delegate to the Steam function
  4. Handle the result when Steam completes the operation

For example, unlocking an achievement:

#include "SteamAchievementsCPPLibrary.h"

void UMyClass::UnlockAchievement(const FString& AchievementID)
{
    FOnSteamUnlockAchievementSuccessNative OnSuccess;
    OnSuccess.BindLambda([]()
    {
        UE_LOG(LogTemp, Log, TEXT("Achievement unlocked"));
    });

    FOnSteamUnlockAchievementFailureNative OnFailure;
    OnFailure.BindLambda([](const FString& Error)
    {
        UE_LOG(LogTemp, Error, TEXT("Failed to unlock achievement: %s"), *Error);
    });

    USteamAchievementsCPPLibrary::UnlockSteamAchievement(
        AchievementID,
        OnSuccess,
        OnFailure
    );
}

Asynchronous operations can also return Unreal objects or Steam data through their delegates.

For example, loading a USaveGame object from Steam Cloud:

#include "SteamCloudSavesCPPLibrary.h"
#include "MySaveGame.h"

void UMyClass::LoadGameFromCloud(const FString& FileName)
{
    FOnSteamCloudLoadGameSuccessNative OnSuccess;
    OnSuccess.BindLambda([](USaveGame* LoadedGame)
    {
        UMySaveGame* SaveGame = Cast<UMySaveGame>(LoadedGame);
        if (!SaveGame)
        {
            return;
        }

        UE_LOG(
            LogTemp,
            Log,
            TEXT("Cloud save loaded. Level: %d, Coins: %d"),
            SaveGame->PlayerLevel,
            SaveGame->Coins
        );
    });

    FOnSteamCloudLoadGameFailureNative OnFailure;
    OnFailure.BindLambda([](const FString& Error)
    {
        UE_LOG(LogTemp, Error, TEXT("Failed to load cloud save: %s"), *Error);
    });

    USteamCloudSavesCPPLibrary::LoadGameFromSteamCloud(
        FileName,
        OnSuccess,
        OnFailure
    );
}

One-time asynchronous calls manage their own callback lifetime and do not require manual unsubscription.


Persistent Event Subscriptions

Some Steam events can occur multiple times during gameplay.

These APIs use an explicit Subscribe / Unsubscribe pattern:

  1. Create and bind the event delegate
  2. Call the corresponding Subscribe... function
  3. Store the returned handle
  4. Use that handle to unsubscribe when the event is no longer needed

For example, listening for DLC installation events:

#include "SteamDLCCPPLibrary.h"

void UMyClass::StartListeningForDLC()
{
    FOnSteamDLCInstalledNative OnInstalled;
    OnInstalled.BindUObject(this, &UMyClass::HandleDLCInstalled);

    DLCListenerHandle =
        USteamDLCCPPLibrary::SubscribeToSteamDLCInstalled(OnInstalled);
}

void UMyClass::HandleDLCInstalled(int32 DLCAppID)
{
    UE_LOG(LogTemp, Log, TEXT("DLC installed: %d"), DLCAppID);
}

void UMyClass::StopListeningForDLC()
{
    if (!DLCListenerHandle.IsValid())
    {
        return;
    }

    USteamDLCCPPLibrary::UnsubscribeFromSteamDLCInstalled(DLCListenerHandle);
    DLCListenerHandle = FSteamDLCListenerHandle();
}

The listener handle should be stored as a member of the subscribing object:

FSteamDLCListenerHandle DLCListenerHandle;

Persistent subscriptions should be removed when the listener is no longer needed or before the subscribing object is destroyed.

Unlike one-time asynchronous operations, subscribed events can fire repeatedly until explicitly unsubscribed.


Summary

The Steam C++ API uses one library per Steam feature area and follows three consistent patterns:

  • Call synchronous functions for immediate state and cached data
  • Bind native delegates for one-time asynchronous Steam operations
  • Store subscription handles for persistent Steam events and unsubscribe when finished

Once these patterns are understood, the same general workflow applies across Achievements, Cloud Saves, DLC, Friends, Steam Input, Leaderboards, Lobbies, Multiplayer, Overlay, Rich Presence, Screenshots, Stats, User, Utilities, and Voice Chat.