Oculus Quest Development

All Oculus Quest developers MUST PASS the concept review prior to gaining publishing access to the Quest Store and additional resources. Submit a concept document for review as early in your Quest application development cycle as possible. For additional information and context, please see Submitting Your App to the Oculus Quest Store.

Leaderboards

Note: You are viewing the Unity version of this topic. To view this topic for native development, see Leaderboards (Native). To view this topic for Unreal development, see Leaderboards (Unreal).

Leaderboards provide a way for a game to keep track of players and their scores in relation to other. Leaderboards can help create competition and increase engagement among your users.

For example, in a racing game, for a specific track you might have a leaderboard for the fastest lap time, sorted by lowest time, and a leaderboard for the most number of wins, sorted by the largest value. A game may have many different leaderboards.

The Oculus Platform manages the leaderboard data, however, you will be responsible for displaying, reporting, and verifying the leaderboard data in your app.

To manage leaderboards, Oculus offers:

See the Implement section for steps to add a leaderboards to your apps.

You can optionally choose to make leaderboards user-facing, meaning a user can see their rank compared to friends and other users in the Oculus app. You can also choose to have notifications automatically generated when a user passes a friend’s leaderboard score.

The following image shows a user-facing leaderboard.

user facing leaderboard

Define a Leaderboard on the Developer Dashboard

The first step in adding leaderboards to your game is defining them in the developer dashboard. Navigate to Leaderboards and select the app that you would like to create a leaderboard for.

Select Create Leaderboard and enter the following information:

  • API Name - This is the unique string that you will allow you to reference this leaderboard in your app code. The API Name is case-sensitive, the name you define in the Dashboard must exactly match the name you reference in your code.
  • Sort Order - There are two options for Sort Order depending on your use-case:
    • Higher is Better will rank users in descending order, from highest to lowest score.
    • Lower is Better will rank users in ascending order, from lowest to highest score.
  • Enter a Title for your leaderboard that will display publicly.
  • If you have localized your app into multiple languages, use the Modify Languages button to select additional languages, and enter the localized Title for the leaderboard in each language you choose.
  • Finally, to enable social features for the leaderboard, use the sliders to opt in. You can:
    • Add a Deep Link Destination, which means when a user clicks on the leaderboard, they will be taken to the in-app destination that you specify. For more information about destinations, see Destinations and Rich Presence.
    • Choose to have the leaderboard user facing, meaning a user that owns your app can see their rank on a leaderboard in the Oculus app.
    • You can also choose to have Friend surpassed notifications if the leaderboard is user-facing. This means notifications are sent by Oculus to a user when a friend passes their score.

Select Submit when finished to save the leaderboard.

You can update leaderboard settings at any time in the Developer Center. You may also clear the results in a leaderboard and reset the scores.

Leaderboard Best Practices

To help increase engagement with your leaderboards, follow these best practices:

  • Set a user-friendly display title for the leaderboard in addition to the API name.
  • To reach a broader market, provide translations for your display title.
  • Make sure your leaderboard is public by checking the toggle on the leaderboard page if you want Oculus to provide notifications and social stories for this leaderboard
  • Create a destination for the leaderboard, and associate it with your leaderboard. If you provide a destination, you can deep link users directly into the right level of your app, to jump into the action and challenge a friend’s leaderboard score that they’ve just seen at the platform level.

Edit a Leaderboard

You can edit any of a leaderboard’s properties except its API Name. This means you can add translations and social feature after you have created it. To edit a leaderboard:

  • Go to the Developer Dashboard > Manage > [Your App] > Platform Services > Leaderboards
  • Click the ellipses (...) button on the right hand side of the leaderboard you want to edit and choose View/Edit Details
  • Make the desired changes, such as adding languages and localized titles or enabling social features.
  • Click Submit to save the changes.

The following image shows an example of the Edit Leaderboard page.

create leaderboard

Leaderboard Client APIs

Once you’ve finished creating the leaderboards in the dashboard, you can begin to integrate them in your game or app. When you call the functions in this section use the Leaderboard API Name you defined in the developer dashboard.

A leaderboard contains an array of leaderboard entries, and a leaderboard entry represents one users score and rank in a particular leaderboard.

Details about each function that follows can be found in the Leaderboard Requests Reference .

Retrieve a list of leaderboard entries

This method retrieves an array of leaderboard entries for a specified leaderboard.

Platform.Leaderboard.GetEntries()

If no error occurred, the result will contain an array of leaderboard entries.

Retrieve a list of leaderboard entries after a rank

This method retrieves a list of entries starting after a rank that you define. For example, if you specify a list with an ‘afterRank’ of 10, you’ll get a list starting with the 11th position.

Platform.Leaderboard.GetEntriesAfterRank()

If no error occurred, the result will contain an array of leaderboard entries after the rank you specify.

Retrieve the next list of entries

This method retrieves the next group of leaderboard entries. This can be used to paginate the leaderboard data.

Platform.Leaderboard.GetNextEntries()

If no error occurred, the message will contain an array of leaderboard entries.

Retrieve the previous list of entries

This method retrieves the previous group of leaderboard entries. This can be used to paginate the leaderboard data.

Platform.Leaderboard.GetPreviousEntries()

If no error occurred, the result will contain an array of leaderboard entries.

Write a leaderboard entry

This method will write a new leaderboard entry to a specified leaderboard for the current user. It is not an incremental update, it will overwrite the existing entry.

Platform.Leaderboard.WriteEntry()

If no error occurred, the result will contain a leaderboard status.

Get the total number of leaderboard entries

Use this method to get the total number of entries in the leaderboard so that you can show a users rank within the total number of entries. For example, use this method to display that a user is number 50 out of 200 entries.

Platform.LeaderboardEntryList.TotalCount

Returns an unsigned long that specifies the total count of leaderboard entries.

Get a block of leaderboard entries for specified user(s)

Request a block of leaderboard entries for the specified user ID(s) for viewing by this client. Use this method to get rankings for users that are competing against each other. You specify the leaderboard name and whether to start at the top, or for the results to center on the (client) user. Note that if you specify the results to center on the client user, their leaderboard entry will be included in the returned array, regardless of whether their ID is explicitly specified in the list of IDs.

If no error occurred, the result will contain an array of leaderboard entries.

Implement a Leaderboard

To implement leaderboards, there are two different processes.

  • Retrieve and Display Leaderboards - Display the current leaderboard state before a game begins. Use Platform.Leaderboards.GetEntries for Unity. There are other methods you can use to get a subset of leaderboard entries based on input criteria.

  • Update Leaderboard Entries - Write the results of the current game to your leaderboard. Use Platform.Leaderboards.WriteEntry for a Unity app. A user may only have one entry on each leaderboard, subsequent entries will overwrite the existing entry on the specified leaderboard.

Implementation Tips

When implementing leaderboards, there are two common scenarios you should be aware of. They are:

  • To retrieve leaderboard entries centered around the current user, use the LeaderboardStartAt enum to define where the values returned start or are centered. To retrieve only the current user, center on the viewer and limit results returned to 1.
  • To return only the user’s friends, you can use the LeaderboardFilterType enum to define the results returned.

Example Implementation - Unity

The following Unity example demonstrates retrieving information from a leaderboard called 'MOST_MATCHES_WON' and writing a new leaderboard entry after a win for the current user. The following example is taken from the VRHoops sample app. See the full sample in the Oculus Integration Package . For more information about samples, see the Sample Apps page.

using UnityEngine;
using System.Collections.Generic;
using Oculus.Platform;
using Oculus.Platform.Models;

// Coordinates updating leaderboard scores and polling for leaderboard updates.
public class LeaderboardManager
{
    // API NAME for the leaderboard where we store how many matches the user has won
    private const string MOST_MATCHES_WON = "MOST_MATCHES_WON";

    ///...

    // the top number of entries to query
    private const int TOP_N_COUNT = 5;

    // how often to poll the service for leaderboard updates
    private const float LEADERBOARD_POLL_FREQ = 30.0f;

    // the next time to check for leaderboard updates
    private float m_nextCheckTime;

    ///...

    // whether we've found the local user's entry yet
    private bool m_foundLocalUserMostWinsEntry;

    // number of times the local user has won
    private long m_numWins;

    // callback to deliver the most-wins leaderboard entries
    private OnMostWinsLeaderboardUpdated m_mostWinsCallback;

    ///...

    public void CheckForUpdates()
    {
        if (Time.time >= m_nextCheckTime &&
            PlatformManager.CurrentState == PlatformManager.State.WAITING_TO_PRACTICE_OR_MATCHMAKE)
        {
            m_nextCheckTime = Time.time + LEADERBOARD_POLL_FREQ;

            QueryMostWinsLeaderboard();
            QueryHighScoreLeaderboard();
        }
    }

    #region Most Wins Leaderboard

    public delegate void OnMostWinsLeaderboardUpdated(SortedDictionary<int, LeaderboardEntry> entries);

    public OnMostWinsLeaderboardUpdated MostWinsLeaderboardUpdatedCallback
    {
        set { m_mostWinsCallback = value; }
    }

    void QueryMostWinsLeaderboard()
    {
        // if a query is already in progress, don't start a new one.
        if (m_mostWins != null)
            return;

        m_mostWins = new SortedDictionary<int, LeaderboardEntry>();
        m_foundLocalUserMostWinsEntry = false;

        Leaderboards.GetEntries(MOST_MATCHES_WON, TOP_N_COUNT, LeaderboardFilterType.None,
            LeaderboardStartAt.Top).OnComplete(MostWinsGetEntriesCallback);
    }

    void MostWinsGetEntriesCallback(Message<int, LeaderboardEntry> msg)
    {
        if (!msg.IsError)
        {
            foreach (LeaderboardEntry entry in msg.Data)
            {
                m_mostWins[entry.Rank] = entry;

                if (entry.User.ID == PlatformManager.MyID)
                {
                    m_foundLocalUserMostWinsEntry = true;
                    m_numWins = entry.Score;
                }
            }

            // results might be paged for large requests
            if (msg.Data.HasNextPage)
            {
                Leaderboards.GetNextEntries(msg.Data).OnComplete(MostWinsGetEntriesCallback);
                return;
            }

            // if local user not in the top, get their position specifically
            if (!m_foundLocalUserMostWinsEntry)
            {
                Leaderboards.GetEntries(MOST_MATCHES_WON, 1, LeaderboardFilterType.None,
                    LeaderboardStartAt.CenteredOnViewer).OnComplete(MostWinsGetEntriesCallback);
                return;
            }
        }
        // else an error is returned if the local player isn't ranked - we can ignore that

        if (m_mostWinsCallback != null)
        {
            m_mostWinsCallback(m_mostWins);
        }
        m_mostWins = null;
    }

    #endregion

    // submit the local player's match score to the leaderboard service
    public void SubmitMatchScores(bool wonMatch, uint score)
    {
        if (wonMatch)
        {
            m_numWins += 1;
            Leaderboards.WriteEntry(MOST_MATCHES_WON, m_numWins);
        }

        if (score > 0)
        {
            Leaderboards.WriteEntry(HIGHEST_MATCH_SCORE, score);
        }
    }
}

Server to Server APIs

You may need to manipulate a leaderboard from your trusted server. For details on leaderboard server-to-server APIs, see Leaderboard Server to Server APIs.