Unity SDK

Leaderboards

Submit and read scores by stable string key. Boards support sort direction, rotation schedules and global vs sticky-instance modes - all enforced server-side.

Overview

Identify boards with their dashboard key (e.g. "weekly_high_score"). Every method has a parallel …ById overload if you prefer the leaderboard's UUID.

Rotation & instances

Each leaderboard has a rotation schedule (manual, daily, weekly, monthly…). Every rotation cycle is stored as its own instance: when a board rotates the previous instance is marked closed (its scores are preserved forever) and a new open instance starts collecting submissions.

Players are sticky to the instance they first submitted to in a given cycle, so within a rotation a player always competes against the same field. The dashboard "Capacity" setting (e.g. top 100) is enforced per instance - older low-ranked scores are evicted as new players push in.

Note
Pass instanceId to GetScores / GetScoresAroundPlayer to read a specific past cycle. Without it you get the current open instance.

Dashboard

Open a leaderboard from Project → Leaderboards to get a dedicated page with three tabs:

  • Live - the current open instance, with paginated / top-N / range view modes and inline edit + delete on each score.
  • History - pick any closed instance from the dropdown to inspect its final standings (this is what your players see when they query GetLastClosedResult).
  • Stats - total scores, unique players, all-time best, and a per-instance volume chart so you can see how submissions trend across rotation cycles.

Listing boards

exampleC#
1var boards = await Leaderboards.List();
2foreach (var b in boards) Debug.Log($"{b.key}: {b.name}");

Submitting a score

exampleC#
1var result = await Leaderboards.Submit(
2 leaderboardKey: "weekly_high_score",
3 score: 12_500,
4 playerName: "Cipher",
5 metadata: new System.Collections.Generic.Dictionary<string, string> {
6 { "character", "ranger" }
7 }
8);
9if (result.success) Debug.Log($"Rank {result.rank}");
Note
playerId defaults to KalmForgeIdentity.PlayerId. Pass an explicit value only if you're submitting on behalf of another player from server code.

Reading scores

exampleC#
1var top10 = await Leaderboards.GetScores("weekly_high_score", limit: 10);
2var page2 = await Leaderboards.GetScores("weekly_high_score", limit: 10, offset: 10);
3
4// Read a specific past instance:
5var historic = await Leaderboards.GetScores("weekly_high_score", instanceId: "...");

Around the player

exampleC#
1var slice = await Leaderboards.GetScoresAroundPlayer(
2 "weekly_high_score", before: 5, after: 5
3);
4// Returns 11 entries centred on the calling player (or empty if no score yet).
5
6var mine = await Leaderboards.GetMyScore("weekly_high_score");

Rotation details

exampleC#
1var d = await Leaderboards.GetDetails("weekly_high_score");
2Debug.Log($"resets in {d.time_remaining_seconds}s, {d.current_player_count} players");

Player statistics

exampleC#
1var stats = await Leaderboards.GetPlayerStatistics("weekly_high_score");
2Debug.Log($"best #{stats.best_rank} (avg {stats.average_score:F1}) over {stats.total_rotations} weeks");

Last week's result & rewards

For "you placed Nth last week, here's your reward" flows, query the most recent closed instance the player participated in. The result includes their final rank, score, and whether they've already claimed a reward for it.

exampleC#
1// On app launch / main menu:
2var last = await Leaderboards.GetLastClosedResult("weekly_high_score");
3if (last.found && !last.claimed) {
4 // Show the "you placed #X with Y points last week!" UI
5
6 var claim = await Leaderboards.ClaimLastClosedReward("weekly_high_score");
7 if (claim.newly_claimed) {
8 GrantInGameReward(claim.rank, claim.score);
9 }
10}
Note
GetLastClosedResult is a read; ClaimLastClosedRewardatomically marks the reward as claimed. A player can only successfully claim each closed instance once - repeat calls returnalready_claimed = true.

Renaming the player

exampleC#
1bool ok = await Leaderboards.UpdatePlayerName("NewName");

Renames the player across every board and instance in the project. Call this once when the player picks or changes their display name.

API reference

Leaderboards - static API
NameTypeDescription
List()Task<List<LeaderboardInfo>>All boards configured for the project.
Submit(key, score, playerId?, playerName?, metadata?)Task<SubmitResult>Submit by stable key.
SubmitById(id, …)Task<SubmitResult>Submit by leaderboard UUID.
GetScores(key, limit=50, offset=0, instanceId?)Task<List<LeaderboardEntry>>Top entries for the current or a specific instance.
GetScoresById(id, …)Task<List<LeaderboardEntry>>Same, by id.
GetScoresAroundPlayer(key, before=5, after=5, playerId?, instanceId?)Task<List<LeaderboardEntry>>Window centred on the player.
GetMyScore(key)Task<LeaderboardEntry>Convenience: just the calling player's entry.
GetDetails(key, playerId?)Task<LeaderboardDetails>Rotation timing + counts. Pass playerId to scope to their sticky instance.
GetPlayerStatistics(key, playerId?)Task<PlayerStatistics>Best/worst/average across all past instances.
GetLastClosedResult(key, playerId?)Task<LastClosedResult>Final rank+score from the most recent closed instance the player was in.
ClaimLastClosedReward(key, playerId?)Task<LastClosedResult>Atomically claim the previous-instance reward exactly once.
UpdatePlayerName(newName, playerId?)Task<bool>Rename across every board & instance in the project.

REST endpoint

examplebash
1POST /api/public/sdk/leaderboards
2Headers: X-API-Key: kf_xxx_yyy
3
4# All actions go through one endpoint with an "action" field:
5{ "action": "submit", "leaderboard_key": "weekly_high_score",
6 "player_id": "...", "player_name": "Cipher", "score": 12500,
7 "metadata": { "character": "ranger" } }
8
9{ "action": "scores", "leaderboard_key": "...", "limit": 50, "offset": 0 }
10{ "action": "around_player", "leaderboard_key": "...", "player_id": "...", "before": 5, "after": 5 }
11{ "action": "details", "leaderboard_key": "...", "player_id": "..." }
12{ "action": "player_statistics", "leaderboard_key": "...", "player_id": "..." }
13{ "action": "update_player_name", "player_id": "...", "player_name": "..." }
14{ "action": "last_closed_result", "leaderboard_key": "...", "player_id": "..." }
15{ "action": "claim_last_closed_reward", "leaderboard_key": "...", "player_id": "..." }
16
17# GET to list:
18GET /api/public/sdk/leaderboards
Back to DocsKalmForge SDK · v1.0.1