Search code examples
c#xnasteamleaderboardsteamworks-api

How to do leaderboards in Steamworks.NET?


I am trying to include leaderboards in my application (a game written in C#, using SteamWorks.NET and based on XNA).

Steam is initialized properly.

On gamestart I call:

SteamAPICall_t hSteamAPICall = SteamUserStats.FindLeaderboard("Most active beta testers");
leaderboard_BetaTesters_ResultFindLeaderboard = Callback<LeaderboardFindResult_t>.Create(OnLeaderboardFindResult_BetaTesters);

using

static private void OnLeaderboardFindResult_BetaTesters(LeaderboardFindResult_t pCallback)
{
// See if we encountered an error during the call
if (pCallback.m_bLeaderboardFound == 0)
  {
  Warning.Happened("Leaderboard could not be found / accessed");
  return;
  }
else
  {
  Write.Text("Steam leaderboad connected");
  }
  leaderboard_BetaTesters = pCallback.m_hSteamLeaderboard;
}

And in every Update() I call:

if (SystemLogic.SteamInitSuccessul()) SteamAPI.RunCallbacks();

However, OnLeaderboardFindResult_BetaTesters is never called. What am I doing wrong?


Solution

  • I know is an old issue, but I've the same one just now.

    I've the same issue when I tried to implement Steam leaderboards on Unity with Steamworks.NET. Finally I get it working from the original Steamworks C++ sample project. (The documentation for Steamworks.NET is really poor, like the original Steamworks c++ one, so you have to check the Steamworks c++ Sample Project to check how to use it)

    You have a mistake, you have to use the "CallResult<>" class instead of the "Callback<>" one.

    The following code allowed me to upload scores on Unity to a SteamLeaderboard:

    using UnityEngine;
    using Steamworks;
    using System.Collections;
    using System.Threading;
    
    public class SteamLeaderboards : MonoBehaviour
    {
        private const string s_leaderboardName = "StoryMode";
        private const ELeaderboardUploadScoreMethod s_leaderboardMethod = ELeaderboardUploadScoreMethod.k_ELeaderboardUploadScoreMethodKeepBest;
    
        private static SteamLeaderboard_t s_currentLeaderboard;
        private static bool s_initialized = false;
        private static CallResult<LeaderboardFindResult_t> m_findResult = new CallResult<LeaderboardFindResult_t>();
        private static CallResult<LeaderboardScoreUploaded_t> m_uploadResult = new CallResult<LeaderboardScoreUploaded_t>();
    
    
        public static void UpdateScore(int score)
        {
            if (!s_initialized)
            {
                UnityEngine.Debug.Log("Can't upload to the leaderboard because isn't loadded yet");
            }
            else
            {
                UnityEngine.Debug.Log("uploading score(" + score + ") to steam leaderboard(" + s_leaderboardName + ")");
                SteamAPICall_t hSteamAPICall = SteamUserStats.UploadLeaderboardScore(s_currentLeaderboard, s_leaderboardMethod, score, null, 0);
                m_uploadResult.Set(hSteamAPICall, OnLeaderboardUploadResult);
            }
        }
    
        public static void Init()
        {
            SteamAPICall_t hSteamAPICall = SteamUserStats.FindLeaderboard(s_leaderboardName);
            m_findResult.Set(hSteamAPICall, OnLeaderboardFindResult);
            InitTimer();
        }
    
        static private void OnLeaderboardFindResult(LeaderboardFindResult_t pCallback, bool failure)
        {
            UnityEngine.Debug.Log("STEAM LEADERBOARDS: Found - " + pCallback.m_bLeaderboardFound + " leaderboardID - " + pCallback.m_hSteamLeaderboard.m_SteamLeaderboard);
            s_currentLeaderboard = pCallback.m_hSteamLeaderboard;
            s_initialized = true;
        }
    
        static private void OnLeaderboardUploadResult(LeaderboardScoreUploaded_t pCallback, bool failure)
        {
            UnityEngine.Debug.Log("STEAM LEADERBOARDS: failure - " + failure + " Completed - " + pCallback.m_bSuccess + " NewScore: " + pCallback.m_nGlobalRankNew + " Score " + pCallback.m_nScore + " HasChanged - " + pCallback.m_bScoreChanged);
        }
    
    
    
        private static Timer timer1; 
        public static void InitTimer()
        {
            timer1 = new Timer(timer1_Tick, null,0,1000);
        }
    
        private static void timer1_Tick(object state)
        {
            SteamAPI.RunCallbacks(); 
        }
    }
    

    *I have edited several times this code without compile it, and maybe contains any syntax error, but the implementation should be fine

    ** Also remember this code has been used on Unity 4, but the Unity classes are used only for "console log" messages and for the last two methods "call each x miliseconds the SteamAPI.RunCallbacks() method"