Steam achivements

I’ve followed the steam tutorial here:

Then I have spent the last few hours grinding my face against code wondering why I cant save a float progress value for steam achievements.
From what I have found is that you cant do this.
I always thought steam achievements would show you a progress bar per achievement.

My question is, lets say I want to have an achievement that I want to unlock after 10 games, how do I go about storing this progress? Do I manually need to save this to some kind of ini file somewhere?

anyone have any insight into this?

This is a bit old but I’d say it’s still the same - progress towards individual achievements is something you’d need to handle yourself. That’s just a guess, but it’s how I’d handle it.

The Steam can handle progress automatically, but not with the current UE4 the Steam achievements implementation.
If you will increment the Steam stat co-related with the Steam achievement, the achievement will be unlocked when stat get maximum value.
I’ve extended native code OnlineAchievementsInterfaceSteam.cpp

with something like this:



      **  FOnlineAchievementsSteam::ReadAchievementsFromConfig** - this function loads achievements descriptions from the config file, and the code below should be placed in that function

	const int32 achieviementsNum = 1;
        //this is remapping between Steam achievement to Stat stat( You need to read steam docs to undestand difference between simple achievement and stat)
	static const FString AchievementsMapping[achieviementsNum][2] =
	{
		{ TEXT("ACH_PLAYTIME_100_HOURS"), TEXT("STAT_PLAYTIME") },
        };
        
       	for (int32 i = 0; i < achieviementsNum; i++)
	{
		FOnlineAchievementSteam NewAch;
		NewAch.Id = AchievementsMapping*[0];
		NewAch.StatId = AchievementsMapping*[1];  //**I added FString StatId; to the FOnlineAchievement struct**
		NewAch.Progress = 0.0;
		NewAch.bReadFromSteam = false;
		Achievements.Add(NewAch);
	}

	return Achievements.Num() > 0;




then in the FOnlineAchievementsSteam::WriteAchievements extend the achi writer with something like this:



                for (int32 AchIdx = 0; AchIdx < AchNum; ++AchIdx)
		{
			const FOnlineAchievement& AchievementInfo = (*PlayerAch)[AchIdx];
			if (AchievementInfo.Id == AchievementId)
			{

				if (!AchievementInfo.StatId.IsEmpty())
				{
					int32 CurrentStat = 0;
					SteamUserStats()->GetStat(TCHAR_TO_UTF8(*AchievementInfo.StatId), &CurrentStat);

					int32 Value = 0;
					It.Value().GetValue(Value);
					CurrentStat += Value;

					SteamUserStats()->SetStat(TCHAR_TO_UTF8(*AchievementInfo.StatId), CurrentStat);
				}
				else
				{
					// do not unlock it now, but after a successful write
#if !UE_BUILD_SHIPPING
					float Value = 0.0f;
					It.Value().GetValue(Value);
					if (Value <= 0.0f)
					{
						UE_LOG_ONLINE(Verbose, TEXT("Resetting achievement '%s'"), *AchievementId);
						SteamUserStats()->ClearAchievement(TCHAR_TO_UTF8(*AchievementId));
					}
					else
					{
#endif // !UE_BUILD_SHIPPING

						UE_LOG_ONLINE(Verbose, TEXT("Setting achievement '%s'"), *AchievementId);
						SteamUserStats()->SetAchievement(TCHAR_TO_UTF8(*AchievementId));

#if !UE_BUILD_SHIPPING
					}
#endif // !UE_BUILD_SHIPPING
				}


			
				break;
			}
		}



then you have to implement your own function to increment stat related to certain achievement:



IOnlineAchievementsPtr Achievements = OnlineSub->GetAchievementsInterface();
WriteObjectStats = MakeShareable(new FOnlineAchievementsWrite());
WriteObjectStats->SetIntStat(TEXT("ACH_PLAYTIME_100_HOURS"),1); //increment ACH_PLAYTIME_100_HOURS with 1 second or something

FOnlineAchievementsWriteRef WriteObjectRef = WriteObjectStats.ToSharedRef();
Achievements->WriteAchievements(*UserId, WriteObjectRef);



Hope it will help you

Unreal can handle this automatically. You just have to use the leaderboard interface and the achievements interface (leaderboard interface to modify stats and achievements interface to modify achievements). Pretty much the only thing you need to implement is IndicateAchievementProgress. You just increment the stat with the leaderboards interface and steam worries about triggering the achievement when the stat reaches the correct point that you set in the steam achievements webpage dealio. You essentially hacked the leaderboard interface into the achievement interface.

That said, if you’re going to do anything that isn’t inherently supported with the unreal api, I’d just write your own wrapper for Steam stats/achievements instead of trying to extend the unreal api because there’s some things that will just become impossible or not worth it if you’re using the steam interface because it’s a pita to make parts of the steam interface accessible because of the way the online interface inheritance and package structure is handled. I use both; modify stats with unreal’s interface, and then have a project local wrapper for the extra steam functions that I needed access to. Usually the latter part is pretty unnecessary because most of the steam functions I need are just single function calls or exposed, I just have it so all the things are in one easy to access spot when I need them.

1 Like