Leaderboards
Leaderboards is a service allowing you to provide player rankings dependent on their results in played matches.
Security and reliability is ensured thanks to server authoritative principle.
It makes reaching out to the community by organizing exciting events with prizes a real possibility, changing even single player games into real competetive exprience.
In order for leaderboards to work, it is important to end correctly finished matches with results, as shown in the example below (for a two players game).
private void FinishGame()
{
// Game finishing logic
{...}
if (Elympics.IsServer)
{
Elympics.EndGame(new ResultMatchPlayerDatas(new List<ResultMatchPlayerData>
{
// scoreManager.Score[i] is only an example of usage - it could be any value you want to store as a result
new ResultMatchPlayerData { MatchmakerData = new float[1] { scoreManager.Score[0] } },
new ResultMatchPlayerData { MatchmakerData = new float[1] { scoreManager.Score[1] } },
}));
}
}
Results are then saved in our database and used to calculate the ranking.
To retrieve this data inside your game, use LeaderbordClient
with desired scope parameters.
Result is stored in LeaderboardFetchResult
object containing list of LeaderboardEntry
objects.
Leaderboards work currently for every player individually - team leaderboards are not yet supported.
Each entry consists of:
- Elympics user ID
- Score
- Leaderboard position
- Date of scoring (only for best result type)
Custom nicknames or e-mail adresses are not stored in our database. In order to identify players and show their nicknames or contact for granting prizes, you should provide your own External Game Backend. In game, player identifying could also be done by displaying raw Elympics player IDs and highlighting which one represents the player. An alternative way could be deterministic nickname generation based on those IDs.
Scope parameters
There are currently two leaderboard types available:
BestResult
(great for competitive single player games)BestSumOfResults
- summing results for every match of every player in given scope (good for multiplayer matches as Elo ranking system, where you want to grant points for the winners and penalize the losing side with negative points)
Leaderboards are sorted in descending order, meaning that the greater score the better.
Leaderboards can be calculated using diverse time scopes (but it's best to stick to one as in the future possible time scopes for a given game will have to be predefined before usage):
AllTime
Month
(for last 30 days)Day
(for last 24h)Custom
(allows setting from-to dates, including timezone offsets)
Custom
time scope allows you to create timed events where after closing, top players may be granted prizes.
We don't support prize execution directly, but it may be a very good use case of our leaderboards service.
Providing External Game Backend is recommended in such case.
You can also reduce considered scope to chosen queue providing its name and to limited game version chosing between All
and Current
one provided in ElympicsConfig.
Usage in Unity
To use leaderboards service in your game use LeaderboardClient
object with desired scope parameters explained above.
It uses current Game Id from your ElympicsConfig to identify which game leaderboards to fetch.
Leaderboards are based on pages, meaning that you have to also specify how many entries you want to fetch at once.
LeaderboardClient
can be initialized as shown in the example below. Similar configuration is used by our endless runner template.
private LeaderboardClient leaderboardClient;
private void CreateLeaderboardClient()
{
var pageSize = 3; // Depends on display design - in this game we show top three and also player with his nearest neighbours
var queue = "Solo"; // Queues other than Default must be created in https://console.elympics.ai/ first
var gameVersion = LeaderboardGameVersion.All; // Worth changing to Current if new version contains important balance changes
var leaderboardType = LeaderboardType.BestResult; // Adjust to the type of game
var customTimeScopeFrom = "2023-07-07T12:00:00+02:00";
var customTimeScopeTo = "2023-07-14T12:00:00+02:00";
// Planned event lasts whole week, starting and ending at 12:00PM GMT+2 - only matches from that time will be taken into account
var timeScopeObject = new LeaderboardTimeScope(DateTimeOffset.Parse(customTimeScopeFrom), DateTimeOffset.Parse(customTimeScopeTo));
leaderboardClient = new LeaderboardClient(pageSize, timeScopeObject, queue, gameVersion, leaderboardType);
}
You can send requests using methods described below:
FetchFirstPage
- useful for displaying top players or for scrolling through the whole leaderboardFetchPageWithUser
- returns page where currently authenticated user can be foundFetchNextPage
,FetchPreviousPage
,FetchRefreshedCurrentPage
- used to further navigate through pages relatively to the last successfully fetched one
Those calls are handled asynchronously and do not return received values directly. Instead, you have to specify onSuccess
and optionally onFailure
callbacks each fetch request, which allows for flexible leaderboards displaying. If not specified, onFailure
logs an error.
An example usage provided below:
public void FetchMyPage() => leaderboardClient.FetchPageWithUser(LogEntries, CustomFailHandler);
private void LogEntries(LeaderboardFetchResult result)
{
var playerId = ElympicsLobbyClient.Instance.UserGuid.ToString();
foreach (var entry in result.Entries)
{
if (entry.UserId.Equals(playerId))
Debug.Log("Mine entry below!");
Debug.Log($"{entry.Position}. Score: {entry.Score} User: {entry.UserId} When: {entry.ScoredAt?.LocalDateTime}");
}
}
private static void CustomFailHandler(LeaderboardFetchError fetchError)
{
if (fetchError == LeaderboardFetchError.NoScoresForUser)
Debug.Log("You have to score at least once to be able to fetch your results!");
}
Error types are represented by LeaderboardFetchError
enum, consisting of:
UnknownError
NoRecords
PageLessThanOne
PageGreaterThanMax
NoScoresForUser
RequestAlreadyInProgress
NotAuthenticated
You can call only one request at the time so if you plan on making a more complicated leaderboards display, it's best to chain them using callbacks, similarly to the endless runner template. We recommend exploring it for better understanding of how leaderboards could be implemented and utilized in a real life scenario.
Current limitations
In most cases, Elympics user ID is generated using a client secret, randomized on first game start and then stored in system data. Note that upon reinstalling the game your ID will change, making it impossible to distinguish your current identity from the previous one - making two separate leaderboard entries for single user. There also won't be possibility to come back to the previous identity. To overcome this, you could use Eth Wallet which ensures continuity of Elympics user ID over various devices. An alternative is providing your own External Game Backend where you could handle such cases the way you want. For example you can log in by Google and connect one such account with each Elympics ID it encounters.
There is currently no way of two separate players logging in at a single device because Elympics ID won't be changed regardless of external login logic, it cannot be imposed. The only method of implementing such behaviour is using Eth Wallet login method.
Leaderboards Sample
By Unity Package Manager you can import various Elympics Samples, including "Leaderboard test" which allows you to go through basic implementation and showcase its capabilities.
If your game doesn't have any match results recorded, feel free to temporarily change your Game Id to another one - for example 9e806e1a-4f6b-4ad8-b93c-7e9d9ce9bd05
which represents our Template Run.
Use Tester
Game Object to change leaderboard parameters and available canvas buttons to navigate through it.
Remember that every runtime change have to be finalized by Apply Leaderboard Client changes
button in order work properly.