You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Unity中使用Steamworks.NET处理多个排行榜

Steamworks.NET Unity 多排行榜处理方案

你的问题核心是复用同一个CallResult实例时,多次调用Set()会覆盖之前的回调绑定,导致只有最后一次查询会触发回调,且无法区分结果对应哪个排行榜。下面给两种实用的解决方法:

方法一:用字典关联查询句柄与排行榜名称(适合动态数量的排行榜)

这种方法通过字典记录每个查询请求对应的排行榜名称,回调时根据查询句柄匹配名称,再分配到对应的句柄变量。

  1. 定义存储变量和回调实例:
// 存储待处理的查询请求:键是查询句柄,值是排行榜名称
private Dictionary<SteamAPICall_t, string> _pendingLeaderboardQueries = new Dictionary<SteamAPICall_t, string>();
// 通用的排行榜查询回调实例
private CallResult<LeaderboardFindResult_t> _leaderboardFindCallResult;

// 多排行榜句柄
private SteamLeaderboard_t m_Leaderboard_one;
private SteamLeaderboard_t m_Leaderboard_two;
  1. 初始化回调:
void Awake()
{
    _leaderboardFindCallResult = CallResult<LeaderboardFindResult_t>.Create(OnLeaderboardFindResult);
}
  1. 封装查询方法:
public void RequestLeaderboard(string leaderboardName)
{
    SteamAPICall_t callHandle = SteamUserStats.FindLeaderboard(leaderboardName);
    // 记录当前查询的句柄和对应名称
    _pendingLeaderboardQueries.Add(callHandle, leaderboardName);
    // 绑定回调
    _leaderboardFindCallResult.Set(callHandle);
}
  1. 处理回调(注意要添加SteamAPICall_t参数):
void OnLeaderboardFindResult(LeaderboardFindResult_t pCallback, bool bIOFailure, SteamAPICall_t callHandle)
{
    // 先从字典中取出当前查询的排行榜名称
    if (!_pendingLeaderboardQueries.TryGetValue(callHandle, out string leaderboardName))
    {
        Debug.LogWarning("Unknown leaderboard query callback");
        return;
    }
    // 处理完后移除记录,避免内存泄漏
    _pendingLeaderboardQueries.Remove(callHandle);

    if (bIOFailure)
    {
        Debug.LogError($"IO Failed when finding leaderboard: {leaderboardName}");
        return;
    }

    if (pCallback.m_bLeaderboardFound == 0)
    {
        Debug.LogError($"Leaderboard not found: {leaderboardName}");
        return;
    }

    // 根据名称分配到对应的句柄
    switch (leaderboardName)
    {
        case "YourLeaderboardOneName":
            m_Leaderboard_one = pCallback.m_hSteamLeaderboard;
            Debug.Log($"Loaded leaderboard: {leaderboardName}");
            break;
        case "YourLeaderboardTwoName":
            m_Leaderboard_two = pCallback.m_hSteamLeaderboard;
            Debug.Log($"Loaded leaderboard: {leaderboardName}");
            break;
        // 可扩展更多排行榜
    }
}

方法二:为每个排行榜创建独立回调实例(适合固定数量的排行榜)

如果你的排行榜数量固定,直接给每个排行榜分配独立的CallResult和回调方法,逻辑更直观。

  1. 定义独立的回调和句柄:
private CallResult<LeaderboardFindResult_t> _findLeaderboardOneResult;
private CallResult<LeaderboardFindResult_t> _findLeaderboardTwoResult;

private SteamLeaderboard_t m_Leaderboard_one;
private SteamLeaderboard_t m_Leaderboard_two;
  1. 初始化各回调:
void Awake()
{
    _findLeaderboardOneResult = CallResult<LeaderboardFindResult_t>.Create(OnLeaderboardOneFound);
    _findLeaderboardTwoResult = CallResult<LeaderboardFindResult_t>.Create(OnLeaderboardTwoFound);
}
  1. 发起查询:
public void LoadAllLeaderboards()
{
    // 查询第一个排行榜
    SteamAPICall_t handleOne = SteamUserStats.FindLeaderboard("YourLeaderboardOneName");
    _findLeaderboardOneResult.Set(handleOne);

    // 查询第二个排行榜
    SteamAPICall_t handleTwo = SteamUserStats.FindLeaderboard("YourLeaderboardTwoName");
    _findLeaderboardTwoResult.Set(handleTwo);
}
  1. 各自的回调处理:
void OnLeaderboardOneFound(LeaderboardFindResult_t callback, bool ioFail)
{
    if (!ioFail && callback.m_bLeaderboardFound != 0)
    {
        m_Leaderboard_one = callback.m_hSteamLeaderboard;
        Debug.Log("Leaderboard One loaded successfully");
    }
}

void OnLeaderboardTwoFound(LeaderboardFindResult_t callback, bool ioFail)
{
    if (!ioFail && callback.m_bLeaderboardFound != 0)
    {
        m_Leaderboard_two = callback.m_hSteamLeaderboard;
        Debug.Log("Leaderboard Two loaded successfully");
    }
}

为什么之前的方法失效?

你之前复用同一个OnLeaderboardFindResultCallResult实例,每次调用Set(handle)都会替换掉之前绑定的查询句柄,导致只有最后一次的查询请求会触发回调,前面的请求回调被覆盖,自然无法区分结果。

内容的提问来源于stack exchange,提问作者MatterGoal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 14:28:20