玩家信息
1. 概述
玩家信息是用于描述玩家的核心属性集合。具体来说,它包含两个部分:
- 基础信息是内置的不可修改字段,如
player_id
、display_name
和avatar_uri
。 - 自定义信息是由游戏自定义的字段,这是来自玩家数据模板.的核心数据集。
完成本教程后,您将了解以下内容:
- 如何在网页端查看和修改玩家信息。
- 如何在代码中查询和更新玩家信息。
2. 门户网站上的玩家信息
2.1 查看玩家信息
登录网页门户,进入控制台并前往玩家 > 查询:
点击玩家的ID以查看玩家详细信息:
2.2 玩家信息定义
玩家信息通常作为一个核心属性集合,用于在好友、组队和房间等服务模块中描述玩家。由于其基本信息是由 PGOS 以通用性为目标定义的,无法满足游戏描述玩家核心属性的所有需求。因此,PGOS 为游戏提供了一种扩展玩家信息的方式:从玩家数据模板中选择某些项作为玩家信息的一部分,这被称为自定义信息。
自定义信息旨在使玩家信息更加丰富,因为玩家信息可能不足以描述玩家的"基本信息"。例如,当玩家收到陌生人的好友请求时,游戏可能需要向玩家显示该陌生人的"等级",这可以从玩家数据中获取,但那将需要另一个 API 调用。如果游戏将"等级"添加到自定义信息中,使其成为玩家基本信息的一部分,游戏就不需要额外的 API 调用,这为开发带来了便利。
进入控制台并前往玩家 > 玩家信息定义:
点击"管理"按钮来选择要显示在玩家自定义信息中的项目:
开发者可以通过
FPlayerInfo::custom_info
访问自定义信息,详见数据结构. >❗ 注意: > >玩家自定义信息中的数据项对所有玩家都是可见的。虽然您可以将任何数据项添加为自定义信息(无论其访问权限如何),但我们仍建议您谨慎考虑这样做。另外需要注意的是,如果向自定义信息中添加过多数据项,可能会导致不必要的性能问题。
3. 数据结构
3.1 玩家信息和玩家详情
玩家信息有两种数据结构:FPlayerInfo
和 FPlayerDetail
。FPlayerDetail
继承自 FPlayerInfo
的数据。只有数据所有者和游戏服务器可以访问 FPlayerDetail
。
struct FPlayerInfo
{
FString player_id;
FString display_name;
FString gender;
FString avatar_uri;
int32 account_provider;
FString account_platform;
FString account_open_id;
FString account_id;
EClientOS os;
TMap<FString, FKVDataValue> custom_info;
};
struct FPlayerDetail : public FPlayerInfo
{
FString language;
int64 first_login_time;
int64 last_login_time;
int64 last_logout_time;
int64 total_time;
FString last_login_ip;
FString cur_login_ip;
};
除了以下由PGOS后端更新的数据成员外,其他数据成员在游戏中设置之前默认为空。
player_id:PGOS提供的游戏区服中唯一的玩家ID。
display_name:玩家的显示名称。
gender:玩家的性别。
avatar_uri:玩家的头像URI。
account_provider:账号服务提供商。0表示FAS,1表示INTL,2表示MSDK,3表示WeGame,4表示PlayFab,5表示Steam,6表示Epic,7表示XboxLive,8表示PlayStationNetwork,9表示Nintendo。
account_platform:账号平台名称,PGOS会在游戏调用
LoginPGOS
时从传入的参数中获取并保存。它可以是以下值之一:
[
"WeChat",
"QQ",
"Guest",
"Facebook",
"GameCenter",
"Google",
"IEGPassport",
"Twitter",
"Garena",
"EGame",
"Nintendo",
"LINE",
"Apple",
"VK",
"XboxLive",
"Steam",
"EpicGames",
"Discord",
"PlayStationNetwork",
"DMM",
"SquareEnix",
"Supercell",
"Kakao",
"Instagram",
"Whatsapp",
"Sop",
"LI PASS",
"Amazon",
"AndroidDevice",
"Custom",
"FacebookInstantGames",
"GooglePlay",
"IOSDevice",
"Kongregate",
"LoadTest",
"OpenIdConnect",
"Organic",
"Parse",
"ServerCustom",
"Twitch",
"Unknown"
]
account_open_id: 已登录账号服务提供商的 open ID。
account_id: 玩家所拥有的账号平台用户 ID(例如 Steam SteamID、PSN 账号 ID、Xbox XUID)。
custom_info: 来自玩家数据的自定义信息,key: 键名,value: 值。
language: 玩家的显示语言,如果您希望游戏支持多语言。
first_login_time: 玩家在游戏区服首次登录的 Unix 时间戳。
last_login_time: 玩家在游戏区服最后一次登录的 Unix 时间戳。
last_logout_time: 玩家在游戏区服最后一次登出的 Unix 时间戳。
total_time: 玩家的总在线时长,以秒为单位。
除非另有说明,PGOS 接口中的时间戳均为 Unix 时间戳。
3.2 玩家用户ID
下表通过几个示例展示了玩家拥有的各种用户ID:
Account Service Provider used | Open ID | Account ID | Player ID |
---|---|---|---|
PGOS FAS | FAS ID | FAS ID | PGOS Player ID |
Steamworks SDK | Steam ID | Steam ID | PGOS Player ID |
INTL SDK (e.g. Login on Steam) | INTL Open ID | Steam ID | PGOS Player ID |
PlayFab SDK (e.g. Login on Steam) | PlayFab ID | Steam ID | PGOS Player ID |
4. 查询玩家信息
您可以一次性获取一个或多个玩家的信息。
4.1 游戏客户端
API | Description |
---|---|
GetMyInfo | 查询当前玩家的详细信息。结果以 FPlayerDetail 的形式封装。 |
GetPlayerInfo | 查询玩家信息。结果以 FPlayerInfo 的形式封装。 |
BatchGetPlayerInfo | 查询多个玩家的信息。结果以 FPlayerInfo 的形式封装。 |
API 详情:
4.1.1 GetMyInfo Client API
Interface prototype:
/**
* Query the current player's profile.
*/
void GetMyInfo(TFunction<void(const FPgosResult& Ret, const FPlayerDetail* Data)> Callback) const;
Example Code:
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{
PlayerProfile->GetMyInfo([](const FPgosResult& Ret, const FPlayerDetail* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetMyInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetMyInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
Key Error Codes
4.1.2 GetPlayerInfo Client API
Interface prototype:
/**
* Query a player's info
*
* @param PlayerId The player id to query.
*/
void GetPlayerInfo(
const FString& PlayerId,
TFunction<void(const FPgosResult& Ret, const FPlayerInfo* Data)> Callback) const;
Example Code:
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{
FString PlayerId = "197117";
PlayerProfile->GetPlayerInfo(PlayerId, [](const FPgosResult& Ret, const FPlayerInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetPlayerInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetPlayerInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
Key Error Codes
4.1.3 BatchGetPlayerInfo Client API
Interface prototype:
/**
* Query multiple players' info
*
* @param PlayerIds The player_ids to query.
*/
void BatchGetPlayerInfo(
const TArray<FString>& PlayerIds,
TFunction<void(const FPgosResult& Ret, const FClientBatchGetPlayerInfoCltRsp* Data)> Callback) const;
Example Code:
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{
TArray<FString> PlayerIds = {"197117", "197118"};
PlayerProfile->BatchGetPlayerInfo(PlayerIds, [](const FPgosResult& Ret, const FClientBatchGetPlayerInfoCltRsp* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetPlayerInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetPlayerInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
Key Error Codes
4.2 For Game Server
API | Description |
---|---|
GetPlayerInfo | 查询玩家的详细信息。结果以 FPlayerDetail 的形式封装。 |
BatchGetPlayerInfo | 查询一个或多个玩家的详细信息。结果以 FPlayerDetail 的形式封装。 |
API details:
4.2.1 GetPlayerInfo Server API
Interface prototype:
/**
* Query a player's player detail
*
* @param PlayerId The player to query.
*/
void GetPlayerInfo(
const FString& PlayerId,
TFunction<void(const FPgosResult& Ret, const FPlayerDetail* Data)> Callback) const;
Example Code:
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{
FString PlayerId = TEXT("197117");
PlayerProfile->GetPlayerInfo(PlayerId, [](const FPgosResult& Ret, const FPlayerDetail* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetPlayerInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetPlayerInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
Key Error Codes
4.2.2 BatchGetPlayerInfo Server API
Interface prototype:
/**
* Query one or more players' player detail
*
* @param PlayerIds The players to query.
*/
void BatchGetPlayerInfo(
const TArray<FString>& PlayerIds,
TFunction<void(const FPgosResult& Ret, const FServerBatchGetPlayerInfoSvrRsp* Data)> Callback) const;
Example Code:
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{
TArray<FString> PlayerIds = {TEXT("197117"), TEXT("197118")};
PlayerProfile->BatchGetPlayerInfo(PlayerIds, [](const FPgosResult& Ret, const FServerBatchGetPlayerInfoSvrRsp* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetPlayerInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetPlayerInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
Key Error Codes
5. 更新玩家信息
玩家只能更新自己的玩家信息,不能更新其他玩家的信息。
5.1 游戏客户端
API | Description |
---|---|
SetMyName | 更新当前玩家的显示名称。 |
SetMyAvatar | 更新当前玩家的头像 |
SetMyLanguage | 更新当前玩家的语言 |
SetMyGender | 更新当前玩家的性别 |
API details:
5.1.1 SetMyName Client API
玩家昵称长度限制为2至64个字符。
Interface prototype:
/**
* Update current player's display name.
*
* @param display_name Set the current player's display name. The display name length is limited to 2 to 64 characters.
* @param result_callback The result callback after the API execution ends, and it will be called in an ASYNCHRONOUS CHILD THREAD.
*/
void SetMyName(
const FString& DisplayName,
TFunction<void(const FPgosResult& Ret)> Callback) const;
Example Code:
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{
FString DisplayName = TEXT("ConfusedGirl");
PlayerProfile->SetMyName(DisplayName, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SetMyName Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SetMyName Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
5.1.2 SetMyAvatar Client API
Interface prototype:
/**
* Update the current player's avatar
*
* @param AvatarUri The new URI of the player avatar.
*/
void SetMyAvatar(
const FString& AvatarUri,
TFunction<void(const FPgosResult& Ret)> Callback) const;
Example Code:
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{
FString AvatarUri = TEXT("https://images.app.goo.gl/BD9qYfdfYPsMLXW69");
PlayerProfile->SetMyAvatar(AvatarUri, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SetMyAvatar Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SetMyAvatar Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
Key Error Codes
5.1.3 SetMyLanguage Client API
Interface prototype:
/**
* Update the current player's language
*
* @param Language The new gender.
*/
void SetMyLanguage(
const FString& Language,
TFunction<void(const FPgosResult& Ret)> Callback) const;
Example Code:
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{
FString Language = TEXT("en-GB");
PlayerProfile->SetMyLanguage(Language, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SetMyLanguage Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SetMyLanguage Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
Key Error Codes
5.1.4 SetMyGender Client API
Interface prototype:
/**
* Update the current player's gender
*
* @param Gender The new language.
*/
void SetMyGender(
const FString& Gender,
TFunction<void(const FPgosResult& Ret)> Callback) const;
Example Code:
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{
FString Gender = TEXT("female");
PlayerProfile->SetMyGender(Gender, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SetMyGender Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SetMyGender Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
Key Error Codes
6. Key Error Handling
Error Code | Relevant API | Handling Suggestion |
---|---|---|
kBackendPlayerDisplayNameContainProfanityWords | SetMyName | 提交的新玩家昵称包含不当用语。游戏可以提示玩家输入合法的显示名称。 |
kBackendPlayerDisplayNameVerificationFailed | SetMyName | 在游戏区服内玩家的玩家昵称必须是唯一的,您要设置的玩家昵称已存在。 |
kBackendDisplayNameAlreadyExists | SetMyName | 玩家受到惩罚。msg是一个JSON序列化字符串,包含截止时间(惩罚结束时的Unix时间戳(以秒为单位),小于等于0表示永久惩罚)和原因。 |
kBackendErrPlayerIsPunished | SetMyName | 玩家受到惩罚。msg是一个JSON序列化字符串,包含截止时间(惩罚结束时的Unix时间戳(以秒为单位),小于等于0表示永久惩罚)和原因。 |
kSdkNetworkError | All Network API | 网络错误,请查看错误信息了解详情。 |