Part 1 - Define achievements in Steamworks
In Steamworks, go to your app → Technical Tools → Edit Steamworks Settings → Stats & Achievements → Achievements. Click New Achievement.
API Name is the string your code uses, like ACH_FIRST_WIN. Pick a consistent scheme and never change it after release, since changing it orphans player progress. Display name and description are what players see. Tick Hidden for story spoilers; hidden achievements show as "hidden" until unlocked.
Each achievement needs an achieved icon (full colour) and an unachieved icon (usually a greyed version), 64 × 64 px JPG or PNG. Tip: design one set in colour and batch-desaturate copies for the locked versions.
Achievements live in the unpublished change set until you push them via the Publish tab. Nothing works in-game before publishing. After publishing, the achievement count appears on your store page automatically.
Part 2 - Trigger them from your game
With Steamworks.NET in Unity (Facepunch.Steamworks is similar), the pattern is request stats once, set the achievement, then store:
// After SteamAPI initialises (e.g. SteamManager in scene)
using Steamworks;
public static class Achievements
{
public static void Unlock(string apiName)
{
if (!SteamManager.Initialized) return;
SteamUserStats.SetAchievement(apiName); // e.g. "ACH_FIRST_WIN"
SteamUserStats.StoreStats(); // commits to Steam, shows the popup
}
}
// Somewhere in gameplay:
Achievements.Unlock("ACH_FIRST_WIN");
Steam shows the overlay notification the moment StoreStats succeeds. Don't call StoreStats every frame; once per unlock or on save is enough.
Part 3 - Test and reset
Run the game through Steam (or with steam_appid.txt beside the executable in development). Unlocks are real, so you'll want to reset between tests.
Call SteamUserStats.ResetAllStats(true) from a debug key, or use the reset option in the Steamworks SDK's test tools. Keep the debug key out of release builds.