# Unity Player Accounts

> Use Unity's comprehensive sign-in solution that provides persistent accounts across games, devices, and platforms.

## 概览##overview

Unity Player Accounts 是 Unity 全面的登录解决方案，广泛适用于各种游戏、设备和平台。这是一种端到端帐户系统，其中包含用户流程 UX、电子邮件和密码、社交平台登录选项、数据访问和删除流程。

Unity Player Accounts 与 Unity Gaming Services 集成，是继匿名方式、Apple、Google、Facebook、Steam 之后，Authentication 支持的又一身份提供商，具有 SSO 优势、组织级别玩家池，以及跨游戏、跨设备或跨平台游玩等优势。

| 技术特性                           | 描述                                                                                                                          |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------- |
| 与 Unity Gaming Services 和编辑器集成 | Player Accounts 是即时可用的登录和身份解决方案，适用于 Unity Gaming Services 和 Unity 生态系统。它与 Authentication 无缝集成，可提供更多功能，如组织级别玩家识别信息。          |
| 跨平台和跨设备                        | 您的玩家可以通过各种平台（包括 iOS、Android、Windows 和 Mac）注册和登录您的游戏。                                                                        |
| 跨游戏                            | 利用组织级别玩家识别信息，为您的所有游戏维护一致的玩家配置文件。                                                                                            |
| 简化的用户注册和登录体验                   | 您的玩家可以根据自己的喜好，灵活选择注册或登录帐户的方式，如电子邮件和密码，以及社交媒体帐户（如 Google 或 Apple）。                                                           |
| 流畅的登录流程                        | 为尽量简化初次登录体验，允许您的玩家匿名开启游戏，之后升级为使用玩家帐户，其间不会丢失任何游戏进度。此外，借助单点登录 (SSO)，玩家登录一次，即可访问所有支持此 Player Accounts 的游戏，而无需重新输入凭据。           |
| 集成一次，一劳永逸                      | 我们基于浏览器的注册和登录流程会自动更新加入新功能，而无需针对您的游戏进行任何集成或更新。专心构建和运行您的游戏，无需重新集成身份验证解决方案。完成集成后，您可以依靠 Player Accounts，紧跟更新步伐，不断纳入全新安全改进措施和功能。 |

## 开始使用##get-started

### 安装 SDK##set-up-the-unity-player-accounts-id-provider

为 Unity 安装全新的 Authentication 软件包：

1. 在 Unity 编辑器中，打开 **Window（窗口）**> **Package Manager（包管理器）**。
2. 在 Package Manager（包管理器）中，选择 **Unity Registry（Unity 注册表）** 列表视图。
3. 搜索 **Authentication**，或者在软件包列表中查找。
4. 选择该包，然后选择 **Install（安装）**。

如需了解更多信息，请参阅 [Package Manager（包管理器）](https://docs.unity3d.com/Manual/upm-ui.html)文档。

### 设置 Unity Player Accounts##before-you-publish-your-game

您可以直接在 Unity Dashboard 设置 Unity Player Accounts。

使用 Unity Player Accounts 之前，请确保您已拥有以下各项：

| 名称          | 描述                                                                           |
| ----------- | ---------------------------------------------------------------------------- |
| 服务条款链接      | 应用程序的服务条款，在登录应用程序（首次登录）的同意步骤中以链接显示。注意：此链接在初始设置阶段为可选设置，但您需要在应用启动之前提供一个服务条款链接。 |
| 隐私政策链接      | 应用程序的隐私政策，在登录应用程序（首次登录）的同意步骤中以链接显示。注意：此链接在初始设置阶段为可选设置，但您需要在应用启动之前提供一个隐私政策链接。 |
| OAuth 客户端名称 | OAuth 客户端的名称。该名称在同意步骤显示给用户，所以要能够识别，比如集成应用程序的名称。                              |
| 平台          | 支持的平台。Unity Player Accounts 支持 iOS/Android 和 Windows。                        |

### 游戏发布前注意事项##unity-player-accounts-sample

查看 Unity 合规性指南和品牌指南

* 必须为玩家提供一种方式，以请求删除和披露应用程序及其 Unity Player 帐户的数据。
* 包含可跳转至 [Unity Player Accounts 帐户删除页面](https://player-account.unity.com/)的链接。
* 包含可跳转至 [Unity Player Accounts 隐私支持电子邮件](mailto:unity-player-login-privacy@unity3d.com)的链接，以供发起数据披露或其他隐私请求。
* 包含可跳转至[电子邮件](mailto:unity-player-login-privacy@unity3d.com)的链接，以供发起数据披露或其他隐私请求。
* 必须始终确保遵守 [Unity 服务条款](https://unity.com/legal/terms-of-service)。
* 必须始终维护、展示和遵守一项明确的隐私政策。该政策要适当地披露给终端用户，遵守所有适用的隐私和数据保护法律法规，并授予 Unity 使用 Unity Player Accounts 服务所需的必要权利。

### 服务和隐私条款

确保在 Unity Dashboard 提供服务和隐私条款链接。

## SDK 集成##sign-in-a-returning-player-or-create-new-player

### 设置 Unity Player Accounts 登录

在安装软件包后，请在编辑器菜单中选择 **Services（服务）> Authentication > Player Account Settings（玩家帐户设置）**。

> **Note:**
>
> **注意**：该资源创建在 `Assets/Resources` 路径下。

添加以下值（在启用后获得）：

* **Client ID（客户端 ID）**
* **Scope（作用域）**（可选。All（全部）或 Empty（空）代表所有允许的作用域）
* **Use Custom Deep Link Uri（使用自定义深层链接 Uri）**（可选。覆盖默认的深层链接 URI）

> **Note:**
>
> **注意**：只要注册的 URI 采用以下规定格式，身份验证流无需配置重定向 URI 即可运行：
>
> * 桌面/独立平台：`http://localhost/callback`
> * Android/IOS 默认深层链接 URI：`unitydl://com.unityplayeraccounts.{unity-project-id}`

#### Unity Player Accounts 样本

> **Note:**
>
> **注意**：样本建立在标准 Unity 输入系统的基础上。启用输入管理器或两个输入系统。在 Unity 编辑器中，访问 **Edit（编辑）**> **Project Settings（项目设置）**> **Player（玩家）**> **Other Settings（其他设置）**> **Active Input Handling（有效输入处理）**。

* 选择 **Window（窗口）> Package Manager（包管理器）** 以导入样本。查找 **Authentication** 并选择 **Samples（示例）** 下的 **Import（导入）**。

* 打开 **Assets（资源）> Samples（示例）> Authentication > \[包版本号] > UI Example（UI 示例）> UnityPlayerAccountsUIExample** 路径下的示例场景。

#### 与 Unity Authentication 服务集成

为 Unity Authentication 配置 Unity Player 帐户 ID 提供商：

1. 在 Unity 编辑器菜单中，访问 **Edit（编辑）> Project Settings...（项目设置...）**，然后从导航菜单中选择 **Services（服务）> Authentication（身份验证）**。
2. 选择 **Go to Dashboard（前往后台）**，打开 Authentication 身份提供商网页。
3. 在网页中选择 **Add Identity Provider（添加身份提供商）**，并选择 **Unity Player Accounts**。
4. 设置提供商，在弹出窗口中选择 **Add provider（添加提供商）**。
5. 返回到 Unity 编辑器中的 **Services（服务）> Authentication**，然后选择 **Refresh（刷新）**。此时将显示 **Unity Player Accounts** ID 提供商。
6. 在 Unity 编辑器中，导航至 **Services（服务）> Authentication > Player Account Settings（玩家帐户设置）**，并确保 Client ID（客户端 ID）设置正确。
7. 运行先前导入的包示例场景 **UnityPlayerAccountsUIExample**。

> **Note:**
>
> **注意**：通过订阅 `SignedIn` 事件，可确保在用户成功登录到他们的 Unity Player 帐户，并收到所需的访问令牌时，您的登录方法得到调用。

```cs
void Awake()
{
   PlayerAccountService.Instance.SignedIn += SignInWithUnity;
}
```

### 回归玩家登录或创建新玩家

使用 `SignInWithUnityAsync` 方法执行以下操作之一：

* 通过 Unity Player Accounts 凭据创建新的 Unity Authentication 玩家。
* 通过 Unity Player Accounts 凭据登录现有玩家。

```cs
 async Task SignInWithUnityAsync(string accessToken)
        {
            try
            {
                await AuthenticationService.Instance.SignInWithUnityAsync(accessToken);
                Debug.Log("SignIn is successful.");
            }
            catch (AuthenticationException ex)
            {
                // Compare error code to AuthenticationErrorCodes
                // Notify the player with the proper error message
                Debug.LogException(ex);
            }
            catch (RequestFailedException ex)
            {
                // Compare error code to CommonErrorCodes
                // Notify the player with the proper error message
                Debug.LogException(ex);
            }
        }
```

### 将玩家从匿名更新为 Unity Player 帐户

在您设置完匿名身份验证后，如果玩家想从匿名升级为 Unity Player 帐户并登录，您应在游戏中引导玩家触发 Unity Player Accounts 登录并从 Unity Player Accounts 获取访问令牌。然后，调用 `LinkWithUnityAsync` API，将玩家帐户与 Unity Player 帐户访问令牌关联。

如果 SDK 上有缓存的玩家帐户，您可以将缓存的玩家帐户与 Unity Player 帐户关联。

1. 通过 `SignInAnonymouslyAsync` 登录缓存玩家的帐户。
2. 通过 `LinkWithUnityAsync` 将缓存的玩家帐户与 Unity Player 帐户关联。

```cs
async Task LinkWithUnityAsync(string accessToken)
        {
            try
            {
                await AuthenticationService.Instance.LinkWithUnityAsync(accessToken);
                Debug.Log("Link is successful.");
            }
            catch (AuthenticationException ex) when (ex.ErrorCode == AuthenticationErrorCodes.AccountAlreadyLinked)
            {
                // Prompt the player with an error message.
                Debug.LogError("This user is already linked with another account. Log in instead.");
            }

            catch (AuthenticationException ex)
            {
                // Compare error code to AuthenticationErrorCodes
                // Notify the player with the proper error message
                Debug.LogException(ex);
            }
            catch (RequestFailedException ex)
            {
                // Compare error code to CommonErrorCodes
                // Notify the player with the proper error message
                Debug.LogException(ex);
            }
        }
```

## 取消 Unity Player 帐户关联##link-a-returning-player-to-unity-player-accounts

使用 `UnlinkUnityAsync` API 可以取消玩家帐户与其 Unity Player 帐户的关联。一旦取消关联，如果玩家帐户不再关联到任何其他身份，则会转换为匿名帐户。

```cs
async Task UnlinkUnityAsync(string idToken)
{
   try
   {
       await AuthenticationService.Instance.UnlinkUnityAsync(idToken);
       Debug.Log("Unlink is successful.");
   }
   catch (AuthenticationException ex)
   {
       // Compare error code to AuthenticationErrorCodes
       // Notify the player with the proper error message
       Debug.LogException(ex);
   }
   catch (RequestFailedException ex)
   {
       // Compare error code to CommonErrorCodes
       // Notify the player with the proper error message
       Debug.LogException(ex);
   }
}
```
