Hi,
There is already a few highscore/leaderboard system option around there, but they always missed something to me. So I did write a little leaderboard system for my current project. As other, i did choose to go with php/sql on the server side, which allow the leaderboard to be used on a lot of platforms/webhosting. To be clear: you’ll need a website running php and sql.
I would need a few interested people to try it and find flows, since it’s hard to handle all the possible situation alone. I’ll try to explain the main functions/usage of my system below. It’s written in C# but since it use “callback” (SendMessage) it should be easy to use in JS. The system would maybe make it’s way to Asset Store for less than 10$, but it’s still not sure, and people willing to help will get it for free of course…
-
One of the main goal of this project was to be able to transparently save/retrieve the user highscore irrespective of network access: the system will always save the user score locally, and so will automatically retrieve his highscore locally if the network is down or the request failed. In a same way, if a locally stored highscore was not saved online, it will be automatically updated online when possible. Well, so you’ll just have to use “GetScore”, “AddScore”, then you’ll automatically get/set what’s possible.
-
User authentication is done via username/password. I did choose this sort of implementation because it’s the only possibility i see to be able for the user to change device (phone, desktop computer…) without loosing access to his highscores. The nice thing is the user informations are handled by the system. You’ll just have to ask one time the user for a login/password, then all will be saved. But if you (the user) is not authenticated, then highscores will be saved/retrieved locally.
-
You can set/retrieve the leader board in descending or ascending order (score vs time).
-
You can add a serializable object to your scores, which allow almost everything to be saved with the highscore ( think date, image, bonus …).
-
The AddScore callback will return the submited score + the rank, which is very usefull.
-
You can retrieve a leaderboard (online scores) with a range, very usefull in combination to the user rank.
-
There is a little (very crappy) admin page to be able to add/delete a leaderboard, add/delete a score.
There is more to say, i’ll update this post when i have the time … for now here is the only ( needed? ) implemented functions:
public void Register( string callback, string username, string password )
public void GetScore( string callback, string leaderboardID )
public void AddScore( string callback, string leaderboardID, int score, object serializableObject )
public void GetLeaderboard( string callback, string leaderboardID, int limit1, int limit2 )
public void GetScoreCount( string callback, string leaderboardID )
Here is some usage example:
using UnityEngine;
using System.Collections;
public class AddScore : MonoBehaviour
{
YouLead youLead;
void Start ()
{
// Retrieve YouLead component, it is actually attached to the same GameObject
youLead = GetComponent<YouLead>();
// Create a custom (serializable) object to be saved with our score
SerializableData data = new SerializableData( Application.loadedLevelName, 0.1024f, 20, 30, 40 );
// Add score and assign a callback function
youLead.AddScore( "OnScoreAdded", "1", 20, data );
}
void OnScoreAdded( YLResult result )
{
// process YouLead result
if( result.success )
{
YLScore score = (YLScore)result.data;
Debug.Log( "Score added for user: `" + score.GetUsername() + "` to leaderboard `" + score.GetLeaderboardID() + "`" );
Debug.Log( "Rank: `" + score.GetRank() + "`" );
Debug.Log( "Score: `" + score.GetScore() + "`" );
SerializableData data = (SerializableData)score.GetData();
if( data !=null )
{
Debug.Log( "Level: " + data.level );
Debug.Log( "Time: " + data.time );
Debug.Log( "Stars: " + data.stars );
Debug.Log( "Bonus: " + data.bonus );
Debug.Log( "Total: " + data.total );
}
if( score.GetMode() == YLScore.MODE_LOCAL )
{
Debug.Log( "Score type: local" );
if( !youLead.GetUser().IsRegistred() )
{
Debug.Log( "Reason: user not registred" );
}
else
{
Debug.Log( "Reason: network error" );
}
}
else
{
Debug.Log( "Score type: online" );
}
}
else
{
Debug.Log( result.data );
}
}
}
using UnityEngine;
using System.Collections;
public class GetScore : MonoBehaviour
{
YouLead youLead;
void Start ()
{
// Retrieve YouLead component, it is actually attached to the same GameObject
youLead = GetComponent<YouLead>();
// Get score :)
youLead.GetScore( "OnGetScore", "1" );
}
void OnGetScore( YLResult result )
{
// process YouLead result
if( result.success )
{
YLScore score = (YLScore)result.data;
Debug.Log( "Score found for user: `" + score.GetUsername() + "` in leaderboard `" + score.GetLeaderboardID() + "`" );
Debug.Log( "Rank: `" + score.GetRank() + "`" );
Debug.Log( "Score: `" + score.GetScore() + "`" );
SerializableData data = (SerializableData)score.GetData();
if( data !=null )
{
Debug.Log( "Level: " + data.level );
Debug.Log( "Time: " + data.time );
Debug.Log( "Stars: " + data.stars );
Debug.Log( "Bonus: " + data.bonus );
Debug.Log( "Total: " + data.total );
}
if( score.GetMode() == YLScore.MODE_LOCAL )
{
Debug.Log( "Score type: local" );
if( !youLead.GetUser().IsRegistred() )
{
Debug.Log( "Reason: user not registred" );
}
else
{
Debug.Log( "Reason: network error or online score not found" );
}
}
else
{
Debug.Log( "Score type: online" );
}
}
else
{
Debug.Log( result.data );
}
}
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class GetLeaderboard : MonoBehaviour
{
YouLead youLead;
void Start ()
{
// Retrieve YouLead component, it is actually attached to the same GameObject
youLead = GetComponent<YouLead>();
youLead.GetLeaderboard( "OnGetLeaderboard", "1", 1, 10 );
}
void OnGetLeaderboard( YLResult result )
{
if( result.success )
{
List<YLScore> scoresList = (List<YLScore>)result.data;
foreach( YLScore score in scoresList )
{
Debug.Log( score.GetRank() + " -> " + score.GetUsername() + ": " + score.GetScore() );
SerializableData data = (SerializableData)score.GetData();
if( data != null )
{
Debug.Log( "Level: " + data.level + ", "
+ "Time: " + data.time + ", "
+ "Stars: " + data.stars + ", "
+ "Bonus: " + data.bonus + ", "
+ "Total: " + data.total );
}
}
}
else
{
Debug.Log( result.data );
}
}
}