How to use Steam Leaderboards from BP?

Hi everyone.

I am trying to use Steam leaderboards in mostly blueprint game (got some C++ too, but I would like to keep it simple). I have Steam Works set up, stats and achievements are working good (after creating BP node for stats). But have problem with leaderboards, I have no idea whats wrong.

When using “Write Leaderboards Integer” (like on screenshot):

there was an error with doubled leaderboard name (name passed to BP node):

LogOnline:Warning: STEAM: Steamworks SDK warning: [S_API WARN] GetStat() failed, stat singleplayerScore_singleplayerScore does not exist - needs to be first configured on the Steamworks site
LogOnline:Warning: STEAM: Failure to write key value pair when uploading to Steam singleplayerScore_singleplayerScore=57364

I don’t understand why Leaderboards are mixed with Steam Stats, but found the place in code where doubled names are created:
In LeaderboardBlueprintLibrary.cpp @ 97 Write object is created with:

bool ULeaderboardBlueprintLibrary::WriteLeaderboardInteger(APlayerController* PlayerController, FName StatName, int32 StatValue)
{
	FOnlineLeaderboardWrite WriteObject;
	WriteObject.LeaderboardNames.Add(StatName);
...
	WriteObject.SetIntStat(StatName, StatValue);
	return WriteLeaderboardObject(PlayerController, WriteObject);
}

Then in OnlineLeaderboardInterfaceSteam.cpp @ 1351 Stat name is passed as both arguments in:

FName LeaderboardStatName = GetLeaderboardStatName(WriteObject.LeaderboardNames[LeaderboardIdx], It.Key());

and in OnlineLeaderboardInterfaceSteam.cpp @ 16 doubled name is created.

inline FName GetLeaderboardStatName(const FName& LeaderboardName, const FName& StatName)
{
	return TCHAR_TO_ANSI((*FString::Printf(TEXT("%s_%s"), *LeaderboardName.ToString(), *StatName.ToString())));
}

I changed GetLeaderboardStatName function to give one name if two arguments are the same with hope to see some leaderboard entries on SteamWorks page, but that didn’t help. Error with non existing leaderboard disappeared, but no entries where created. I admit once again: don’t understand this Leaderboard and Stats mix up, and I am not sure if that change was good :slight_smile:

In logs I got:

LogOnline:Warning: STEAM: Failure to write key value pair when uploading to Steam singleplayerScore=19996
LogOnline:Warning: Async task ‘FOnlineAsyncTaskSteamUpdateStats bWasSuccessful: 0 User: Slimak [0x110000104A5A63D]’ completed in 0.801725 seconds with 0
LogOnline:Warning: Async task ‘FOnlineAsyncTaskSteamUpdateLeaderboard bWasSuccessful: 0 Leaderboard: singleplayerScore Score: 0’ completed in 0.801878 seconds with 0

and for now I have no idea how to make it work. When testing this I got leaderboards reading set up in other BP so logs could be mixed with reading/writing.

Does anybody have an idea what’s wrong, and could share it? :slight_smile:

Were having the same issue!

Also would love to see how you created the nodes for stats!

I will put some walk through about steam stats next week. In few words I copied Leaderboards function and striped them from leaderboards calls :slight_smile:

Were having the same issue!

What did you do about that issue?

We haven’t addressed it yet, but looking into it this week

Ok so here is what we have figured out with your help!

If you name either your steam stat, leader board, or both the name that Unreal creates you will set the variable for the steam stat, leader board, or both.

Example your want your stat or leader board to be Test so on steam name that stat or leader board Test_Test and it works for both. This I figured out from when you saw that unreal was was doubling the name “STEAM: Failure to write key value pair when uploading to Steam singleplayerScore_singleplayerScore=57364”. So we just went with it. If it gets fixed we will just remove the double name from steam.

We don’t mind that because most of the leader boards that we are going to create are going to have a stat associated with it as well.

Hope this helps everyone

Update our fix didn’t seem to work…

our original test worked by:
1- creating a input in the player controller that would call an event on server in the games state to write to the stat/leaderboard on steam
2 - create the stat on steam with the double name

we also did those same steps to look up and print that stat information

It would work but seemed to stop working if you call the write to stat event to quickly

So now were going to look into C++

also if we tryed to do this for more then one stat neither would work at all

I got some things figured out.

To use Steam leaderboards from BP (with Write Leaderboards Integer) we need to create both Steam Stat and Steam Leaderboard with same name. If name doubling is sill in place names on Steam Works should be doubled with underscore in middle, ie.:

  • Stat Name in BP: singleplayerScore
  • Steam Stat: singleplayerScore_singleplayerScore
  • Steam Leaderboard: singleplayerScore_singleplayerScore

I use my single name tweak so I put same in name in all cases.

I got working reads and writes to leaderboards with that. But there was another problem. Writes to Steam Stats are made additive in the code (new values are added to old ones). That caused strange reads at the begging: two writes with values 5000 and 10000 gave me 15000 when red. I could change BP to update stats with delta values, but we already use absolute values for mobiles…

I made change in Engine\Source\Runtime\Online\OnlineSubsystemSteam\Private\OnlineLeaderboardInterfaceSteam.cpp @ 296

int32 OldValue, Value;
Stat.GetValue(Value);
if (SteamUserStatsPtr->GetUserStat(SteamUserId, TCHAR_TO_UTF8(*StatName), &OldValue))
{
	bSuccess = SteamUserStatsPtr->SetStat(TCHAR_TO_UTF8(*StatName), OldValue + Value) ? true : false;	
}

to

int32 OldValue, Value;
Stat.GetValue(Value);
if (SteamUserStatsPtr->GetUserStat(SteamUserId, TCHAR_TO_UTF8(*StatName), &OldValue))
{
	if (OldValue < Value)										
		bSuccess = SteamUserStatsPtr->SetStat(TCHAR_TO_UTF8(*StatName), Value) ? true : false;
}

Few lines further there is second case for float stats and made same change there.

as with: “also if we tried to do this for more then one stat neither would work at all”

New writes/reads are blocked if made before previous one finished. All worked fine when stats access was done separately.

btw: I am sorry for abandoning my topic for 2 weeks, had other urgent things to focus on. Thank you, HughieDM for hints.

And about “Using Steam Stats form BP”, where can put my code snipets??

I’m having the same issue and I am also finding it hard getting my head around it with the leaderboard/stats being so closely related. Is there any official word on the best way to approach this issue and as adding a Stat and leaderboard in the SteamWorks stuff with an ‘_’ doesn’t seem like the right approach as the comment above the GetLeaderboardStatName says:
“Create the proper stat name for a given leaderboard/stat combination”

Is there anywhere which gives a clear instruction on how the Shootergame Steamworks was setup with their naming conventions against the Unreal stuff?

Edit:
So I decided to try and update the GetLeaderboardStatName in C++. I changed it to not put in the “%s_%s” and it seemed to write the stat to the correct leaderboard. The function now looks like:

return TCHAR_TO_ANSI((*FString::Printf(TEXT("%s"), *StatName.ToString())));

Although, it would be nice to have an official word on this?

Sadly no, no official, Epic comment on that topic. I searched for docs or tutorials here (answerhub), forums and wiki. Found few turorials for achievements that gave me some hints. After that, I started to play with code and got what I described above.

At first I’ve also looked at ShooterGame and TappyChiken for hint. In second one there was some achievements BP snipets. Dont remeber what ver. it was.

After your question I updated ShoterGame to 4.8.3. Found no BP for leaderboards or achievemets. In code there are few achievements writes (few places in ShooterPlayerController.cpp) and one leaderboard write in ShooterPlayerController.->UpdateLeaderboardsOnGameEnd. That leaderboard write is custom made with leaderboard name: “ShooterAllTimeMatchResults” and few stats (“Score”, “Frags”…). I guess they have stats like: “ShooterAllTimeMatchResults_Score” etc. I guess because there’s no info about steam in ShoterGame docs.

Good luck, I hope I helped somehow.

Yeah a few of your pointers made me feel a bit better about not being the only one lost here.
For now, I simply take out the ‘_’ it puts in the stat name when it does a Leaderboard write and all seems fine. For some in-game stats, I go straight to the stat itself to update it:

SteamUserStats()->SetStat(TCHAR_TO_UTF8(*strStatName), nVal);

Seems to work fine as the Engine has already called the required functions to get the Steam cache of the stats in memory so they are pretty fast calls. I have also found that you can send WriteLeaderboard requests with a write object that doesn’t contain any stats and it will still update the leaderboard on Steam based on the RatedStat.

I would love to know how you managed to expose Steam Stats. We are currently stuck trying to figure it out. Did you put out that walk through about steam stats?

Has this been fixed?

I’ve made a thread on a tutorial to fix this issue (and credited the one who seemed to have found it first). Hope it helps many with the same issue.

For anyone who is struggling with this, if you want it fixed by Epic you should vote on this issue:

There doesn’t seem to be an issue about the extra underscore / name double up, unfortunately.

I started to convert to a code project to fix this, but being a code project seems to break or complicate other things. Having the steam stat BP nodes fixed officially would be great.

Just a heads up for anyone who is working with this issue in 4.19 and wants to keep it in Blueprints.

Write Leaderboard Integer -node writes as follows in 4.19:
Steam Stat with “name_name”
Steam Leaderboard with “name”

I confirmed this by creating an achievement linked to a stat with name_name, and it updated. The Leaderboard was created automatically on first call of the Write Leaderboard Integer -node.

Hi!! Did you make it work? Can you show me a screenshot of the blueprint? Thanks!

Hey, do you finally get a solution for this? I want to integrate the steam leaderboard in my UE4 game with blueprint but I don’t know how. Thanks!!!