Revision Difference
Leaderboards#563589
<cat>code.general</cat>
<title>Leaderboards</title>
# Creating a Leaderboard
Creating a leaderboard is really easy.
```
using Steamworks;
using Steamworks.Data;
...
var leaderboard = await SteamUserStats.FindOrCreateLeaderboardAsync( "MyLeaderboard",
LeaderboardSort.Ascending,
LeaderboardDisplay.Numeric );
```
Here you've created a leaderboard named "MyLeaderboard" which is sorted in ascending (highest first) and is number based (high score etc) rather than time based (fastest lap etc).
# Getting a Leaderboard
You can safely get a leaderboard with the same function. If you only want to get one that exists you can use:
```
var leaderboard = await SteamUserStats.FindLeaderboardAsync( "MyLeaderboard" );
```
<note>FindLeaderboardAsync and FindOrCreateLeaderboardAsync return a nullable. If for whatever reason the board cannot be found - it'll be null. This means you should check it first via `leaderboard.HasValue` and then the real leaderboard is in `leaderboard.Value`.</note>
# Submitting a Score
```
var result = await lb.SubmitScoreAsync( 576 );
```
This function will only replace your last score if the new one is better. On success (`result.HasValue`) this function will return a <page>Data.LeaderboardUpdate</page>.
You can force your score to be replace, even if it's worse, using:
```
var result = await lb.ReplaceScoreAsync( 576 );
var result = await lb.ReplaceScore( 576 );
```
# Getting Scores
```
// Get top 20 scores
var globalScores = await lb.Value.GetScoresAsync( 20 );
foreach ( var e in globalScores)
{
Console.WriteLine( $"{e.GlobalRank}: {e.Score} {e.User}" );
}
// Get scores from friends
var friendScores = await lb.Value.GetScoresFromFriendsAsync();
foreach ( var e in friendScores )
{
Console.WriteLine( $"{e.GlobalRank}: {e.Score} {e.User}" );
}
// Get scores around current user
var surroundScores = await lb.Value.GetScoresAroundUserAsync( -10, 10 );
foreach ( var e in surroundScores )
{
Console.WriteLine( $"{e.GlobalRank}: {e.Score} {e.User}" );
}⤶
⤶
```⤶
⤶
⤶
# Example⤶
⤶
```csharp⤶
⤶
using System;⤶
using System.Threading.Tasks;⤶
using Steamworks;⤶
using Steamworks.Data;⤶
using UnityEngine;⤶
⤶
public static class SteamLeaderBoardSystem⤶
{⤶
/// <summary>⤶
/// This function will only replace your last score if the new one is better.⤶
/// </summary>⤶
/// <param name="leaderboard"></param>⤶
/// <param name="value"></param>⤶
/// <param name="details"></param>⤶
public static async Task SubmitLeaderboard(Steamworks.Data.Leaderboard leaderboard, int value,⤶
int[] details = null)⤶
{⤶
var leaderboardUpdate = await leaderboard.SubmitScoreAsync(value, details ?? Array.Empty<int>());⤶
if (!leaderboardUpdate.HasValue)⤶
{⤶
Debug.LogError("leaderboardUpdate is null");⤶
return;⤶
}⤶
⤶
Debug.Log(leaderboardUpdate.Value);⤶
}⤶
⤶
⤶
/// <summary>⤶
/// Force your score to be replaced⤶
/// </summary>⤶
/// <param name="leaderboard"></param>⤶
/// <param name="value"></param>⤶
/// <param name="details"></param>⤶
public static async Task ReplaceLeaderboard(Steamworks.Data.Leaderboard leaderboard, int value,⤶
int[] details = null)⤶
{⤶
var leaderboardUpdate = await leaderboard.ReplaceScore(value, details ?? Array.Empty<int>());⤶
if (!leaderboardUpdate.HasValue)⤶
{⤶
Debug.LogError("leaderboardUpdate is null");⤶
return;⤶
}⤶
⤶
Debug.Log(leaderboardUpdate.Value);⤶
}⤶
⤶
⤶
public static async Task<Steamworks.Data.Leaderboard?> GetLeaderBoards(string lbName)⤶
{⤶
try⤶
{⤶
return await FindOrCreateLeaderboardAsync(lbName);⤶
}⤶
catch (Exception e)⤶
{⤶
Debug.LogError(e);⤶
}⤶
⤶
return null;⤶
}⤶
⤶
private static async Task<Steamworks.Data.Leaderboard?> FindOrCreateLeaderboardAsync(string leaderboardName)⤶
{⤶
try⤶
{⤶
return await SteamUserStats.FindOrCreateLeaderboardAsync(leaderboardName,⤶
LeaderboardSort.Ascending,⤶
LeaderboardDisplay.Numeric);⤶
}⤶
catch (Exception e)⤶
{⤶
Debug.LogError(e);⤶
}⤶
⤶
return null;⤶
}⤶
}
⤶
```⤶
```⤶
⤶
# Example usage of the example above⤶
⤶
```csharp⤶
⤶
public class SteamLeaderBoard : MonoBehaviour⤶
{⤶
private const string LeaderboardName = "MyLeaderboard";⤶
private Steamworks.Data.Leaderboard _lb;⤶
⤶
private async void Awake()⤶
{⤶
try⤶
{⤶
var lb = await SteamLeaderBoardSystem.GetLeaderBoards(LeaderboardName);⤶
if (lb.HasValue) _lb = lb.Value;⤶
else Debug.LogError("leaderboard did not have value");⤶
}⤶
catch (Exception e)⤶
{⤶
Debug.LogError($"Error loading leaderboards: {e.Message}");⤶
// Optionally, you could handle the exception, e.g., retry logic or fallback behavior⤶
}⤶
}⤶
⤶
#region TEST⤶
⤶
[ContextMenu("ReplaceScoreTest")]⤶
private void ReplaceScoreTest()⤶
{⤶
var entry = new LeaderboardEntry(1234.1829f, 12345789);⤶
ReplaceSpeedScore(entry);⤶
}⤶
⤶
#endregion⤶
⤶
#region ReplaceScores⤶
⤶
private void ReplaceSpeedScore(LeaderboardEntry entry)⤶
{⤶
_ = SteamLeaderBoardSystem.ReplaceLeaderboard(_lb, entry.TimeI, entry.Details);⤶
}⤶
⤶
#endregion⤶
}⤶
⤶
⤶
// Struct to hold data for ease-of-use and re-use-ability⤶
public struct LeaderboardEntry⤶
{⤶
public readonly int Score;⤶
public readonly int SomeOtherValue;⤶
public readonly int[] Details;⤶
⤶
public LeaderboardEntry(int score, int someOtherValue)⤶
{⤶
Score = score;⤶
SomeOtherValue = someOtherValue;⤶
Details = new[] { someOtherValue };⤶
}⤶
}⤶
```⤶