Leaderboards - Code
Allow player to manage a leaderboard with animated text [SOCL-Leaderboards-03]
Variations On A Theme
Choose the Leaderboard setup that works best for your needs;
• Leaderboard (Standard) - Shows non-animated score values. See Leaderboards - Guide for more info
• Leaderboard (With Interpolation) - Shows animated score values. See Leaderboards - Code for more info
The purpose of this guide is for game makers to setup a Leaderboard with interpolation.
Here, "interpolation" refers to a Leaderboard with animated score
text. The score value rises creating excitement in games with rapidly changing scores.
The User Interface
When set up properly, the player's user interface in the game project will be as follows:
Animated Screenshot
Steps
Follow these steps to get started:
Step | Detail |
---|---|
1. Setup a traditional "Leaderboard Flow" Prefab | • See Leaderboards - Guide for more info |
2. Submit Leaderboard Score w/ Additional Stats | • See Send Score below |
3. Render Leaderboard Score w/ Additional Stats | • See Render Score below Note: The provided example is built on top of the existing "Leaderboard Flow" Prefab. This has limited flexibility. Depending on the needs of the project, game makers may choose instead to build a custom Leaderboard UI from scratch. In either case the provided example serves as a useful model |
Example
Here are examples which cover common programming needs.
Beamable SDK Examples
• The following example code is available for download at GitHub.com/Beamable_SDK_Examples
Code
Submit Score
Here is a snippet from LeaderboardFlowInterpolationExample.cs
;
private async void SetupBeamable()
{
_beamContext = BeamContext.Default;
await _beamContext.OnReady;
Debug.Log($"_beamContext.PlayerId = {_beamContext.PlayerId}");
LeaderboardContent leaderboardContent =
await _leaderboardMainMenuCustom.LeaderboardBehavior.Leaderboard.Resolve();
Debug.Log($"PopulateLeaderboard Starting. Wait < 30 seconds... ");
int leaderboardRowCountMin = 10;
int leaderboardScoreMin = 99;
int leaderboardScoreMax = 99999;
// Populate with custom values
Dictionary<string, object> leaderboardStats = new Dictionary<string, object>();
leaderboardStats.Add("leaderboard_score_timestamp", new
DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds());
leaderboardStats.Add("leaderboard_score_velocity", 99); // 99 score delta per second
// Populates mock "alias" and "score" for each leaderboard row
string loggingResult = await MockDataCreator.PopulateLeaderboardWithMockData(
_beamContext,
leaderboardContent,
leaderboardRowCountMin,
leaderboardScoreMin,
leaderboardScoreMax,
leaderboardStats);
Debug.Log($"PopulateLeaderboard Finish. Result = {loggingResult}");
}
Render Score
Here is a snippet from LeaderboardItemCustom.cs
;
public void Update()
{
// Prepare value
long scoreTimestamp = long.Parse(_rankEntry.GetStat("leaderboard_score_timestamp"));
long scoreVelocity = long.Parse(_rankEntry.GetStat("leaderboard_score_velocity"));
long currentTimestamp = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
long millisecondsSinceSubmission = currentTimestamp - scoreTimestamp;
long scoreSinceSubmission = (millisecondsSinceSubmission * scoreVelocity) / 1000;
// Render value
double score = _rankEntry.score + scoreSinceSubmission;
TxtScore.text = $"{score:00000}";
}
Get Board
When calling either GetBoard
or GetAssignedBoard
, the parameters share the following semantics:
leaderBoard
/boardId
: The board whose subset of rank entries you want to retrieve.- For the partitioned case (
GetAssignedBoard
), it'll always return you the partition containing the requesting/authenticated user.
- For the partitioned case (
from
: Is the first "rank" you want to retrieve. This parameter is ignored if afocus
is given.- If this value is greater than the lowest rank, you'll get no
RankEntries
back: if there are 10 entries in the board and you pass infrom=15
, you'll get an empty array ofRankEntries
in yourLeaderBoardView
.
- If this value is greater than the lowest rank, you'll get no
max
: Is the number of ranks, starting fromfrom
, and moving towards the lowest rank that you want to retrieve.- As in, if
from=20
andmax=10
, you'll get ranks[20~30]
. - If there are not enough entries to fill this amount, the search is truncated.
- As in, if
focus
: is a User's PlayerId that'll be used as the middleRankEntry
of the resultingLeaderBoardView
.- Takes
max/2
ranks above thefocus
andmax/2
ranks from below thefocus
. - It is inclusive. As in, if
focus
is at rank 50 and you pass inmax=10
, you should see[40~61]
. - If there are not enough entries in the leaderboard either above or below you, the corresponding
max/2
will be truncated.
- Takes
outlier
: A GamerTag whoseRankEntry
is guaranteed to be included. When this is passed in, the resulting entry is stored inLeaderBoardView.rankgt
.
Here is a snippet from LeaderboardServiceExample.cs
;
private async Task<List<RankEntry>> LeaderboardServiceGetBoard(string id, long userId)
{
LeaderBoardView leaderBoardView = await _beamContext.Api.LeaderboardService.GetBoard(id, 0, 100,
userId);
foreach (RankEntry rankEntry in leaderBoardView.rankings)
{
// Get alias for userId of rankEntry
long nextUserId = rankEntry.gt;
var stats =
await _beamContext.Api.StatsService.GetStats("client", "public", "player", nextUserId );
string alias = "";
stats.TryGetValue(alias, out alias);
if (string.IsNullOrEmpty(alias))
{
alias = "Unknown Alias";
}
// Log
Debug.Log($"Rank = {rankEntry.rank}, Alias = {alias}, Score = {rankEntry.score}");
}
return leaderBoardView.rankings;
}
Updated about 1 month ago