menu_bookDocumentation
Backend Services - Achievements, Leaderboards, Stats
Backend Services - Achievements, Leaderboards, Stats
Integrate Steam backend services for player progression, competition, and analytics.
Achievements
Track and award player accomplishments:
CSHARP
// Unlock an achievement
Sandbox.Services.Achievements.Unlock("first_win");
// Check if unlocked
bool hasAchievement = Sandbox.Services.Achievements.IsUnlocked("first_win");
// Get all achievements
var achievements = Sandbox.Services.Achievements.All;
foreach (var achievement in achievements)
{
Log.Info($"{achievement.Name}: {achievement.IsUnlocked}");
}Achievement Definition
Define achievements in your game settings:
- ID — Unique identifier (lowercase, no spaces)
- Name — Display name
- Description — What the player did to earn it
- Hidden — Secret until unlocked
- Icon — Unlocked/locked state images
Leaderboards
Rank players by score, time, or custom metrics:
CSHARP
// Submit a score
await Leaderboards.Submit("high_score", playerScore);
// Submit with replay data
await Leaderboards.Submit("speed_run", timeSeconds, replayData);
// Get top scores
var topScores = await Leaderboards.Get("high_score", 10);
foreach (var entry in topScores)
{
Log.Info($"{entry.Rank}. {entry.DisplayName}: {entry.Score}");
}
// Get player's friends scores
var friendScores = await Leaderboards.GetFriends("high_score");
// Get scores around player (centering)
var nearbyScores = await Leaderboards.GetCentered("high_score", 5);Leaderboard Types
| Type | Use Case |
|---|---|
| Numeric | High scores, points, kills |
| Time | Speed runs, lap times (lower is better) |
Filtering and Aggregation
CSHARP
// Filter by date
var thisWeek = await Leaderboards.Get("score", filter: LeaderboardFilter.ThisWeek);
// By country (ISO 3166-1 alpha-2)
var usScores = await Leaderboards.Get("score", country: "US");
// Aggregation methods
await Leaderboards.Submit("daily_best", score, aggregation: LeaderboardAggregation.Best);Stats
Track player and global statistics:
CSHARP
// Increment a stat (creates if doesn't exist)
await Stats.Increment("zombies_killed", 5);
// Set absolute value
await Stats.SetValue("total_playtime", hoursPlayed);
// Get current value
int kills = await Stats.GetValue("zombies_killed");
// Get global stats
var globalStats = await Stats.GetGlobal("total_matches_played");Auth Tokens
Secure API communication:
CSHARP
// Get auth token for web API calls
var token = await Auth.GetTokenAsync();
// Use with your backend
var response = await http.RequestJsonAsync($"https://myapi.com/userdata?token={token}");Tokens are:
- Unique per player
- Time-limited
- Verifiable against Steam
Web API
Access leaderboards from external services:
CODE
GET https://api.sbox.game/leaderboards/{org}.{game}/{leaderboard_id}
Authorization: Bearer {auth_token}Response:
JSON
{
"entries": [
{
"rank": 1,
"steam_id": "76561197991348132",
"score": 999999,
"timestamp": "2024-01-15T10:30:00Z"
}
]
}Best Practices
- Progressive achievements — Easy early wins, harder later
- Descriptive names — "Kill 100 Zombies" not "Zombie Hunter"
- Granular stats — Track everything, analyze later
- Handle failures — Services may be unavailable
- Batch operations — Submit stats in groups when possible
Rate Limits
- Achievements: 100 unlocks per minute
- Leaderboards: 10 submissions per minute
- Stats: 100 updates per minute
Was this helpful?