Android
前提条件
在接入 GooglePGS 之前,请注意:虽然 GooglePGS 可与任意 Player Network 登录渠道配合使用,但建议(非必须)先配置 Google 登录(INTLGoogle 渠道),因为跨设备同步功能是为 Google 生态设计的。如需配置 INTLGoogle,请按照 Google Android 登录指南 进行操作。
此外,还需满足以下 PGS 专属前提条件:
- 从 Google Cloud Console → APIs & Services → Credentials 获取 Web 客户端 ID(server client ID)。此 ID 将用作
GOOGLEPGS_SERVER_PROJECT_ID。 - 在 Google Play Console 的 Play Games Services → Setup and management 中为您的应用启用 Google Play Games Services。
- 在项目中添加
INTLGooglePGS插件。
获取 Web 客户端 ID 和启用 Google Play Games Services 的详细分步说明,请参阅 Google Android 登录指南。
Google Play Games Services 接入
Google Play Games Services(GooglePGS)支持 PGS 登录、跨设备登录态同步,以及 PGS 成就等功能。推荐需要在 Android 设备与 Google Play 游戏电脑版之间同步登录态,或需要使用 PGS 成就功能的游戏接入。
接入 GooglePGS 需要集成 INTLGooglePGS 插件。虽然 GooglePGS 可与任意登录渠道配合使用,但通常与 INTLGoogle 搭配使用——跨设备同步功能是为 Google 生态设计的,需要 Android 设备和 Google Play 游戏电脑版登录同一个 Google 账号。
步骤1:为 GooglePGS 配置 SDK
-
在项目的 INTLConfig.ini 文件中,添加以下配置:
INTLConfig.ini[Android LifeCycle]
LIFECYCLE = GooglePGS
[GooglePGS]
GOOGLEPGS_SERVER_PROJECT_ID = {INTL_GOOGLEPGS_SERVER_PROJECT_ID}
GOOGLEPGS_ENABLE_PGS = 1
GOOGLEPGS_ENABLE_SYNC = 0
GOOGLEPGS_AUTO_ACTIVATE = 1
GOOGLEPGS_LOGIN_WITH_PGS_ON_MOBILE = 0- 将
{INTL_GOOGLEPGS_SERVER_PROJECT_ID}替换为 Web 客户端 ID。
这是 API OAuth 配置过程中 Credentials 部分中网络应用的客户端 ID,在 API OAuth 2.5 配置过程中也称为 server client ID。 GOOGLEPGS_ENABLE_PGS控制客户端侧 PGS 流程是否开启,包括 PGS 初始化、登录和欢迎气泡。设置GOOGLEPGS_ENABLE_PGS = 1为启用。
note从 V1.31 版本开始,
GOOGLEPGS_ENABLE_PGS仅控制客户端侧 PGS 流程。后台同步行为现在由GOOGLEPGS_ENABLE_SYNC单独控制。GOOGLEPGS_ENABLE_SYNC控制 SDK 是否将玩家的 OpenID 与 PGS Player ID 同步到 Player Network 后台进行绑定。此绑定可实现基于 PGS 的跨设备自动登录——当玩家在设备 A 上登录后,设备 B 可以通过 PGS Player ID 自动找到关联的 OpenID。设置GOOGLEPGS_ENABLE_SYNC = 1为启用,默认为0(禁用)。
tip如果您的游戏不需要通过 PGS 实现跨设备登录恢复,可以保持
GOOGLEPGS_ENABLE_SYNC = 0。对于未在 Player Network 管理端配置独立 PGS 渠道的游戏,建议使用此设置。-
GOOGLEPGS_AUTO_ACTIVATE控制 SDK 是否在成功登录后自动触发 PGS 初始化(非强制方式)。默认值为1(启用,与 V1.32 之前的行为一致)。如果游戏希望自行控制 PGS 初始化时机(例如避免在新手引导期间出现 PGS 提示),可设置为0。禁用后,游戏需在合适的时机手动调用ActivatePGSService。 -
GOOGLEPGS_LOGIN_WITH_PGS_ON_MOBILE控制是否允许在移动设备上使用 PGS 自动登录。默认值为0,即 PGS 自动登录仅在 Google Play 游戏电脑版上生效。设置为1可在 Android 移动设备上也启用 PGS 自动登录。
- 将
-
gradle 文件中定义
manifestPlaceholders,将{INTL_GOOGLEPGS_APPID}替换为 Google Play 游戏服务 App ID。- Unity
- Unreal Engine
mainTemplate.gradleandroid {
defaultConfig {
manifestPlaceholders = ["GOOGLEPGS_APPID":"{INTL_GOOGLEPGS_APPID}"]
}
}note对于 Player Network SDK V1.17 及更高版本,请编辑
INTLConfig_APL.xml。对于 Player Network SDK V1.16.04 及更早版本,请编辑
INTLCore_UPL.xml。<buildGradleAdditions>
<insert>
<![CDATA[
android{
defaultConfig {
manifestPlaceholders = ["GOOGLEPGS_APPID":"{INTL_GOOGLEPGS_APPID}"]
}
}]]>
</insert>
</buildGradleAdditions>
[可选] 步骤2:启用跨设备自动登录
当玩家在 Android 设备上通过任意渠道(如 Google)登录后,即可通过 GooglePGS 将登录态同步到 Google Play 游戏电脑版上。Android 设备与 Google Play 游戏电脑版需要登录同一个 Google 账号。
此步骤需要在步骤1中设置 GOOGLEPGS_ENABLE_SYNC = 1。如果未启用,OpenID 与 PGS Player ID 的绑定关系不会被创建,跨设备自动登录将无法生效。
在 Google Play 游戏电脑版上,SDK 在调用 AutoLogin() 时会自动使用 PGS 登录流程——如果未找到本地登录结果,SDK 会尝试通过玩家的 PGS Player ID 恢复会话。
- Unity
- Unreal Engine
INTLAPI.AutoLogin();
UINTLSDKAPI::AutoLogin();
[可选] 步骤3:手动触发 PGS 登录
通过其他渠道(如 Google)成功登录后,SDK 会自动在后台触发一次非强制 PGS 登录。在此自动流程中,SDK 会初始化 PGS 并展示 PGS 欢迎弹窗,然后检查玩家的 PGS 认证状态:
- 如果已认证:SDK 继续请求服务端授权码,用于 PGS 身份绑定。
- 如果未认证:SDK 静默跳过 PGS 登录,不会向玩家展示登录界面。
在设备上有 Google 账号的情况下,应用首次启动时,PGS v2 可能会展示登录或创建档案的提示,这是 PGS 平台自身的引导流程。此提示由 PGS 初始化(PlayGamesSdk.initialize())触发,而非 SDK 的 signIn() 调用,不受 SDK 控制。在后续启动中,PGS 会静默认证(如果玩家之前已完成登录)或保持未认证状态而不展示任何界面。如果设备上没有 Google 账号,即使首次启动也不会出现此提示。
如果需要从游戏侧显式触发 PGS 登录(例如让玩家关联 PGS 身份),可以调用 ActivatePGSService 接口。此接口仅支持 Android,接受一个 forceSignIn 参数:
ActivatePGSService(true)— 强制登录(默认值)。如果 PGS 未认证,SDK 会调用signIn()向玩家展示 Google PGS 登录界面。ActivatePGSService(false)— 非强制登录。与自动流程行为一致:如果 PGS 未认证,SDK 静默跳过,不展示任何界面。
调用时,SDK 将:
- 执行前置检查:验证
GOOGLEPGS_ENABLE_PGS = 1、Activity 有效、Google Play Services 可用。如果任一检查失败,将通过认证结果回调返回错误。 - 初始化 PGS 并检查玩家是否已通过 PGS 认证:
- 如果已认证:SDK 直接请求服务端授权码,用于 PGS 身份绑定。
- 如果未认证(强制):SDK 会调用
signIn()向玩家展示 Google PGS 登录界面。如果玩家成功完成登录,SDK 继续请求授权码。如果玩家关闭界面或登录失败,将通过认证结果回调返回错误。 - 如果未认证(非强制):SDK 静默跳过 PGS 登录,不展示任何界面,并通过认证结果回调返回错误。
PGS 身份绑定(OpenID ↔ PGS Player ID)仅在 GOOGLEPGS_ENABLE_SYNC = 1 时才会发送到 Player Network 后台。如果未启用,ActivatePGSService 会完成 PGS 认证,但不会创建跨设备绑定关系。
从 V1.32 开始,如果 GOOGLEPGS_AUTO_ACTIVATE = 0,SDK 不会在登录后自动初始化 PGS。游戏应在合适的时机调用 ActivatePGSService:
ActivatePGSService(false)— 触发与自动路径相同的非强制流程(展示欢迎气泡,未认证时静默跳过)。ActivatePGSService(true)— 强制登录,未认证时展示 PGS 登录界面。
- Unity
- Unreal Engine
// 非强制:与自动流程行为一致
INTLAPI.ActivatePGSService(false);
// 强制:未认证时展示 PGS 登录界面
INTLAPI.ActivatePGSService(true);
// 非强制:与自动流程行为一致
UINTLSDKAPI::ActivatePGSService(false);
// 强制:未认证时展示 PGS 登录界面
UINTLSDKAPI::ActivatePGSService(true);
图片:PGS 初始化成功后显示的欢迎气泡
图片:当玩家尚未认证时调用 ActivatePGSService(true) 显示的 PGS 登录界面
验收测试
完成 PGS 接入后,请验证以下场景:
- PGS 自动初始化:登录后,确认 PGS 欢迎气泡出现(当
GOOGLEPGS_ENABLE_PGS = 1且GOOGLEPGS_AUTO_ACTIVATE = 1时)。 - 跨设备同步:在 Android 设备上设置
GOOGLEPGS_ENABLE_SYNC = 1并登录,然后在 Google Play 游戏电脑版上使用同一 Google 账号启动游戏——玩家应自动登录,无需重新输入凭据。 - 手动 PGS 登录:调用
ActivatePGSService(true),确认当玩家尚未认证时 PGS 登录界面出现。
GooglePGS 配置参考
| 配置项 | 默认值 | 说明 |
|---|---|---|
GOOGLEPGS_SERVER_PROJECT_ID | — | Google Cloud Console OAuth 凭证中的 Web 客户端 ID(server client ID)。必填。 |
GOOGLEPGS_ENABLE_PGS | 0 | 启用客户端侧 PGS 流程(初始化、登录、欢迎气泡)。 |
GOOGLEPGS_ENABLE_SYNC | 0 | 将玩家的 OpenID 与 PGS Player ID 同步到 Player Network 后台进行绑定,以实现跨设备自动登录。 |
GOOGLEPGS_AUTO_ACTIVATE | 1 | 控制 SDK 是否在成功登录后自动触发 PGS 初始化。设置为 0 可手动控制时机。 |
GOOGLEPGS_LOGIN_WITH_PGS_ON_MOBILE | 0 | 允许在移动设备上使用 PGS 自动登录(不仅限于 Google Play 游戏电脑版)。 |
Google PGS 成就系统
Player Network SDK 提供了成就模块,集成了 Google Play Games Services 成就功能。游戏可以通过此模块解锁成就、增加进度以及展示原生成就界面。
从 V1.32.01 版本开始,所有成就接口均使用立即(服务器确认)变体。回调中的 RetCode 反映实际的服务器结果,IncrementAchievement 会在 ExtraJson 中返回 {"newly_unlocked": true/false}。错误处理也已标准化:RetCode 现在使用标准 INTL 错误码(如 NEED_LOGIN、INVALID_ARGUMENT),而不再返回 UNKNOWN 并在 ThirdCode 中使用自定义错误码。在 V1.32.01 之前的版本中,仅有 UnlockAchievement、IncrementAchievement 和 ShowAchievements 可用,且 UnlockAchievement 和 IncrementAchievement 使用即发即弃调用——回调会立即返回成功,但不会确认操作已在服务器上完成。
前提条件
- 完成上述 GooglePGS 配置,并设置
GOOGLEPGS_ENABLE_PGS = 1。 - 在 Google Play Console 的 Play Games Services > Setup and management > Achievements 中配置成就。
- 调用任何成就接口前,PGS 必须已认证。如果 PGS 未认证,接口将通过回调返回
NEED_LOGIN错误。当GOOGLEPGS_ENABLE_PGS = 1时,SDK 会在成功登录后自动认证 PGS,也可以通过ActivatePGSService手动触发。
注册成就回调
注册回调以接收成就操作结果。
- Unity
- Unreal Engine
// 添加成就回调
INTLAPI.AddAchievementResultObserver(OnAchievementResult);
// 移除成就回调
INTLAPI.RemoveAchievementResultObserver(OnAchievementResult);
// 处理成就结果
public void OnAchievementResult(INTLAchievementResult ret)
{
Debug.Log($"Achievement MethodID: {ret.MethodId}, RetCode: {ret.RetCode}");
}
// 注册成就回调
FINTLAchievementEvent achievementObserver;
achievementObserver.AddUObject(this, &UMyClass::OnAchievementResult);
UINTLSDKAPI::SetAchievementResultObserver(achievementObserver);
// 移除成就回调
UINTLSDKAPI::GetAchievementResultObserver().Clear();
void UMyClass::OnAchievementResult(FINTLAchievementResult ret)
{
UE_LOG(LogTemp, Log, TEXT("Achievement MethodID: %d, RetCode: %d"), ret.MethodId, ret.RetCode);
}
解锁成就
通过成就 ID 解锁一个标准(非增量)成就。如果该成就已解锁,调用仍然成功,但不会改变其状态。
结果通过成就回调返回,MethodId = 2701。不返回 ExtraJson。
- Unity
- Unreal Engine
INTLAPI.UnlockAchievement("GooglePGS", "achievement_id_here");
UINTLSDKAPI::UnlockAchievement(TEXT("GooglePGS"), TEXT("achievement_id_here"), TEXT("{}"));
增加成就进度
对于增量成就,按指定步数增加进度。numSteps 参数必须大于 0。如果新的总步数达到或超过成就所需步数,则成就被解锁。
结果通过成就回调返回,MethodId = 2702。ExtraJson 字段包含 {"newly_unlocked": true/false},表示此次调用是否导致成就被解锁。
- Unity
- Unreal Engine
INTLAPI.IncrementAchievement("GooglePGS", "achievement_id_here", 1);
UINTLSDKAPI::IncrementAchievement(TEXT("GooglePGS"), TEXT("achievement_id_here"), 1, TEXT("{}"));
展示成就界面
展示 Google Play Games 原生成就界面。该界面以独立 Activity 的形式叠加在游戏上方显示。
结果通过成就回调返回,MethodId = 2703。不返回 ExtraJson。
- Unity
- Unreal Engine
INTLAPI.ShowAchievementsUI("GooglePGS");
UINTLSDKAPI::ShowAchievementsUI(TEXT("GooglePGS"), TEXT("{}"));
图片:显示在游戏上方的 Google Play Games 原生成就界面
查询成就列表
V1.32.01 及以上版本可用。查询当前玩家的所有成就,包括成就状态(UNLOCKED、REVEALED、HIDDEN)、类型(STANDARD、INCREMENTAL)、步进度和名称。在 extraJson 中传入 {"force_reload": true} 可绕过本地缓存,强制从服务器重新加载。
结果通过成就回调返回,MethodId = 2704。ExtraJson 字段包含以下结构的 JSON 对象:
{
"achievements": [
{
"id": "achievement_id",
"state": "UNLOCKED", // UNLOCKED | REVEALED | HIDDEN
"type": "STANDARD", // STANDARD | INCREMENTAL
"current_steps": 5, // 仅 INCREMENTAL 类型
"total_steps": 10, // 仅 INCREMENTAL 类型
"last_updated_timestamp": 1234567890,
"name": "Achievement Name"
}
],
"is_stale": false // 数据是否来自缓存
}
- Unity
- Unreal Engine
// 使用缓存(默认)
INTLAPI.QueryAchievementList("GooglePGS");
// 强制从服务器重新加载
INTLAPI.QueryAchievementList("GooglePGS", "{\"force_reload\": true}");
// 使用缓存(默认)
UINTLSDKAPI::QueryAchievementList(TEXT("GooglePGS"), TEXT("{}"));
// 强制从服务器重新加载
UINTLSDKAPI::QueryAchievementList(TEXT("GooglePGS"), TEXT("{\"force_reload\": true}"));
设置成就步数
V1.32.01 及以上版本可用。将增量成就的完成步数设置为至少一个目标值。与 IncrementAchievement(增加步数)不同,此接口直接设置进度——如果当前步数已经等于或大于目标值,成就保持不变。如果目标值达到或超过总步数,则成就被解锁。
结果通过成就回调返回,MethodId = 2705。ExtraJson 字段包含 {"newly_unlocked": true/false},表示此次调用是否导致成就被解锁。
- Unity
- Unreal Engine
INTLAPI.SetAchievementSteps("GooglePGS", "achievement_id_here", 5);
UINTLSDKAPI::SetAchievementSteps(TEXT("GooglePGS"), TEXT("achievement_id_here"), 5, TEXT("{}"));
揭示成就
V1.32.01 及以上版本可用。向玩家揭示一个隐藏的成就。揭示后,该成就在成就界面中变为可见,但在玩家完成其要求之前仍处于未解锁状态。
结果通过成就回调返回,MethodId = 2706。
- Unity
- Unreal Engine
INTLAPI.RevealAchievement("GooglePGS", "achievement_id_here");
UINTLSDKAPI::RevealAchievement(TEXT("GooglePGS"), TEXT("achievement_id_here"), TEXT("{}"));
成就接口参考
| 接口 | 参数 | 说明 |
|---|---|---|
UnlockAchievement | channel、achievementId、extraJson(可选) | 解锁一个标准成就。 |
IncrementAchievement | channel、achievementId、numSteps(Unity)/ Progress(UE)、extraJson(可选) | 增加增量成就的进度。 |
ShowAchievementsUI | channel、extraJson(可选) | 展示原生成就界面。 |
QueryAchievementList | channel、extraJson(可选) | 查询所有成就及其当前状态。 |
SetAchievementSteps | channel、achievementId、numSteps(Unity)/ Progress(UE)、extraJson(可选) | 将增量成就的步数设置为目标值。 |
RevealAchievement | channel、achievementId、extraJson(可选) | 向玩家揭示一个隐藏成就。 |
AddAchievementResultObserver(Unity) | callback | 注册成就结果回调。 |
RemoveAchievementResultObserver(Unity) | callback | 移除已注册的成就结果回调。 |
SetAchievementResultObserver(UE) | FINTLAchievementEvent& | 注册成就结果委托。 |
GetAchievementResultObserver(UE) | — | 返回委托对象;调用 .Clear() 可移除。 |
成就结果数据
INTLAchievementResult(Unity)/ FINTLAchievementResult(UE)包含:
| 字段 | 类型 | 说明 |
|---|---|---|
MethodId | int | 触发此结果的方法(2701=解锁,2702=增加进度,2703=展示界面,2704=查询列表,2705=设置步数,2706=揭示)。 |
RetCode | int | 结果码。0 表示成功。 |
SubRetCode | int | 二级结果码(V1.28 起可用)。 |
RetMsg | string | 结果消息。 |
ThirdCode | int | 原始 Google Play Games Services 状态码。仅在 RetCode 为 9999(THIRD)时填充,表示错误来源于 PGS。参见 GamesClientStatusCodes。 |
ThirdMsg | string | 当 ThirdCode 有值时为可读的 PGS 状态字符串,或错误详情消息。 |
ExtraJson | string | 额外结果数据(JSON 格式)。具体内容请参阅各接口章节。 |
Platform | string | 成就提供方名称,如 "GooglePGS"。 |
SeqId | string | 请求的序列 ID。 |
验收测试
完成成就接入后,请验证以下场景:
图片:PGS 成就界面,从上到下依次为标准锁定成就、增量锁定成就和隐藏成就
- 解锁成就:对一个标准成就调用
UnlockAchievement,验证回调返回MethodId = 2701且RetCode = 0。确认该成就在成就界面中已解锁。 - 增加成就进度:对一个增量成就调用
IncrementAchievement,验证回调返回MethodId = 2702且RetCode = 0。检查ExtraJson中包含{"newly_unlocked": true/false}。 - 展示成就界面:调用
ShowAchievementsUI,验证回调返回MethodId = 2703且RetCode = 0。确认 Google Play Games 原生成就界面已展示。 - 查询成就列表:调用
QueryAchievementList,验证成就回调返回MethodId = 2704且RetCode = 0。检查ExtraJson中包含achievements数组,且其中的状态、类型和步数数据有效。 - 设置成就步数:对一个增量成就调用
SetAchievementSteps,验证回调返回MethodId = 2705且RetCode = 0。检查ExtraJson中包含{"newly_unlocked": true/false}。 - 揭示成就:对一个隐藏成就调用
RevealAchievement,验证回调返回MethodId = 2706且RetCode = 0。确认该成就在成就界面中变为可见。
故障排查
本节分享在接入和测试 Google Play 游戏服务过程中发现的常见问题,以及如何验证和解决这些问题的指导。
PGS 接入问题
-
验证 PGS 配置和签名证书
确认 Play 游戏服务关联了正确的 OAuth 客户端。关联的 OAuth 客户端必须包含:
- 正在测试的应用的包名
- 用于签署通过 Google Play 分发的应用的 SHA-1 证书指纹
如果启用了 Google Play 应用签名,请验证应用签名证书,而非仅验证开发证书或上传证书。
如果 OAuth 客户端使用了不同的包名或 SHA-1 指纹,PGS 后台请求可能会失败,即使界面显示操作成功。例如,登录提示可能仍然出现,成就也可能似乎已解锁并显示解锁提示;然而,成就最终可能无法正确同步,甚至可能恢复到锁定状态。此错误可能不会在游戏日志或 INTL SDK 日志中显示。
有关更多信息,请参见 Play 游戏服务凭据。
-
验证账号是否为 PGS 测试用户
在 PGS 配置和成就发布之前,确认用于测试的 Google 账号已被添加为授权 PGS 测试人员。
还需确认:
- Google Play 游戏使用的账号是已添加到测试人员列表中的账号。
- 该账号有权访问适用的测试发布。
- 安装的构建属于预期的包名和 PGS 项目。
- 如果设备上存在多个 Google 账号,是否选择了正确的账号。
成就问题
-
等待并观察
成就更新可能不会立即显示在 Google Play 游戏界面或不同游戏会话中。调用成就 API 后,请等待更新生效,然后刷新或重启相关会话,再判断操作是否失败。
在等待上一次更新显示期间,避免重复提交同一操作。
-
验证成就 ID
确认
achievement_id与 Google Play 管理中心中的值完全一致。成就 ID 区分大小写,应始终直接从管理中心复制,而非手动输入。例如,包含大写字母
I的 ID 可能被误读为包含小写字母l:正确:CgkI_***********I****
错误:Cgkl_***********l****还需检查:
- 首尾是否有空格
- 字母大小写是否被改变
- 字母是否与视觉上相似的数字混淆
- 是否复制了来自其他 PGS 项目或应用的 ID
-
检查成就发布状态
草稿成就可用于测试成就操作、回调、进度更新和解锁行为。但是,解锁草稿成就不会授予 XP。
在开发期间将成就保持为草稿状态,以便可以重置其解锁状态进行重复测试。不要仅为了验证 XP 而在游戏及其 PGS 集成准备上线之前发布成就。
报告 PGS 问题时,请在私密调试频道中以纯文本形式提供完整的相关 ID(如成就 ID),以及应用包名、构建来源、签名证书 SHA-1 指纹和测试人员状态。不要仅通过截图提供 ID。