Help with steam achievements, please

Hello friends.

It’s me again. Just before uploading my final game build to steam, I wanted to add achievements, however, I am having a very hard time, I tried both methods, by kismet and unreal script, but this is not working.

First of all I followed this tutorial:

www.worldofdasm.com/index_files/STEAMtutorial_menu.htm

It’s very simple and straightforward. The steam achievements setup is basically done by copying the kismet online subsystem classes to the src folder, add these new package on the ini files so it gets compiled. But there is one step which the tutorial did not mention, but I found here on the udn page:

https://docs.unrealengine.com/udk/Three/KismetOnlineSubsystem.html#Downloads

‘’ USE_STEAMWORKS and USE_GAMECENTER are defined in a file called Globals.uci. Comment out the one which you don’t want to use. When you modify Globals.uci, the Unrealscript Compiler won’t automatically pick this up. Thus you’ll need force a recompilation of Unrealscripts when you change it.’’ So I got the kismet nodes on my game.

Then I changed the achievements mapping in DefaultEngineUDK.ini:

[OnlineSubsystemSteamworks.OnlineSubsystemSteamworks]
bEnableSteam=true
bUseVAC=true
GameDir=unrealtest
GameVersion=1.0.0.0
Region=255
CurrentNotificationPosition=8
ResetStats=0
+AchievementMappings=(AchievementId=0,AchievementName=NEW_ACHIEVEMENT_1_0,ViewId=30,ProgressCount=0,MaxProgress=1,bAutoUnlock=True)
+AchievementMappings=(AchievementId=1,AchievementName=NEW_ACHIEVEMENT_1_1,ViewId=30,ProgressCount=0,MaxProgress=1,bAutoUnlock=True)

And last I added the kismet node on a testmap:

image

Then I tested the game, both offline and online, directly from my game uploaded to steam, because steam client recognizes my game running offline in the same it recognizes my game build uploaded to my steamworks account. The achievements did not unlock.

Here follows my achievements on steamworks panel:

image

I also created for each achievement a custom stats, following the tutorial on UDN Online Subsystem Works:

image

However, as I said, the achievements of my game don’t get unlocked by the kismet node:

image

Then I tried to unlock achievements directly from Unreal Scripting, following these 2 tutorials here:

https://forums.unrealengine.com/t/urgent-i-really-need-help-setting-up-steam-achievements/76959

Here follows the changes I made on UTAchievements:

enum EUTGameAchievements
{
	EUTA_EXPLORE_EveryMutator,
	EUTA_WEAPON_DontTaseMeBro,
	EUTA_WEAPON_StrongestLink,
	EUTA_WEAPON_HaveANiceDay,
	EUTA_VEHICLE_Armadillo,
	EUTA_POWERUP_DeliveringTheHurt,
	EUTA_HUMILIATION_SerialKiller,
	EUTA_HUMILIATION_OffToAGoodStart,
	NEW_ACHIEVEMENT_1_0,
	NEW_ACHIEVEMENT_1_1,
};

I added my 2 custom achievements here, then on the default properties I commented the UTAchievements and let only mine:

defaultproperties
{
	AchievementStatsReadClass=Class'UTStatsReadAchievements'
	AchievementStatsWriteClass=Class'UTStatsWriteAchievements'

	// @todo: Figure out if you want to add automatic progress for bitmask toasts (or if you want to, e.g., update two different stats for it,
	//		one bitmask, one count)

	// The list of achievements
	//AchievementsArray.Add((Id=EUTA_EXPLORE_EveryMutator,UnlockType=EAUT_BitMask,UnlockCriteria=0x1ff,ProgressCriteria=3,bDoUnlock=True,bDoProgress=True))

	// The below achievements are setup so the achievement manager does not handle unlocks/progress-toasts for these achievements;
	//	instead, this is handled by OnlineSubsystemSteamworks automatic achievement progress/unlock handling.
	//	To regain control of unlocks/progress from here, bAutoUnlock (and ProgressCount, if you want control of progress toasts) must be
	//	unset in AchievementMappings in DefaultEngineUDK.ini, and bDoUnlock/bDoProgress must be set to True here
	//AchievementsArray.Add((Id=EUTA_WEAPON_DontTaseMeBro,UnlockType=EAUT_Count,UnlockCriteria=4,ProgressCriteria=2,bDoUnlock=False,bDoProgress=False))
	//AchievementsArray.Add((Id=EUTA_WEAPON_StrongestLink,UnlockType=EAUT_Count,UnlockCriteria=4,ProgressCriteria=2,bDoUnlock=False,bDoProgress=False))
	//AchievementsArray.Add((Id=EUTA_WEAPON_HaveANiceDay,UnlockType=EAUT_Count,UnlockCriteria=4,ProgressCriteria=2,bDoUnlock=False,bDoProgress=False))
	//AchievementsArray.Add((Id=EUTA_VEHICLE_Armadillo,UnlockType=EAUT_Count,UnlockCriteria=4,ProgressCriteria=2,bDoUnlock=False,bDoProgress=False))
	//AchievementsArray.Add((Id=EUTA_POWERUP_DeliveringTheHurt,UnlockType=EAUT_Count,UnlockCriteria=60,ProgressCriteria=30,bDoUnlock=False,bDoProgress=False))
	//AchievementsArray.Add((Id=EUTA_HUMILIATION_SerialKiller,UnlockType=EAUT_Count,UnlockCriteria=1,ProgressCriteria=0,bDoUnlock=False,bDoProgress=False))
	//AchievementsArray.Add((Id=EUTA_HUMILIATION_OffToAGoodStart,UnlockType=EAUT_Count,UnlockCriteria=1,ProgressCriteria=0,bDoUnlock=False,bDoProgress=False))
	AchievementsArray.Add((Id=NEW_ACHIEVEMENT_1_0,UnlockType=EAUT_Count,UnlockCriteria=1,ProgressCriteria=0,bDoUnlock=True,bDoProgress=True))
	AchievementsArray.Add((Id=NEW_ACHIEVEMENT_1_1,UnlockType=EAUT_Count,UnlockCriteria=1,ProgressCriteria=0,bDoUnlock=True,bDoProgress=True))
}

Then I changed UTStatsReadAchievements:

defaultproperties
{
	ViewId=`STATS_GROUP_ACHIEVEMENTS

	ViewName="Achievements"

	// Column names for the table view
	//ColumnIds.Add(EUTA_EXPLORE_EveryMutator)
	//ColumnIds.Add(EUTA_WEAPON_DontTaseMeBro)
	//ColumnIds.Add(EUTA_WEAPON_StrongestLink)
	//ColumnIds.Add(EUTA_WEAPON_HaveANiceDay)
	//ColumnIds.Add(EUTA_VEHICLE_Armadillo)
	//ColumnIds.Add(EUTA_POWERUP_DeliveringTheHurt)
	//ColumnIds.Add(EUTA_HUMILIATION_SerialKiller)
	//ColumnIds.Add(EUTA_HUMILIATION_OffToAGoodStart)
	ColumnIds.Add(NEW_ACHIEVEMENT_1_0)
	ColumnIds.Add(NEW_ACHIEVEMENT_1_1)

	// Column metadata
	//ColumnMappings.Add((Id=EUTA_EXPLORE_EveryMutator,Name="EUTA_EXPLORE_EveryMutator"))
	//ColumnMappings.Add((Id=EUTA_WEAPON_DontTaseMeBro,Name="EUTA_WEAPON_DontTaseMeBro"))
	//ColumnMappings.Add((Id=EUTA_WEAPON_StrongestLink,Name="EUTA_WEAPON_StrongestLink"))
	//ColumnMappings.Add((Id=EUTA_WEAPON_HaveANiceDay,Name="EUTA_WEAPON_HaveANiceDay"))
	//ColumnMappings.Add((Id=EUTA_VEHICLE_Armadillo,Name="EUTA_VEHICLE_Armadillo"))
	//ColumnMappings.Add((Id=EUTA_POWERUP_DeliveringTheHurt,Name="EUTA_POWERUP_DeliveringTheHurt"))
	//ColumnMappings.Add((Id=EUTA_HUMILIATION_SerialKiller,Name="EUTA_HUMILIATION_SerialKiller"))
	//ColumnMappings.Add((Id=EUTA_HUMILIATION_OffToAGoodStart,Name="EUTA_HUMILIATION_OffToAGoodStart"))
	ColumnMappings.Add((Id=NEW_ACHIEVEMENT_1_0,Name="NEW_ACHIEVEMENT_1_0"))
	ColumnMappings.Add((Id=NEW_ACHIEVEMENT_1_1,Name="NEW_ACHIEVEMENT_1_1"))
}

Then I also changed UTStatsWriteAchievements :

defaultproperties
{
	ViewIds=(`STATS_GROUP_ACHIEVEMENTS)

	// Properties and their types
	//Properties.Add((PropertyId=EUTA_EXPLORE_EveryMutator,Data=(Type=SDT_Int32,Value1=0)))
	//Properties.Add((PropertyId=EUTA_WEAPON_DontTaseMeBro,Data=(Type=SDT_Int32,Value1=0)))
	//Properties.Add((PropertyId=EUTA_WEAPON_StrongestLink,Data=(Type=SDT_Int32,Value1=0)))
	//Properties.Add((PropertyId=EUTA_WEAPON_HaveANiceDay,Data=(Type=SDT_Int32,Value1=0)))
	//Properties.Add((PropertyId=EUTA_VEHICLE_Armadillo,Data=(Type=SDT_Int32,Value1=0)))
	//Properties.Add((PropertyId=EUTA_POWERUP_DeliveringTheHurt,Data=(Type=SDT_Int32,Value1=0)))
	//Properties.Add((PropertyId=EUTA_HUMILIATION_SerialKiller,Data=(Type=SDT_Int32,Value1=0)))
	//Properties.Add((PropertyId=EUTA_HUMILIATION_OffToAGoodStart,Data=(Type=SDT_Int32,Value1=0)))
	Properties.Add((PropertyId=NEW_ACHIEVEMENT_1_0,Data=(Type=SDT_Int32,Value1=0)))
	Properties.Add((PropertyId=NEW_ACHIEVEMENT_1_1,Data=(Type=SDT_Int32,Value1=0)))
}

Last but not least, I changed my custom player controller following the last tutorial, I just added this piece of code on the beginning of my player controller class:

/**
 * Initializes the object responsible for handling/tracking achievements
 */
function InitAchievementHandler()
{
	if (AchievementHandler != none)
		return;

	AchievementHandler = new(self) AchievementHandlerClass;

	if (AchievementHandler != none)
		AchievementHandler.Initialize();
}

/**
 * Unlocks the achievement on the client (can only be done clientside)
 *
 * @param AchievementId		The achievement to update (and possibly unlock)
 */
reliable client function ClientUpdateAchievement(int AchievementId, optional int Count=1)
{
	// Spectators don't get any
	//if (PlayerReplicationInfo.bOnlySpectator)
	//	return;

	if (AchievementHandler == none)
		InitAchievementHandler();

	if (AchievementHandler != none)
		AchievementHandler.UpdateAchievement(AchievementId, Count);
}

simulated event PostBeginPlay()
{
  Super.PostBeginPlay();
}

simulated event Destroyed()
{
    Super.Destroyed();
    
    if (AchievementHandler != none)
	{
		AchievementHandler.Cleanup();
		AchievementHandler = none;
	}
}

And on the end I added these 2 custom exec functions to test the achievement unlock:

exec function UnlockAchievement0()
{
  ClientUpdateAchievement(NEW_ACHIEVEMENT_1_0, 1);
}

exec function UnlockAchievement1()
{
  ClientUpdateAchievement(NEW_ACHIEVEMENT_1_1, 1);
}

DefaultProperties
{
    AchievementHandlerClass=Class'UTAchievements'
}

It is still not working, however, whenever I run these functions to unlock the achievement, I receive the error message UTAchievements Failed to read online achievement stats.

Please guys, before giving up achievements for my game, I need some help from more experienced udk users.

Thanks in advance.

I just found the function which outputs the error message. It is in the UTAchievementsBase.uc

/**
 * Callback which is triggered when the online subsystem finishes reading stats into the 'AchievementStatsRead' object
 *
 * @param bWasSuccessful	Whether or not the stats read was successful
 */
function ReadAchievementStatsComplete(bool bWasSuccessful)
{
	local int i, j, CurValue;

	if (!bWasSuccessful)
	{
		`log("UTAchievements: Failed to read online achievement stats");
		return;
	}

	// Read all the achievements (based on the 'AchievmentsArray' list) into the 'AchievementValues' array
	for (i=0; i<AchievementsArray.Length; ++i)
	{
		j = AchievementStatsRead.ColumnIds.Find(AchievementsArray[i].Id);

		if (j != INDEX_NONE)
		{
			if (AchievementStatsRead.GetIntStatValueForPlayer(PlayerReplicationInfo.UniqueId, j, CurValue))
			{
				j = AchievementValues.Length;
				AchievementValues.Length = j+1;

				AchievementValues[j].Id = AchievementsArray[i].Id;
				AchievementValues[j].Value = CurValue;
			}
		}
	}

	bInitializedAchievementValues = True;

	AchievementStatsRead = none;
	OnlineSub.StatsInterface.ClearReadOnlineStatsCompleteDelegate(ReadAchievementStatsComplete);


	// If there are any deferred calls to 'UpdateAchievement' pending, call them now
	for (i=0; i<DeferredAchievementUpdates.Length; ++i)
	{
		UpdateAchievement(DeferredAchievementUpdates[i].Id, DeferredAchievementUpdates[i].Value,
					i != (DeferredAchievementUpdates.Length-1));
	}

	DeferredAchievementUpdates.Length = 0;
}

But now I cant understand why the game is not being able to read the achievements, since I did setup everything correctly, or at least I think I have done everything correctly.

Just a thought occured to me now. Does UDK engine support the latest steam sdk? I am talking about my custom build of UDK, which is based on May 2011. I am using the latest steam sdk version, and I can’t do different, I am not going to use an outdated version of the steam sdk since it updates itself automatically and I need to ensure that my game runs smoothly on the steam client.

So maybe that’s the problem? My UDK build is not compatible with the latest steamworks?

I have seen this happens with UE4:

I haven’t tried implementing Steam achievements in my own game. From the looks of what you’ve done, it seems more complicated than I thought it would be.

I can tell you however that UDK most definitely does NOT support the latest Steamworks SDK. I had to make a lot of changes in C++ to use Steamworks. I think @Coldscooter wrote a custom dll to use Steamworks.

1 Like

Thanks my friend @Nathaniel3W, yeah, I imagined this, that udk does not support the latest Steamworks SDK, and the solution is to write a custom dll, which is far away from my limited knowledge. So I will pass by now, I won’t add achievements for my game. At the very least, I was able to setup a very simple split-screen multiplayer which allows 2 player playing online, a PvP match, through Steam Remote Play Together.

Thanks my friend for your ongoing support, and I am very excited, in the next few days my game will be fully released on Steam.

Cheers.

Although the Steam SDK included with UDK is very old, it still fully supports Steam Achievements and multiplayer connectivity (using Steam sockets).

I am using the native UDK implementation for advertising multiplayer games over the Steam API, joining, etc.

It is just the Steam Inventory service that I needed to include a separate DLL to use (which i use for weapon and clothing skins).

1 Like

Thanks my friend for answering me. But do you have an idea why this is not working with me? Neither the kismet online subsystem, neither going through the UTAchievements script classes. I just receive that error message ‘‘UTAchievements Failed to read online achievement stats’’.

Any help will be very appreciated.

Thanks.

I haven’t yet setup achievements in my game. I will be doing so soon-ish.

Are you sure you’ve added your correct app id in your steam_appid.txt in your root game folder?

Also, I’m pretty sure there is extra logging you can unsupress in the config to give you more details of network calls to the API.

1 Like

I can confirm achievements works correctly with UDK (even if the Steamworks SDK is old).
I think your issue is with your settings. You have

GameDir=unrealtest

If you use UDK (not UE3 full sources), you have to put here the GameDir defined in Steamworks.
Else, open OnlineSubsystemSteamworks.h and go on line 16: #define STEAM_PRODUCT_NAME TEXT(“YOUR_STEAM_PRODUCT_NAME”)

The product name is defined here: https://partner.steamgames.com/apps/dedicatedservers/STEAM_APPS_ID

1 Like

To UE3 licenses, you can update without trouble to the v1.46 26th July 2019 Steamworks SDK (I’m using it).

1 Like

Thanks my friend. Ok, I already uploaded my game to steam, and send it to their final review before the release.

But I will come back to add achievements as the first update for my game. I will try what you explained to me now. Thank you very much.