跳到主要内容

统计

1. 概述

统计是一项帮助您存储和跟踪玩家或全局统计数据的服务。默认情况下,统计也是 Leaderboard 服务的主要数据源。

阅读本章,您将了解关键机制以及如何设置和使用统计。

2. 关键概念

2.1 Stat

Stat本质上是一个用于存储统计数据的数据映射。其中的每个数据项都包含以下关键字段:

  • Key:这是一个用于标识数据项的唯一字符串。Key 的具体设置取决于您的场景。例如,您可以将其设置为 PlayerID 来跟踪玩家的击杀数,或者将其设置为 TeamID 来跟踪团队的得分。
  • Value:该数据项的值是 double 类型,默认值为 0。
  • Secondary Value:这是一个可选的数据项值,也是 double 类型,默认值为 0。它用于 Leaderboard 服务中的多值排序。如果您不需要多值排序,可以忽略此字段。
  • Tags:可以为数据项添加标签。此字段用于在 Leaderboard 服务中配置和构建子排行榜。您还可以使用它来存储任意字符串来标记数据项。
  • custom_data: data item可以添加 custom_data 字段,用于存储附加信息。

您可以使用特定的聚合类型更新 Stat 中的数据项。下表概述了此机制:

Aggregate TypeValueSecondary ValueTags
OverrideOverwriteOverwriteOverwrite
Sum新值与现有值之和OverwriteOverwrite
Max如果新值大于现有值,则Overwrite如果值更新则Overwrite如果值更新则Overwrite
Min如果新值小于现有值,则Overwrite如果值更新则Overwrite如果值更新则Overwrite

2.2 周期

您可以使用“周期”功能来跟踪特定时间段内的统计数据。当您将属性绑定到周期后,PGOS 后端会在您更新Stat数据时自动更新周期数据。周期结束后,数据将被重置,例如,允许玩家开始新的比赛。例如,游戏可以跟踪每日击杀数或赛季最佳游戏会话得分。

您可以选择不同的周期类型,包括每日、每周、每月和季度(自定义)。您可以确定每种周期类型的重置时间。对于季度周期,您可以为每个周期定义重置时间,例如,为持续 90 天的游戏赛季定义 90 天的重置时间。

一个Stat可以绑定多个Cycle,一个Cycle也可以绑定多个Stat。

提示

请注意,如果在绑定后将数据更新到 Cycle,则绑定之前的已存在的 Stat 数据将不会再传输到 Cycle。。

  • Stat 不与 Cycle 绑定:其中只有一个持久数据图,如下图所示:

    image-20230921171114283

  • Stat 与 Cycle 绑定:每个绑定的 Cycle 都有一个额外的 Cycle 数据映射。每个 Cycle 数据与持久数据分开存储,如下图所示:

    image-20230921171139755

3. 在门户网站上管理

3.1 统计信息

3.1.1 添加新统计信息

登录 Web 门户,进入控制台,然后前往Statistics > Stats

image-20230906171133759

字段说明:

  • Stat名称:新统计的名称。它只能包含字母、数字和下划线,并且必须以字母开头。
  • 最小值(可选):统计项值的最小值。如果需要限制项值的最小值,请启用并指定限制值。
  • 最大值(可选):统计项值的最大值。如果需要限制项值的最大值,请启用并指定限制值。
  • 描述(可选):统计项的描述。

如果一切正常,您将获得一条新统计:

image-20230906172448274

3.1.2 编辑统计数据

如果您想编辑某个统计数据,请点击统计数据列表中的编辑链接按钮:

image-20230906172814253

提示

对最大限制和最小限制的修改仅影响后续的更新操作,不会改变现有数据。

3.1.3 删除统计数据

如果您想移除某个统计数据,请点击统计数据列表中的删除链接按钮:

image-20230906192931943

提示

一旦统计数据被删除,其数据将无法再通过“PgosSDK”或 HTTP API 访问。

3.1.4 管理统计项

点击Stat Name即可开始管理统计项:

image-20230906175254806

点击Stat Name后,您将看到最近更新的统计项列表:

image-20230922185421849

如果要搜索特定项,请输入Item key,然后单击搜索按钮:

如果您想同时搜索多个项,请启用multi-keys复选框,并在搜索框中输入多个item key。

image-20230906195333551

如果您想添加/更新统计项,请点击添加/更新数据按钮:

image-20230906195853748

填写所有字段并点击确定按钮,然后:

  • 如果 item key存在,则更新该项目。
  • 如果 item key不存在,则添加该项目。

3.2 周期

3.2.1 添加新周期

登录 Web 门户,进入控制台,然后前往Statistics > Cycle

image-20250523102058402

字段说明:

  • 名称:新周期的名称。名称只能包含字母、数字和下划线,且必须以字母开头。
  • 类型:周期类型,表示数据重置的周期,包括每日、每周、每月和季节性(自定义)。
  • 重置时间:重置周期数据的时间。
  • 开始日期时间:周期开始执行的时间。
  • 结束日期时间(可选):此时间表示Cycle停止运行的时间。
  • 锁定时间跨度(可选):在Cycle的最后几秒锁定数据,以防止新的提交。默认为 0。
  • 描述(可选):周期的描述。

如果一切顺利,您将获得一个新的周期:

image-20230922193429424

3.2.2 编辑周期

如果您想编辑周期,请点击周期列表中的编辑链接按钮:

image-20250523102650127

3.2.3 删除周期

如果您想移除某个周期,请点击周期列表中的删除按钮:

image-20230922193801224

3.2.4 将统计信息绑定到周期

如果您希望某个统计信息包含周期数据,则需要将该统计信息绑定到周期。在周期列表中,点击要绑定的cycle name:

image-20230922194422480

点击cycle name 后,你将会看到以下信息:

image-20230922194550144

点击 Bind Stat button, 你可以绑定stats到周期:

image-20230922195138930

您可以选择要绑定到周期的统计。绑定后,您选择的统计将出现在已绑定统计列表中:

image-20230922195258186

如果要从周期中解除绑定某个统计数据,请点击绑定统计数据列表中的删除链接按钮:

image-20230922195735544

3.2.5 查看周期数据

将Stats绑定到周期后,您将能够在以后更新Stats Item数据时同时获取相应的周期数据。如果您想在控制台中查看周期数据,请进入Manage stat items页面,点击物品键旁边的下拉箭头,即可查看周期数据:

image-20230922200815960

4. Cycle机制

Statistics服务持久化统计数据时,其逻辑如下:

  1. 基本持久化 无论统计数据是否与Cycle关联,都会始终存储一条永久的“持久化”统计数据记录。除非开发者通过移除统计数据定义明确删除,否则这些数据将无限期地保留。
  2. Cycle绑定的数据处理 对于与Cycle绑定的统计数据: CycleRound
  • 服务为每个绑定Cycle维护独立存储
  • cycle重置机制:
    • 每次“cycle”完成时,触发重置
    • 上一cycle的数据将被存档
    • 后续cycle的数据将被持久化
  1. Cycle排序

    • 每个cycle维护一个“cycle序列”计数器
    • 初始化为 1(表示cycle中的第一轮)
    • 按顺序递增(cycle序列 = n 表示第 n 轮迭代)
    • 达到cycle配置的结束日期时间时,排序停止
  2. 锁定时间的执行

    • 在每个cycle的最后 N 秒(可通过“锁定时间跨度”参数配置):

    • 拒绝新的数据更新请求

    • 默认禁用锁定(设置锁定时间跨度 = 0 表示禁用)

关于锁定时间跨度

例如,在游戏 A 的运营事件配置中:

  • 每周晚上 8:00 发布顶级矿工排名,并将奖励分发给前 100 名玩家。
    • 为了在晚上 8:00 之前完成排名,服务器需要时间:
      • 提取排行榜结果
      • 验证数据完整性(例如,进行漏洞/黑客攻击的反作弊检查)

如果重置时间设置为晚上 8:00,则必须预留缓冲期来完成这些操作。这可以通过配置锁定时间跨度参数来实现。

关键约束

  • 配置的锁定时间跨度不得超过一轮的总时长。

5. 边界情况

使用 Stat 和 Cycle 时,可能会遇到以下边界情况,请注意。

5.1 Stat 的最小/最大限制

在配置 Stat 的最小或最大限制时,如果使用以下聚合类型的值的结果可能超出最小或最大限制,PGOS 将按下表所示进行处理。

Aggregate TypeValue Result
Override大于最大限制的值将被设置为最大限制本身,而小于最小限制的值将被设置为最小限制本身。
Sum如果值的总和超过了最大限制,则该值将被设置为最大限制本身。如果值的总和小于最小限制,则该值将被设置为最小限制本身。
Max将当前值与大于最大限制的值进行比较时,该值将被设置为最大限制本身。
Min将当前值与小于最小限制的值进行比较时,该值将被设置为最小限制本身。

让我们以“最小值:0 最大值:100”限制为例:

Aggregate TypeOld ValueValue In RequestResult Value
Override75150100
Override75-1000
Sum7530100
Sum75-1000
Max75150100
Min75-1000

5.2 周期首次重置时间

在某些情况下,周期的首次重置时间可能短于预设的重置时间。以下示例可能会出现这种情况:

每日周期

Cycle TypeReset TimeStart Date
Daily10:002023-09-01 00:00:00

首次重置时间为 2023-09-01 10:00:00,即周期开始后 10 小时,而非 24 小时。下次重置时间为 2023-09-02 10:00:00,之后的重置时间亦如此。

每周周期

Cycle TypeReset TimeReset WeekdayStart Date
Weekly10:00Tuesday2023-01-01 00:00:00 (Let's assume this day is Monday)

第一次重置时间为 2023-01-02 10:00(星期二),下次重置时间为 2023-01-09 10:00,之后每次重置时间均相同。

月周期

Cycle TypeReset TimeReset MonthdayStart Date
Monthly10:0052023-01-01 00:00:00

第一次重置时间为 2023 年 1 月 5 日 10:00(星期二),下一次重置时间为 2023 年 2 月 5 日 10:00,之后的重置时间也一样。

如您所见,在上述场景中,第一次重置的时间周期通常小于Cycle Type中配置的时间周期。如果出现这种情况,请注意,这是符合预期的。

5.3 周期每月重置边界案例

使用月周期时,如果重置日期超过当月的最大天数,则默认为当月最后一天。

Cycle TypeReset TimeReset MonthdayStart Date
Monthly10:00312024-02-01 00:00:00

第一次重置时间为2024-02-28 10:00:00,即该月的最后一天。

6. 通过 SDK 访问

6.1 客户端

游戏可以通过 PgosSDK 在游戏客户端查询统计数据。

API描述
GetStatPersistentInfo查询指定stat item的持久信息。
BatchGetStatPersistentInfo批量查询指定Stat name和key的stat item的持久信息。
GetStatCycleInfo查询当前周期轮次中指定stat item的周期信息。
BatchGetStatCycleInfo批量查询当前周期轮次中指定 stat names 和 keys的周期信息。
BatchGetStatCycleRoundInfo批量查询当前周期的轮次信息

6.1.1 GetStatPersistentInfo 客户端 API

查询指定统计项的持久化信息。

接口原型:

/**
* Query the persistent info of the specified stat item.
*
* @param Params Request structure for querying persistent info.
*/
void GetStatPersistentInfo(
const FGetStatPersistentInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FStatItem* Data)> Callback) const;

struct FGetStatPersistentInfoParams {
/** Stat name. */
FString stat_name;
/** Stat item key. */
FString key;
};

代码示例:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetClientStatisticsAPI();
if (Statistics)
{
FGetStatPersistentInfoParams Params;
Params.stat_name = TEXT("EnemyKills");
Params.key = TEXT("p456792");
Statistics->GetStatPersistentInfo(Params, [](const FPgosResult& Ret, const FStatItem* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetStatPersistentInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetStatPersistentInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

6.1.2 BatchGetStatPersistentInfo 客户端 API

批量查询指定stat name和key的持久化信息。

接口原型:

/**
* Query item persistent info with specified stat names and keys in batches.
* For example: stat_names=["s1", "s2"], keys=["k1", "k2"],
* then you will get a batch of items:[("s1", "k1"), ("s1", "k2"), "s2", "k1"), ("s2", "k2")]
* It will ignore non-existing (stat_name + key) combination items.
*
* @param Params Request structure for querying item persistent infos.
*/
void BatchGetStatPersistentInfo(
const FBatchGetStatPersistentInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FBatchGetStatPersistentInfoResult* Data)> Callback) const;

struct FBatchGetStatPersistentInfoParams
{
/** Stat names. */
TArray<FString> stat_names;
/** Stat item keys. */
TArray<FString> keys;
};

代码示例:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetClientStatisticsAPI();
if (Statistics)
{
FBatchGetStatPersistentInfoParams Params;
Params.stat_names.Add(TEXT("EnemyKills"));
Params.stat_names.Add(TEXT("PlayerDeaths"));
Params.keys.Add(TEXT("p456791"));
Params.keys.Add(TEXT("p456792"));
Statistics->BatchGetStatPersistentInfo(Params, [](const FPgosResult& Ret, const FBatchGetStatPersistentInfoResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatPersistentInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatPersistentInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

6.1.3 GetStatCycleInfo 客户端 API

查询当前周期轮次中指定stat item的周期信息。

接口原型:

/**
* Query the cycle info of the specified stat item for the current cycle round.
*
* @param Params Request structure for querying the cycle info.
*/
void GetStatCycleInfo(
const FGetStatCycleInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FGetStatCycleInfoResult* Data)> Callback) const;

struct FGetStatCycleInfoParams
{
/** The stat name. */
FString stat_name;
/** The stat item key. */
FString key;
/** The stat cycle name. */
FString cycle_name;
};

代码示例:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetClientStatisticsAPI();
if (Statistics)
{
FGetStatCycleInfoParams Params;
Params.stat_name = TEXT("EnemyKills");
Params.key = TEXT("p456792");
Params.cycle_name = TEXT("Daily");
Statistics->GetStatCycleInfo(Params, [](const FPgosResult& Ret, const FGetStatCycleInfoResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetStatCycleInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetStatCycleInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

6.1.4 BatchGetStatCycleInfo 客户端 API

批量查询当前周期轮次中指定 stat names 和 keys的周期信息。

接口原型:

/**
* Query cycle info with specified stat names and keys for the current cycle round in batches.
* For example: stat_names=["s1", "s2"], keys=["k1", "k2"],
* then you will get a batch of items:[("s1", "k1"), ("s1", "k2"), "s2", "k1"), ("s2", "k2")]
* It will ignore non-existing (stat_name + key) combination items.
*
* @param Params Request structure for querying item cycle infos.
*/
void BatchGetStatCycleInfo(
const FBatchGetStatCycleInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FBatchGetStatCycleInfoResult* Data)> Callback) const;

struct FBatchGetStatCycleInfoParams
{
/** The stat names. */
TArray<FString> stat_names;
/** The stat item keys. */
TArray<FString> keys;
/** The stat cycle name. */
FString cycle_name;
};

代码示例:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetClientStatisticsAPI();
if (Statistics)
{
FBatchGetStatCycleInfoParams Params;
Params.stat_names.Add(TEXT("EnemyKills"));
Params.stat_names.Add(TEXT("PlayerDeaths"));
Params.keys.Add(TEXT("p456791"));
Params.keys.Add(TEXT("p456792"));
Params.cycle_name = TEXT("Daily");
Statistics->BatchGetStatCycleInfo(Params, [](const FPgosResult& Ret, const FBatchGetStatCycleInfoResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatCycleInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatCycleInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

6.1.5 BatchGetStatCycleRoundInfo 客户端 API

批量查询周期的当前轮次信息。

接口原型:

/**
* Query the current round infos of cycles in batches.
*
* @param Params Request structure for querying current round infos.
*/
void BatchGetStatCycleRoundInfo(
const FBatchGetStatCycleRoundInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FBatchGetStatCycleRoundInfoResult* Data)> Callback) const;

struct FBatchGetStatCycleRoundInfoParams
{
/** The stat cycle names. */
TArray<FString> cycle_names;
};

代码示例:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetClientStatisticsAPI();
if (Statistics)
{
FBatchGetStatCycleRoundInfoParams Params;
Params.cycle_names.Add(TEXT("Daily"));
Params.cycle_names.Add(TEXT("Weekly"));
Statistics->BatchGetStatCycleRoundInfo(Params, [](const FPgosResult& Ret, const FBatchGetStatCycleRoundInfoResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatCycleInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatCycleRoundInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

6.2 服务器端

游戏可以通过 PgosSDK 在游戏服务器上查询和更新统计数据。

API描述
GetStatPersistentInfo查询指定stat item的持久信息
BatchGetStatPersistentInfo批量查询指定stat item 和key的stat item的持久信息
GetStatCycleInfo查询当前周期轮次中指定stat item的周期信息。
BatchGetStatCycleInfo批量查询当前周期轮次中指定 stat names 和 keys的周期信息。
UpdateStatItem更新指定stat items.
BatchUpdateStatItem批量更新指定stat items
BatchGetStatCycleRoundInfo批量查询周期的当前轮次信息。

6.2.1 GetStatPersistentInfo Server API

查询指定stat item的持久信息

接口原型:

/**
* Query the persistent info of the specified stat item.
*
* @param Params Request structure for querying persistent info.
*/
void GetStatPersistentInfo(
const FGetStatPersistentInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FStatItem* Data)> Callback) const;

struct FGetStatPersistentInfoParams {
/** Stat name. */
FString stat_name;
/** Stat item key. */
FString key;
};

代码示例:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetServerStatisticsAPI();
if (Statistics)
{
FGetStatPersistentInfoParams Params;
Params.stat_name = TEXT("EnemyKills");
Params.key = TEXT("p456792");
Statistics->GetStatPersistentInfo(Params, [](const FPgosResult& Ret, const FStatItem* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetStatPersistentInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetStatPersistentInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

6.2.2 BatchGetStatPersistentInfo Server API

批量查询指定stat item 和key的stat item的持久信息。

接口原型:

/**
* Query item persistent infos with specified stat names and keys in batches.
* For example: stat_names=["s1", "s2"], keys=["k1", "k2"],
* then you will get a batch of items:[("s1", "k1"), ("s1", "k2"), "s2", "k1"), ("s2", "k2")]
* It will ignore non-existing (stat_name + key) combination items.
*
* @param Params Request structure for querying item persistent infos.
*/
void BatchGetStatPersistentInfo(
const FBatchGetStatPersistentInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FBatchGetStatPersistentInfoResult* Data)> Callback) const;

struct FBatchGetStatPersistentInfoParams
{
/** Stat names. */
TArray<FString> stat_names;
/** Stat item keys. */
TArray<FString> keys;
};

代码示例:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetServerStatisticsAPI();
if (Statistics)
{
FBatchGetStatPersistentInfoParams Params;
Params.stat_names.Add(TEXT("EnemyKills"));
Params.stat_names.Add(TEXT("PlayerDeaths"));
Params.keys.Add(TEXT("p456791"));
Params.keys.Add(TEXT("p456792"));
Statistics->BatchGetStatPersistentInfo(Params, [](const FPgosResult& Ret, const FBatchGetStatPersistentInfoResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatPersistentInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatPersistentInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

6.2.3 GetStatCycleInfo Server API

查询当前周期轮次中指定stat item的周期信息。

接口原型:

/**
* Query the cycle info of the specified stat item for the current cycle round.
*
* @param Params Request structure for querying the cycle info.
*/
void GetStatCycleInfo(
const FGetStatCycleInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FGetStatCycleInfoResult* Data)> Callback) const;

struct FGetStatCycleInfoParams
{
/** The stat name. */
FString stat_name;
/** The stat item key. */
FString key;
/** The stat cycle name. */
FString cycle_name;
};

代码示例:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetServerStatisticsAPI();
if (Statistics)
{
FGetStatCycleInfoParams Params;
Params.stat_name = TEXT("EnemyKills");
Params.key = TEXT("p456792");
Params.cycle_name = TEXT("Daily");
Statistics->GetStatCycleInfo(Params, [](const FPgosResult& Ret, const FGetStatCycleInfoResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetStatCycleInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetStatCycleInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

6.2.4 BatchGetStatCycleInfo Server API

批量查询当前周期轮次中指定 stat names 和 keys的周期信息。

接口原型:

/**
* Query cycle infos with specified stat names and keys for the current cycle round in batches.
* For example: stat_names=["s1", "s2"], keys=["k1", "k2"],
* then you will get a batch of items:[("s1", "k1"), ("s1", "k2"), "s2", "k1"), ("s2", "k2")]
* It will ignore non-existing (stat_name + key) combination items.
*
* @param Params Request structure for querying item cycle infos.
*/
void BatchGetStatCycleInfo(
const FBatchGetStatCycleInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FBatchGetStatCycleInfoResult* Data)> Callback) const;

struct FBatchGetStatCycleInfoParams
{
/** The stat names. */
TArray<FString> stat_names;
/** The stat item keys. */
TArray<FString> keys;
/** The stat cycle name. */
FString cycle_name;
};

代码示例:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetServerStatisticsAPI();
if (Statistics)
{
FBatchGetStatCycleInfoParams Params;
Params.stat_names.Add(TEXT("EnemyKills"));
Params.stat_names.Add(TEXT("PlayerDeaths"));
Params.keys.Add(TEXT("p456791"));
Params.keys.Add(TEXT("p456792"));
Params.cycle_name = TEXT("Daily");
Statistics->BatchGetStatCycleInfo(Params, [](const FPgosResult& Ret, const FBatchGetStatCycleInfoResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatCycleInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatCycleInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

6.2.5 UpdateStatItem Server API

更新指定的stat item。

接口原型:

/**
* Update the specified stat item.
*
* @param Params Request structure for updating the specified stat item.
*/
void UpdateStatItem(
const FServerUpdateStatItemParams& Params,
TFunction<void(const FPgosResult& Ret, const FServerStatItemAfterUpdate* Data)> Callback) const;

struct FServerUpdateStatItemParams
{
/** The stat item to update. */
FStatItem item;
/** Whether update custom data. It won't overwrite the old one when updated if this is true. */
bool ignore_custom_data = false;
/** Whether update tags. It won't overwrite the old one when updated if this is true. */
bool ignore_tags = false;
};

struct FStatItem
{
/** Stat name. */
FString stat_name;
/** Stat item key. */
FString key;
/**
* The meaning of the value varies in different scenarios:
* 1. Get stat item persistent value: it is item persistent value.
* 2. Get stat item cycle value: it is item cycle value.
* 3. Update stat item value: it is the value to be aggregated into the stat item.
*/
double value = 0.0;
/** Stat item secondary value. It will overwrite the old one when updated. */
double secondary_value = 0.0;
/** Stat item tags. It will overwrite the old one when updated if 'ignore_tags' is false. Max 10 values, each value limited to 64 bytes(in a narrow-character string) */
TArray<FString> tags;
/** Used to store additional information. It will overwrite the old one when updated if 'ignore_custom_data' is false. Limited to 512 bytes(in a narrow-character string) */
FString custom_data;
/** The method to aggregate. */
EPgosAggregateType aggregate_type = EPgosAggregateType::Overwrite;
};

代码示例:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetServerStatisticsAPI();
if (Statistics)
{
FServerUpdateStatItemParams Params;
Params.item.stat_name = TEXT("EnemyKills");
Params.item.key = TEXT("p456792");
Params.item.value = 2;
Params.item.aggregate_type = EAggregateType::Sum;
Statistics->UpdateStatItem(Params, [](const FPgosResult& Ret, const FServerStatItemAfterUpdate* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("UpdateStatItem Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("UpdateStatItem Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

6.2.6 BatchUpdateStatItem Server API

批量更新stat items。

接口原型:

/**
* Update the stat items in batches.
*
* @param Params Request structure for updating the stat items in batches.
*/
void BatchUpdateStatItem(
const FServerBatchUpdateStatItemParams& Params,
TFunction<void(const FPgosResult& Ret, const FServerBatchUpdateStatItemResult* Data)> Callback) const;

struct FServerBatchUpdateStatItemParams
{
/** The stat items to update. */
TArray<FStatItem> items;
/** Whether update custom data. It won't overwrite the old one when updated if this is true. */
bool ignore_custom_data = false;
/** Whether update tags. It won't overwrite the old one when updated if this is true. */
bool ignore_tags = false;
};

代码示例:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetServerStatisticsAPI();
if (Statistics)
{
FStatItem item1;
item1.stat_name = TEXT("EnemyKills");
item1.key = TEXT("p600001");
item1.value = 2;
item1.aggregate_type = EAggregateType::Sum;

FStatItem item2;
item2.stat_name = TEXT("EnemyKills");
item2.key = TEXT("p600002");
item2.value = 5;
item2.aggregate_type = EAggregateType::Sum;

FServerBatchUpdateStatItemParams Params;
Params.items.Add(item1);
Params.items.Add(item2);
Statistics->BatchUpdateStatItem(Params, [](const FPgosResult& Ret, const FServerBatchUpdateStatItemResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchUpdateStatItem Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchUpdateStatItem Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

6.2.7 BatchGetStatCycleRoundInfo Server API

批量查询周期的当前轮次信息。

接口原型:

/**
* Query the current round infos of cycles in batches.
*
* @param Params Request structure for querying current round infos.
*/
void BatchGetStatCycleRoundInfo(
const FBatchGetStatCycleRoundInfoParams& Params,
TFunction<void(const FPgosResult& Ret, const FBatchGetStatCycleRoundInfoResult* Data)> Callback) const;

struct FBatchGetStatCycleRoundInfoParams
{
/** The stat cycle names. */
TArray<FString> cycle_names;
};

代码示例:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Statistics = IPgosSDKCpp::Get().GetServerStatisticsAPI();
if (Statistics)
{
FBatchGetStatCycleRoundInfoParams Params;
Params.cycle_names.Add(TEXT("Daily"));
Params.cycle_names.Add(TEXT("Weekly"));
Statistics->BatchGetStatCycleRoundInfo(Params, [](const FPgosResult& Ret, const FBatchGetStatCycleRoundInfoResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatCycleInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetStatCycleRoundInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

6.3 关键错误处理

错误码相关APIHandling Suggestion
kBackendStatItemMissingCriticalFieldsGetStatPersistentInfo Client API
BatchGetStatPersistentInfo Client API
GetStatCycleInfo Client API
BatchGetStatCycleInfo Client API
GetStatPersistentInfo Server API
BatchGetStatPersistentInfo Server API
GetStatCycleInfo Server API
BatchGetStatCycleInfo Server API
UpdateStatItem Server API
BatchUpdateStatItem Server API
缺失关键字段,如 stat_name,key。
kBackendStatKeysNoDataGetStatPersistentInfo Client API
BatchGetStatPersistentInfo Client API
GetStatCycleInfo Client API
BatchGetStatCycleInfo Client API
GetStatPersistentInfo Server API
BatchGetStatPersistentInfo Server API
GetStatCycleInfo Server API
BatchGetStatCycleInfo Server API
未找到指定stat 和周期的数据
kSdkNetworkErrorAll Network API网络错误, 检查错误日志,获取更多细节