# Apple Game Center

> Provide an Apple Game Center sign-in option to enable players to authenticate using their Game Center accounts on Apple platforms.

###### SDK 最低版本：2.4.0##minimum-sdk-version-240

本文将引导您完成以下场景，为您游戏中使用 Apple Game Center 玩家标识符的玩家设置身份验证：

* 设置 Apple Game Center 登录
* 回归用户登录或创建新用户。
* 将用户从匿名登录更新为通过 Apple Game Center 帐户进行平台登录。

要为您的游戏玩家提供 Apple Game Center 登录选项，请对您的应用进行设置以启用 Apple Game Center 登录。

您可以直接在 Unity 编辑器中添加 Apple Game Center，也可以在 [Unity Dashboard](https://cloud.unity.com/) 中添加。

## 设置 Apple Game Center 登录

1. 设置并安装 Apple Game Kit Unity 插件，该插件位于 [Apple Unity Plug-ins](https://github.com/apple/unityplugins) 代码仓库。[GameKit](https://developer.apple.com/documentation/gamekit) 框架用于实现 Apple Game Center 功能，包括玩家身份。

2. 将 Apple Game Center 添加为 Unity 的 ID 提供商：

   1. 在 Unity 编辑器菜单中，访问 **Edit（编辑）**> **Project Settings…（项目设置…）**，然后从导航菜单中选择 **Services（服务）**> **Authentication（身份验证）**。
   2. 将 **ID Providers（ID 提供商）** 设置为 **Apple Game Center**，然后选择 **Add（添加）**。
   3. 在 Apple 开发者控制台中找到 **Bundle ID**，输入到 **Bundle ID** 文本字段中，然后选择 **Save（保存）**。Bundle ID 示例：“**com.something.somethingelse**”。

注意：参考的软件包并非由 Unity 开发、拥有或运营。请参考关于使用非 Unity 软件包的[最佳实践](/authentication/approaches-to-authentication.md.md)。

> **Warning:**
>
> **重要**：对于 Unity Authentication，出于安全原因，时间戳输入只在 10 分钟内有效。在调用 SignInWithAppleGameCenterAsync 或 LinkWithAppleGameCenterAsync 之前，请先调用 Apple FetchItems API 来接收新输入。在成功调用一次 SignInWithAppleGameCenterAsync 或 LinkWithAppleGameCenterAsync 之后，无需再次调用这些 API。

在安装完必要的插件并设置好 ID 提供商之后，您可以使用以下代码示例检索用于身份验证的参数：

```cs
using System;
using System.Threading.Tasks;
using UnityEngine;
using Apple.GameKit;

public class AppleGameCenterExampleScript : MonoBehaviour
{
    string Signature;
    string TeamPlayerID;
    string Salt;
    string PublicKeyUrl;
    string Timestamp;

    // Start is called before the first frame update
    async void Start()
    {
        await Login();
    }

    public async Task Login()
    {
        if (!GKLocalPlayer.Local.IsAuthenticated)
        {
            // Perform the authentication.
            var player = await GKLocalPlayer.Authenticate();
            Debug.Log($"GameKit Authentication: player {player}");

            // Grab the display name.
            var localPlayer = GKLocalPlayer.Local;
            Debug.Log($"Local Player: {localPlayer.DisplayName}");

            // Fetch the items.
            var fetchItemsResponse =  await GKLocalPlayer.Local.FetchItems();

            Signature = Convert.ToBase64String(fetchItemsResponse.GetSignature());
            TeamPlayerID = localPlayer.TeamPlayerId;
            Debug.Log($"Team Player ID: {TeamPlayerID}");

            Salt = Convert.ToBase64String(fetchItemsResponse.GetSalt());
            PublicKeyUrl = fetchItemsResponse.PublicKeyUrl;
            Timestamp = fetchItemsResponse.Timestamp.ToString();

            Debug.Log($"GameKit Authentication: signature => {Signature}");
            Debug.Log($"GameKit Authentication: publickeyurl => {PublicKeyUrl}");
            Debug.Log($"GameKit Authentication: salt => {Salt}");
            Debug.Log($"GameKit Authentication: Timestamp => {Timestamp}");
        }
        else
        {
            Debug.Log("AppleGameCenter player already logged in.");
        }
    }
}
```

## 回归玩家登录或创建新玩家##sign-in-a-returning-player-or-create-new-player

您可以使用 `SignInWithAppleGameCenterAsync` 方法执行以下操作之一：

* 通过 Apple Game Center 凭据创建新的 Unity Authentication 玩家帐户。
* 通过 Apple Game Center 凭据登录现有玩家帐户。

如果您的项目中没有与凭据关联的 Unity Authentication 玩家帐户，`SignInWithAppleGameCenterAsync` 将创建新的玩家帐户。如果您的项目中具有与凭据关联的 Unity Authentication 玩家帐户，`SignInWithAppleCenterAsync` 将登录该玩家帐户。该功能不考虑缓存的玩家帐户，`SignInWithAppleGameCenterAsync` 会替换缓存的玩家帐户。

```cs
async Task SignInWithAppleGameCenterAsync(string signature, string teamPlayerId, string   publicKeyURL, string salt, ulong timestamp)
{
    try
    {
        await AuthenticationService.Instance.SignInWithAppleGameCenterAsync(signature, teamPlayerId, publicKeyURL, salt, timestamp);
        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);
    }
}
```

## 将玩家帐户从匿名更新为 Apple Game Center 帐户##updating-a-player-from-anonymous-to-an-apple-game-center-account

在您设置完匿名身份验证后，如果玩家想从匿名升级为 Apple Game Center 帐户，并通过 Apple Game Center 登录，您应在游戏中引导玩家触发 Apple Game Center 登录并从 GameKit 获取 ID 验证参数。然后，调用 `LinkWithAppleGameCenterAsync` API，将玩家帐户与 Apple Game Center teamPlayerID 关联。

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

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

```cs
async Task LinkWithAppleGameCenterAsync(string signature, string teamPlayerId, string   publicKeyURL, string salt, ulong timestamp)
{
    try
    {
        await AuthenticationService.Instance.LinkWithAppleGameCenterAsync(signature, teamPlayerId, publicKeyURL, salt, timestamp);
        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);
    }
}
```

## 取消 Apple Game Center 帐户关联##unlink-apple-game-center-account

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

```cs
async Task UnlinkAppleGameCenterAsync(string idToken)
{
   try
   {
       await AuthenticationService.Instance.UnlinkAppleGameCenterAsync(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);
   }
}
```
