Design

Key Leaderboard design features: 

  • Rank players against each other based on the score your event returns.

  • Can be limited to social-graph-only (just friends) or global (all entrants). 

  • Can be configured to reset daily, weekly, monthly, yearly or never. 

  • Are a core component of Tournaments, which enable your app to issue prizes to players based on their leaderboard rank. 

Design Ideas: 

  • Weekend or Weeklong Leaderboards encourage frequent logins and boost engagement without forcing onerous participation for a player to remain competitive. 

  • A lifetime leaderboard encourages long-form play for your most engaged users to be the best ever.

  • Attaching a Tournament Template to a leaderboard allows your app to issue prize payouts at the end of a tournament period.

UI considerations:
When implementing Leaderboards for your game your UI team should consider implementing:

  • A Leaderboard List 

  • A Rank Widget

A Leaderboard List:

  • Leaderboard Title 

  • Rank column

  • Highlighted player row

  • (Optional) Player banner or social graph picture

  • Player nickname

  • (Optional) Player's guildname or clanname

  • Score being tracked

  • (Optional) Means to page up or down to other entries in the list

  • (Optional) Means to duel a rival (if game is one-on-one)

  • Time remaining

  • (Optional) Tab or paging buttons to view other leaderboards, if available

  • Means to depart the screen

  • (If part of a Tournament) A means to view the associated prize table  

A UI Widget:
The goal of a UI widget is to surface the competitive information to a player and give the means to access the Leaderboard list. The Widget should be small enough to fit on a main menu or pregame screen. 

  • Rank 

  • Time Remaining

  • Means to advance to the full leaderboard list

Implementation

Advance to Design | Leaderboards | Leaderboard Configs
To create a new Leaderboard Click the [+] button. 

The Leaderboard Configuration panel will open.

  • Enter a unique Leaderboard ID with no spaces or special characters. The id is used when posting to and querying the leaderboard. 

  • Select Entry Type. 

Player - This is the most common selection and allows your players to directly compete based on the scoring metric you define.
Group - If your users will be assembled into groups the leaderboard can be configured to aggregate their results into a group score. This is excellent for tournaments with scoring conditions like Cumulative Wins over a weekend.

  • Select Leaderboard Type.

  1. High Value – The score is only posted if it is higher than the player's previously posted score. Used for a typical high score leaderboard. For example, a High-Jumping contest is ranked on only the user's highest jump. 

  2. Cumulative – The posted score is added to the current score. Use this to rank players on the total accumulation of scores over the tournament period. For example, a Leaderboard that tracks who can collect the most Coins over a weekend would be Cumulative.  

  3. Last Value – Each time the player posts a score, it overwrites their previous score. This method is used rarely by design because it may create a disincentive to play after posting a good score. 

  4. Low Value – It is the opposite of High Value. The score is only posted if it is lower than the player's previously posted score. Used for a typical low score leaderboard.

Pro tips: 

  • Hard-core players prefer High-Value leaderboards in skill-based contests with a minimal luck. 

  • Casual players prefer Cumulative leaderboards because it allows them to climb ranks through devotional play. Cumulative tournaments have a greater tendency to drive monetization. 

  • Last Value leaderboards create a Push-Your-Luck mechanic that is used in specific design circumstances. 

Select the Rotation Type

  • Never - Set this for lifetime leaderboards. 

  • Daily - This is useful for high volatility events that happen frequently. For example, this would be good in a Casino App for "Highest Spin of the Day" to promote how well-paying the slot machines are. 

  • Days - Use this option if you want to set up a Weekend Tournament. 

  • Weekly - An excellent choice for group events or Casual player events such as Most Points Earned This Week

  • Monthly - Another good option to give fame and praise to your most loyal users as they are most likely to bubble up to the top of this leaderboard. 

  • Yearly - This can be useful to showcase the top score of the year, and is a good way to give new long-term players a chance to get on top of a prestigious board. 

  • Ad Hoc Tournaments - (Advanced) Allows the admin to configure one-off tournaments with arbitrary start times. Useful for live events

If you select a rotation type that is recurring, then set, 

  • Next Rotation at (Local) date and time - Note: This is not necessarily the Start time for the competition. This setting will control when the event is announced to the player (if set), and when enrollment for the tournament is allowed to begin.   

Indicate the number of rotations to save
In the case that a participant competes but does not return to claim his prize, this setting controls how many tournaments must pass before the user's payout is abandoned. A good value is 3. 

If this Leaderboard will be used in a Tournament, Check the With Tournaments checkbox. This will make it available to be set in the Tournament Template panel. This will add a Tournament Periods tab to the panel.

If this Leaderboard will be used in a Tournament with Divisions (Advanced), also check the Division Template checkbox. This will make the Leaderboard visible in the Division Set Configuration menu. 

If you have configured Pacers in Design | Leaderboards | Pacers and you wish to add them to this leaderboard, select the pacers tab.  

Enable the pacers you wish and set the scores they will display for this leaderboard. 

Select [ Apply ] to save your changes.

Adding Settings to the Tournament Periods Panel

Select the Tournament period date entry.

After selecting the date, a small lock icon will appear on the right. Click to unlock it.

Note: When a recurring tournament is selected the Period Start is configured in the Leaderboard Settings panel. The Period End is configured in the Phases Tab. Therefore, in the case or recurring tournaments, the Period panel is read-only. 

Select the Tournament Tab. 

Select the [+] in the Tournaments widget. Select a Tournament Template from those you have configured for this project. 

If your entry cost is free, you may choose the Auto Join checkbox. This will automatically add users as soon as they post a score event to this leaderboard. 

Auto Claim

The auto claim is a convenience feature provided to developers that automatically awards Tournament prizes to players upon login. This makes it easy to establish Tournaments for games, however, it does not inform the player of why they got a payout. Not informing the player the reason for the boon limits the sense of pride and accomplishment the player will feel for demonstrating mastery in the game. For this reason, it is recommended that apps only use this as an interim feature while the UI team develops a payout dialog that triggers on login and declares the reasons for the boon. 

Sample payout dialog

Containing:

  • Label

  • Tournament Title 

  • Win condition

  • Rank

  • Score

  • Reward

  • Claim

  • (recommended) Flourish/payout effect when a claim is pressed

Setting Phases

Use the (i) to view additional information on the definition of each phase. 

  • Announcement Period - Use if you want to hype players up well in advance of the competition. For example to let players know an event is coming "this weekend". 

  • Enrollment Period - Use if you want to permit players to enroll before the competition starts. This may not be necessary if the competition is based on multiple play sessions' worth of performance, such as a Weekend Cumulative or Week-long Top Score tournament. 

  • Competition Duration - This value is automatically calculated, based off the recurrence you have set and the various amounts of time deducted by other phases. 

  • Disallow Enrollment for final - Prevent players from joining a tournament once they do not have enough time to post a competitive score. In the case of Free tournaments, this value should be zero to five minutes. In the case of Paid tournaments this may be minutes to hours, depending on your design. 

  • Buffer for Final Scores - Allows players in rounds to finish and submit scores while also preventing new players from starting rounds eligible to score. This should be long enough to accommodate two average rounds of play. 

After making changes, it is advised to click the refresh button to display fresh Day/Time data for your analysis.

When done, click [Apply Period Changes], then select [Save & Close].


Writing the code

With a leaderboard config, you will want to query those items and post scores to them with your app.

In your client code

  • Add the brainCloud client to your app.

  • Pair the client with the dashboard.

  • Authenticate your user into brainCloud.

  • Request a list of leaderboard with the ListAllLeaderboards call.

  • Pick on of those leaderboards and query the top 50 scores.

  • Post a new score to that leaderboard which is 5 higher than the current leading score.

  • Review other leaderboard related calls for your app in the API Reference.

void Start() {
    // Unity
    GameObject go = new GameObject();
    _bc = go.AddComponent<BrainCloudWrapper>();
    _bc.WrapperName = _wrapperName; // optionally set a wrapper-name
    _bc.Init(); // extra data, such as: _appId, _secret and _appVersion, is taken from the brainCloud Unity Plugin.
    DontDestroyOnLoad(go); // keep the brainCloud game object through scene changes
 
    _bc.Client.EnableLogging(true);
   
    _bc.AuthenticateAnonymous((response, cbObject) =>
    {
        GetLeaderboards();
    });
}


List<string> leaderboardIds = new List<string>();
public void GetLeaderboards()
{
    _bc.LeaderboardService.ListLeaderboards((response, cbObject) =>
    {
        var jsonMessage =
            (Dictionary<string, object>) BrainCloud.JsonFx.Json.JsonReader.Deserialize(response);
        var jsonData = (Dictionary<string, object>) jsonMessage["data"];
        var leaderboardList = (Dictionary<string, object>[]) jsonData["leaderboardList"];

        // Let's grab a list of leaderboard ids
        foreach (var leaderboard in leaderboardList)
        {
            var leaderboardId = leaderboard["leaderboardId"].ToString();
            leaderboardIds.Add(leaderboardId);
        }

        GetTopScores();
    });
}

int highestPlayerScore = 0;
private string selectedLeaderboard = "";
public void GetTopScores()
{
    // Let's select a random leaderboard id from the previous GetLeaderboards call
    var random = new System.Random();
    selectedLeaderboard = leaderboardIds[random.Next(leaderboardIds.Count)];
   
    var sortOrder = BrainCloudSocialLeaderboard.SortOrder.HIGH_TO_LOW;
   
    // Let's grab the first 50 leaderboard entries
    var startIndex = 0;
    var endIndex = 50;
   
    _bc.LeaderboardService.GetGlobalLeaderboardPage(
        selectedLeaderboard,
        sortOrder,
        startIndex,
        endIndex,
        (response, cbObject) =>
        {
            var jsonMessage =
                (Dictionary<string, object>) BrainCloud.JsonFx.Json.JsonReader.Deserialize(response);
            var jsonData = (Dictionary<string, object>) jsonMessage["data"];

            if (typeof(Dictionary<string, object>[]) == jsonData["leaderboard"].GetType())
            {
                var leaderboard = (Dictionary<string, object>[]) jsonData["leaderboard"];

                // If there is at least one entry
                if (leaderboard.Length > 0)
                {
                    // Let then grab the score from that first place entry
                    var firstPlaceEntry = leaderboard[0];
                    var score = int.Parse(firstPlaceEntry["score"].ToString());
                    highestPlayerScore = score;
                }
            }
        });
}

void PostNewHighScore()
{
    // Let's post a score higher than the current high score
    var higherPlayerScore = highestPlayerScore + 5;
   
    // We can also attach any extra data onto the score
    var extraData = BrainCloud.JsonFx.Json.JsonWriter.Serialize(new Dictionary<string, object>
    {
        {"message","Bested previous highscore by five points!"}
    });

   
    _bc.LeaderboardService.PostScoreToLeaderboard(
        selectedLeaderboard,
        higherPlayerScore,
        extraData);
}


Did this answer your question?