排行榜
1. 概述
如今,排行榜几乎已成为线上游戏的必备功能。通过展示排行榜和玩家排名详情,可以为玩家营造良好的竞技氛围。
2. 关键概念
首先,PGOS 排行榜服务使用 Stat 服务作为其数据源。在创建排行榜之前,您需要在统计服务中创建一个 Stat 对象,用于追踪玩家或全局数据。创建排行榜后,一旦 Stat 对象的数据更新,排行榜中的排名数据也会自动更新。
排行榜的主要特点如下:
- 持久化和周期化排行榜
持久化排行榜的排名数据不会被重置。而周期化排行榜的排名数据会根据您创建排行榜时选择的统计周期定期重置。
- 海量排名数据,实时更新
PGOS 排行榜的核心引擎采用类似 SkipList
的算法实现高性能实时排序,同时将数据动态存储在内存和数据库中,以尽可能节省成本。
- 多值排序
排行榜支持多种排序因素,您可以分别设置它们的排序类型。
- Value:数据项在状态中的值
- Secondary Value:数据项在状态中的次要值
- 更新时间:数据项的更新时间
排序因素的优先级为:Value > Secondary Value > 更新时间
为了保证排序结果的稳定性,Key 是另一个按字母顺序排列的排序因素。这是一种有效的解决方法。这样,当Value、Secondary Value和更新时间分别相等时,您就可以获得稳定的排序结果。
- 周期排行榜存档
周期排行榜的时间帧切换时,所有排名数据将被重置。上一次的排名数据将被存档。您可以通过 API 或 Portal 访问这些数据。
- 支持检索带有相邻物品的排名物品
您可以通过 API 检索带有相邻物品的排名物品。大多数游戏都这样做是为了向玩家显示其排名位置以及排名中的相邻玩家。
- 支持检索任意偏移量的排名列表
您可以精确检索任意偏移量的排名物品。
- 支持检索好友排名列表
您可以检索指定排行榜的当前好友排名列表。排行榜的统计物品键应填写玩家 ID。
3. 在门户网站上管理排行榜
3.1 添加新的排行榜
登录 Web 门户,进入控制台,然后前往Engagement > Leaderboards:
字段说明:
Name:新排行榜的名称。名称只能包含字母、数字和下划线,且不能以数字开头。
Description (可选):排行榜的描述。
Bound Stat:将现有Stat关联为排行榜的数据源。
Order Config:指定排行榜中物品的排序方式。
Value:物品数值的排序方式。排名优先按物品数值排序。
Secondary Value:次要数值的排序方式。当物品数值相同时,次要数值为第二优先排序规则。
如果不重要的话,选择“Not Order”可以提高后端的性能。
更新时间:商品更新时间的排序方式,当商品值与次要值相同时,为第三优先排序规则。
如果不重要的话, 选择“Not Order”可以提高后端的性能。
如果一切顺利,那么您将获得一个新的排行榜:
3.2 删除排行榜
如果您想删除排行榜,请点击排行榜列表中的删除链接按钮:
❗ 注意:一旦排行榜被删除,其数据将无法再通过“PgosSDK”或 HTTP API 访问。
3.3 管理排行榜物品
点击排行榜名称即可开始管理排行榜物品:
点击排行榜名称后,你会看到排行榜项目列表:
如果要搜索特定商品,请输入商品键,然后单击搜索按钮:
如果您想同时搜索多个项目,请启用multi-keys复选框,并在搜索框中输入多个item key。
4. 排行榜绑定 Stat 和 Cycle
4.1 创建一个周期排行榜
排行榜类型默认为Persistent类型,与持久属性数据绑定。您也可以选择Cycle类型,并选择已绑定该属性的现有cycle。此时排行榜数据和排名将根据cycle重置。
注意:
- 创建排行榜之前,stat 中的现有数据将不会更新到周期排行榜中。
- 但是,stat 中的所有数据,包括创建排行榜之前存在的数据,都将加载到持久排行榜中。
4.2 排行榜轮次序列
与周期轮次序列类似,周期排行榜会维护一个 leaderboard_round_seq
值,用于在创建后识别每一轮cycle。
leaderboard_round_seq
从 1 开始,表示排行榜创建后的第一个有效cycle轮次。leaderboard_round_seq
会在当前轮次结束、下一轮开始时加 1。- 如果在cycle开始几轮后创建周期排行榜,则
leaderboard_round_seq
值可能与cycle_round_seq
值不同。
4.3 周期排行榜的归档数据
周期排行榜的排名数据将在每轮cycle结束后自动归档。最多可配置归档 最大存档轮数(Max Archive Rounds)个周期排行榜排名数据。
您可以通过指定 leaderboard_round_seq
,从以下 API 中获取归档数据。
5. 通过 SDK 访问
5.1 游戏客户端
游戏可以通过 PgosSDK
在游戏客户端查询排行榜数据。
API | 描述 |
---|---|
GetRankingList | 查询指定排行榜的当前排名列表。 |
GetRankingItemPos | 查询当前排名列表项与指定排行榜的邻近项。 |
GetFriendsRankingList | 查询指定排行榜当前好友排名列表,排行榜的stat item key需填写玩家id。 |
5.1.1 获取排名列表客户端 API
接口原型:
/**
* Query the current ranking list of the specified leaderboard.
*
* @param Params Request structure for querying the current ranking list.
*/
void GetRankingList(
const FClientGetRankingListParams& Params,
TFunction<void(const FPgosResult& Ret, const FClientLBRankingListResult* Data)> Callback) const;
struct FClientGetRankingListParams
{
/** The name of the leaderboard to query. */
FString leaderboard_name;
/** The starting position of the query. */
int32 offset = 0;
/** The query count. */
int32 count = 0;
/** [Option] Query the ranking list of the specified round in the cycled leaderboard. The default value 0 means querying the ranking of the current round. */
int32 leaderboard_round_seq = 0;
};
struct FClientLBRankingListResult
{
/** List of ranking items. */
TArray<FClientLBRankingItem> items;
/** Leaderboard information. */
FClientLeaderboardInfo leaderboard_info;
/** The total number of ranking items. */
int32 total_num = 0;
/** The next starting position of the list. */
int32 next_offset = 0;
};
struct FClientLeaderboardInfo
{
/** The name of the leaderboard. */
FString leaderboard_name;
/** The name of the stat bound to the leaderboard. */
FString stat_name;
/** Is this leaderboard a cycled leaderboard. */
bool is_cycled = false;
/** The information of cycle bound to the leaderboard. This is only meaningful if `is_cycled` is true. */
FClientCycleInfo cycle_info;
/** Round information for a specified time or current time. This is only meaningful if `is_cycled` is true. */
FClientLeaderboardRoundInfo round_info;
};
/** Information of cycle which configured on the portal. */
struct FClientCycleInfo
{
/** Cycle name. */
FString cycle_name;
/** Start time of the cycle. Unix time in second. */
int64 cycle_start_time = 0;
/** End time of the cycle. Unix time in second. */
int64 cycle_end_time = false;
/** Lock time span of this cycle. After setting, the period before the end of each round will be locked, and the leaderboard data will not be updated during the locked period. Unix time in second. */
int32 lock_time_span = 0;
};
struct FPgosClientLeaderboardRoundInfo
{
/** The sequence number of the leaderboard round. Start from 1, the numbers are increasing in sequence, increasing by 1 in each round. 0 means the data of this round info is invalid or has been cleared. */
int32 round_seq = 0;
/** The round start time. Unix time in second. */
int64 round_start_time = 0;
/** The round end time. Unix time in second. */
int64 round_end_time = 0;
/** True if this round has been locked or end. */
bool round_locked = false;
};
代码示例:
#include "PgosSDKCpp.h"
void SomeUObjectClass::SomeFunction()
{
auto Leaderboard = IPgosSDKCpp::Get().GetClientLeaderboardAPI();
if (Leaderboard)
{
FClientGetRankingListParams Params;
Params.leaderboard_name = TEXT("KillingRanking");
Params.offset = 0;
Params.count = 10;
Leaderboard->GetRankingList(Params, [](const FPgosResult& Ret, const FClientLBRankingListResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetRankingList Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetRankingList Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
leaderboard_round_seq:查询周期排行榜中指定轮次的排名列表。默认值 0 表示查询当前轮次的排名。
加载第一页时,leaderboard_round_seq 通常指定为 0。加载下一页时,建议将 leaderboard_round_seq 指定为第一页返回的序列号,以确保加载同一轮次的数据。
5.1.2 GetRankingItemPos 客户端 API
接口原型:
/**
* Query the current ranking list item with neighbor items of the specified leaderboard.
*
* @param Params Request structure for querying the current ranking list item with neighbor items.
*/
void GetRankingItemPos(
const FClientGetRankingItemPosParams& Params,
TFunction<void(const FPgosResult& Ret, const FClientLBRankingItemPos* Data)> Callback) const;
struct FClientGetRankingItemPosParams
{
/** The name of the leaderboard to query. */
FString leaderboard_name;
/** The stat item key to query. */
FString key;
/**
* Specify the desired number of preceding and subsequent neighbors, ranging from 0 to 10.
* For example: if neighbor_cnt is 3, then you will get 3 preceding neighbors and 3 subsequent neighbors.
*/
int32 neighbor_cnt = 0;
/** [Option] Query the ranking list of the specified round in the cycled leaderboard. The default value 0 means querying the ranking of the current round. */
int32 leaderboard_round_seq = 0;
};
代码示例:
#include "PgosSDKCpp.h"
void SomeUObjectClass::SomeFunction()
{
auto Leaderboard = IPgosSDKCpp::Get().GetClientLeaderboardAPI();
if (Leaderboard)
{
FClientGetRankingItemPosParams Params;
Params.leaderboard_name = TEXT("KillingRanking");
Params.key = TEXT("p600001");
Params.neighbor_cnt = 3;
Leaderboard->GetRankingItemPos(Params, [](const FPgosResult& Ret, const FClientLBRankingItemPos* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetRankingItemPos Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetRankingItemPos Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
leaderboard_round_seq:查询周期排行榜中指定轮次的排名列表。默认值 0 表示查询当前轮次的排名。
加载第一页时,leaderboard_round_seq 通常指定为 0。加载下一页时,建议将 leaderboard_round_seq 指定为第一页返回的序列号,以确保加载同一轮次的数据。
5.1.3 GetFriendsRankingList 客户端 API
查询指定排行榜的当前好友排名列表。排行榜的stat item key应填写玩家 ID。
接口原型:
/**
* Query the current friends ranking list of the specified leaderboard. The leaderboard's stat item key should be filled with player id.
*
* @param Params Request structure for querying the current friends ranking list.
*/
void GetFriendsRankingList(
const FClientGetFriendsRankingListParams& Params,
TFunction<void(const FPgosResult& Ret, const FClientLBFriendsRankingListResult* Data)> Callback) const;
struct FClientGetFriendsRankingListParams
{
/** The name of the leaderboard to query. */
FString leaderboard_name;
/** [Option] Query the ranking list of the specified round in the cycled leaderboard. The default value 0 means querying the ranking of the current round. */
int32 leaderboard_round_seq = 0;
};
/** Response for get friends ranking list. */
struct PGOSSDKCPP_API FClientLBFriendsRankingListResult
{
/** List of friends ranking items. The stat item key was filled with player id. */
TArray<FClientLBRankingItem> items;
/**
* Friends' details. key: player id
* Note that this only contains the player information of friends, not my own. The 'items' contains my ranking.
*/
TMap<FString, FClientPlayerFriendInfo> friend_infos;
};
代码示例:
#include "PgosSDKCpp.h"
void SomeUObjectClass::SomeFunction()
{
auto Leaderboard = IPgosSDKCpp::Get().GetClientLeaderboardAPI();
if (Leaderboard)
{
FClientGetFriendsRankingListParams Params;
Params.leaderboard_name = TEXT("KillingRanking");
Leaderboard->GetFriendsRankingList(Params, [](const FPgosResult& Ret, const FClientLBFriendsRankingListResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetFriendsRankingList Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetFriendsRankingList Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
leaderboard_round_seq:查询周期排行榜中指定轮次的排名列表。默认值 0 表示查询当前轮次的排名。
加载第一页时,leaderboard_round_seq 通常指定为 0。加载下一页时,建议将 leaderboard_round_seq 指定为第一页返回的序列号,以确保加载同一轮次的数据。
5.2 关键错误处理
错误码 | 相关API | 处理建议 |
---|---|---|
kBackendLeaderboardNotExist | GetRankingList Client API GetRankingItemPos Client API | 排行榜不存在。需要创建新排行榜才能使用。 |
kBackendLBKeyNotExist | GetRankingItemPos Client API | 指定的要查询的key在排行榜中不存在。 |