FULL TUTORIAL to add SIMPLE and PROGRESSIVE steam achievements in UE5 with BLUEPRINTS WITHOUT any paid plugins.

I’ve made a video that gets straight to the point if you don’t want to read all of that: https://youtu.be/4JSirvmjOb0

(Same tutorial but on reddit: Reddit - Dive into anything)

This tutorial doesn’t require any paid plugins, it only covers simple and INTEGER progressive achievements. It works in UE5 and recent UE4 versions.

If you want to add the achievements of your own game it must be accepted by steam and changes must be published. If it isn’t, you can still follow a part of this tutorial using steam’s test app “Spacewar” with its AppId being 480.

  1. Make sure to enable “Online” plugins in the Engine.

Post image
(These ones are enough)

  1. Setup steam in Unreal Engine. Download the steam SDK and follow the steps (before “Using Sessions”) in the Unreal Online Subsystem Steam documentation.

Steam SDK: Steamworks

Online Subsystem steam: Online Subsystem Steam Interface in Unreal Engine | Unreal Engine 5.1 Documentation

You don’t need to do the steps after “Using Sessions” to use achievements.

Now Steam should be working on your game. To try it, launch your game as a standalone game and you should see the steam overlay when you press shift + tab. If it doesn’t work try to restart the editor

Post image

  1. We can now add achievements.

For every achievements you will need to add their API Names in “DefaultEngine.ini”.

Post image
To do so, go back to your “DefaultEngine.ini” and add a new line under [OnlineSubsystemSteam] for each achievements (simple or progressive).

On every line you will need to add:

Achievement_{INDEX}_Id={API_NAME} 

You need to increment {INDEX} on each line and {API_NAME} is the steam API name of your achievement, the order shouldn’t matter. Do not add quotation marks around the API name.

This should look like this:

[OnlineSubsystemSteam]
bEnabled=true
SteamDevAppId=2217560
Achievement_0_Id=Level3
Achievement_1_Id=Level6
Achievement_2_Id=Level9
Achievement_3_Id=Level12
Achievement_4_Id=100%
Achievement_5_Id=Damage
Achievement_6_Id=Warming

If the editor was opened, you will need to restart it.

    1. Simple achievements.

Simply add these nodes to your BP when you want to give the achievement, Make sure to change the “Achievement Name” value to your achievement’s API name.

Post image
“Progress” is either -1, 0 or 1.

-1 will remove the achievement, 0 will do nothing and 1 will get the achievement.

    1. Progressive achievements.

In Steamworks, create a stat with its TYPE being “INT”. When you give it a name, repeat it and add “_” between the two names, for exemple, “DamageStat” would be:

DamageStat_DamageStat 

Post image
Make sure to add the stat to your achievement’s progress stat in Steamworks.

Post image
An entry in steam’s leaderboard will be created for this stat. You will be able to access it in the “Leaderboards” tab in Steamworks.

There are multiple ways to load and set a stat value. Here’s how I suggest you do it:

  1. Get the stat’s value and set it in a custom integer variable when the game launches
  2. Update the variable to the target value in-game
  3. At the end of the game, write the value to the steam leaderboard

To do so, when the game launches, add these nodes to get the leaderboard value and set it to a custom variable. I did this in my game instance, after the “Event Init”. (Note that you might need to wait a little bit after the game launches to use these nodes, this is why I made a little timer that tries to call the node multiple times if it fails.)

Post image
When you write the API Name in unreal, don’t repeat it with “_”.

Then, in-game, you just need to change your custom value to whatever you want, I personally just increment it.

At the end of the game, I set the new value using these nodes:

Post image

  1. Packaging the game.

(This is explained in the Online Subsystem Steam documentation)

When you package your game you will need to add a .txt file to your build under:

{MAIN_FOLDER}\{GAME_NAME}\Binaries\Win64\

Post image
To do so, create a new text file called “steam_appid.txt” and inside it paste your app id and nothing else. This id is the number next to your game’s name in Steamworks.

Post image

  1. Enjoy :slight_smile:

If you have any questions or find anything inaccurate or unclear please let me know!

Note that I am not sure if you need to add progressive achievements names to “DefaultEngine.ini” and if you need to enable every single Online plugins. You can also use other values than -1,0,1 in the “Progress” pin but it will just make the code less understandable and won’t give other possibilities. I am guessing the achievement order doesn’t matter in “DefaultEngine.ini” but I’m not 100% sure.

For some reason this subject was very dark and not up to date so thank you to everybody who shared about this and have allowed me to add achievements to my own game! I figured making this tutorial could help other people and save their time. I didn’t came up with anything, I just combined the information that seemed to be working.

Here are the links that helped me:

7 Likes

Thanks for the writeup, a few notes.

Stats
This only really works well if you have 1 Stat. If you have multiple Stats (let’s say Kills, Gold, Level) and you try to update them at the same time (at end of level) only 1 will Succeed, the rest won’t even Fail, just nothing will happen.

While it seems to Succeed in Writing a Stat this way, for me the Read Leaderboard Integer doesn’t work (doesn’t Fail, just nothing happens). The reason I found out was: in order to READ the Stat, it needs a Leaderboard with the Same Name as the Stat but without “_Stat”. So for instance Stat = “Kills_Kills” and Leaderboard = “Kills”.
ALSO the Leaderboard needs to be Descending Numeric.
THEN the Read Leaderboard Integer works…

It’s infuriating to work this way instead of having actual Steam Stats / Achievement nodes exposed in Blueprint :roll_eyes:

Achievements
Same as above, let’s say you finished a Level = 1 Achievement, but also beat a fast time = 1 Achievement, this should Unlock 2 Achievements. But only 1 will unlock. So you need to build a custom queue system…

I suggest putting the Achievement handling in GameInstance so it works even though you exit a level, because if you create a Queue and update Stats and Unlock multiple Achievements you could be waiting for several seconds before the process completes.

It’s so ridiculously obtuse and complex in Unreal compared to Unity, this whole process is 2 lines of code in Unity and it works every time, no need for queueing, no stats ever fail, I can unlock multiple Achievements at the same time… and no word from UE Devs in over 7 years. Just wow :exploding_head:

This is how I setup multiple Stats

STEAMWORKS

First Setup Stats like this:


Stat Name needs to be “stat_stat

Then Create a Leaderboard:


Leaderboard Name needs to be “stat” and Descending Numeric.
Also, it won’t show up as an actual Community Leaderboard if you leave “Community Name” blank.

Setup the Achievement that’s tied to the Stat:

Then Publish these changes!

BLUEPRINT

I recommend handling all Stats / Achievements in GameInstance so it can be accessed everywhere and isn’t abrupted by the player changing scene etc. Also the Events are Asynchronous Calls so they need to be in the Event Graph and can’t be in a Function.

Reading Stats:

In GameInstance: Event Begin I run this Event after a 1 sec Delay (to let everything initialize correctly):


I Read the current Stat values and Save them down in my Save Game so we don’t have to Read Leaderboard Integer constantly (this is because Read Leaderboard Integer takes time AND I have experienced many times that it simply fails to run On Succeed or On Failure. So we use it once every time we start the game and that’s it.
Also don’t use a Sequence for this as it will fail.

Saving Stats:

When you want to add Stats, do it Locally to your Save Game first.


(Your code will look different of course, but this is just a simple example.)

Uploading Stats:

Then it’s time to upload the Stats as follows.


Do not use a Sequence for this as it will fail, it needs to be connected as above for it to work. Also make sure you do NOT call this Event multiple times before it is complete, it is therefor best to have a specific point where it’s called once (like end of a level).

Result:

After getting some Airtime in my game, I end my turn, run the code and it Uploads to Steam as shown below. (You might need to exit the game and let Steam load for a moment before the progress shows up.)


When you hit your goal it will automatically unlock the Achievement.

Resetting Stats:
There are a few ways to reset Stats but not many good ways in Blueprint.

Step 1: In Steamworks > LeaderboardsView ScoresDelete (your entry)
That solves 1 part, but the Stat itself will not be reset in your account.

Step 2: Open Steam with Console by typing this in Run (Win+R)
OpenSteamCmd

A Console window will open with steam: type → reset_all_stats 480
(Where 480 is your unique AppID)
To Reset a specific Achievement type → achievement_clear 480 Achievement_Name

To Reset All Achievements from inside Unreal BP, run this:


(online.ResetAchievements)

3 Likes

As previously stated, if you were to send Write Achievement Progress for multiple Achievements in a short time (like you got 100 kills, beat the level, and leveled up at the same time → 3 Achievements), then only 1 of them would unlock, the rest would get stuck in limbo.

This is one example of an Achievement Unlock Queue system.

In your GameInstance add the following Variables:
String Array where we’ll add Achievement IDs to unlock
and a Bool to let us know it’s in progress
Variables

Then write this system:


Whenever you call to unlock an ID, it’s added to the Array (in the back).

Then we check wether it’s already isUnlockingAchievements (we don’t need to proceed for Achievement nr2 or nr3 as they are already put next in queue in the Array).

Cache Achievements once, then check the Length of Array. If we have 0 then we are done, and we reset the isUnlockingAchievements. If it’s > 0, then we go ahead and Write Achievement Progress for Array[0] and Remove Array[0]. Then we Repeat that cycle until we run out of Array IDs.

Testing

This is how you call to Unlock Achievements.
They’ll be unlocked one after another.

2 Likes

Thank you so much for giving so much more informations!

I had no idea that an achievement might not trigger if there is another at the same time :confused:

1 Like

OH DUDE OR GIRL OR TRANSVESTITE OR TRANSGENDER GIRL OR TRANSGENDER BOY

WOW THATS SO GOOD THANK U

2 Likes

Great tutorial. Quick Q: I tested in the pop-out viewport and it worked like a charm, I saw the achievement pop. But when I quit out of the test, edit some more things, then go to test again, the achievement won’t pop again. How do I reset them? Can I only preview an achievement unlocking once?

BTW: Once I package my build, I find that I can’t open the steam overlay or check achievements when playing the packaged build, even with the text file in the folder. Is that normal? Will achievements only be accessible after I properly upload the build to Steam?

Yes an unlocked Achievement will only pop-up once, unless you Reset it.
If you Ctrl+F Search this post for “Resetting Stats” I wrote a few ways to reset stats and achievements.

Once you have Steam SDK / Steamworks integrated in your Project and make a Build it will automatically run Steam and play whatever build is uploaded (if any). So you have to upload it to Steam before it will work in Build (that is my experience at least).

1 Like

Good tutorial, I tried to create a result system that counts kills in a game. It only seems to work for me, some of my friends have tried it and it doesn’t count kills for them (in my case I have that as a statistic). I don’t know why…