# Facebook

> Provide a Facebook sign-in option to enable players to authenticate using their Facebook accounts in your game.

###### SDK 最低版本：2.0.0##minimum-sdk-version-200

本文将引导您完成以下场景，为您游戏中使用 Facebook 帐户的玩家设置身份验证：

> **Note:**
>
> **注意**：下方代码示例的前提为，您已经有玩家 Facebook 访问令牌。
>
> * 设置 Facebook 帐户登录
> * 回归用户登录或创建新用户。
> * 将用户从匿名登录更新为通过 Facebook 帐户进行平台登录。

要在您的游戏中为玩家提供 Facebook 登录选项，请在 Facebook Developer Portal 中创建应用，并安装 [Facebook Unity SDK](https://developers.facebook.com/docs/unity/downloads)，以登录用户帐户，获取访问令牌。

## 设置 Facebook 帐户登录

在以下步骤中，我们假设您已经设置好 Facebook 应用。

1. 根据 [Facebook 入门文档](https://developers.facebook.com/docs/unity/gettingstarted)设置和安装 Facebook SDK。

2. 将 Facebook 添加为 Unity Authentication 的 ID 提供商：

   1. 在 Unity 编辑器菜单中，访问 **Edit（编辑）**> **Project Settings…（项目设置…）**，然后从导航菜单中选择 **Services（服务）**> **Authentication（身份验证）**。
   2. 将 **ID Providers（ID 提供商）** 设置为 **Facebook**，然后单击 **Add（添加）**。
   3. 在 App ID（应用 ID）文本字段中输入应用 ID（在步骤 1 中获得）。
   4. 在 **App Secret（应用密钥）** 文本字段中输入应用密钥，然后单击 **Save（保存）**。

3. [使用此示例代码](https://developers.facebook.com/docs/unity/examples#login)实现 Facebook 登录。

   > **Note:**
   >
   > **注意**：Unity Authentication SDK 目前不支持快速登录令牌。

> **Note:**
>
> **注意**：根据[此 GitHub 问题](https://github.com/facebook/facebook-sdk-for-unity/issues/537)所述，Facebook SDK 在运行模式下无法与 Unity 2021.1 兼容。解决方法是，[使用此拉取请求](https://github.com/facebook/facebook-sdk-for-unity/pull/539/files)构建新的 Facebook.Unity.dll。

> **Note:**
>
> 目前，我们支持“消费类”和“商业”应用类型。

```cs
using System.Collections.Generic;
using UnityEngine;

// Other needed dependencies
using Facebook.Unity;

public class FacebookExampleScript : MonoBehaviour
{
    public string Token;
    public string Error;

    // Awake function from Unity's MonoBehaviour
    void Awake()
    {
        if (!FB.IsInitialized)
        {
            // Initialize the Facebook SDK
            FB.Init(InitCallback, OnHideUnity);
        }
        else
        {
            // Already initialized, signal an app activation App Event
            FB.ActivateApp();
        }
    }

    void InitCallback()
    {
        if (FB.IsInitialized)
        {
            // Signal an app activation App Event
            FB.ActivateApp();
            // Continue with Facebook SDK
        }
        else
        {
            Debug.Log("Failed to Initialize the Facebook SDK");
        }
    }

    void OnHideUnity(bool isGameShown)
    {
        if (!isGameShown)
        {
            // Pause the game - we will need to hide
            Time.timeScale = 0;
        }
        else
        {
            // Resume the game - we're getting focus again
            Time.timeScale = 1;
        }
    }

    public void Login()
    {
        // Define the permissions
        var perms = new List<string>() { "public_profile", "email" };

        FB.LogInWithReadPermissions(perms, result =>
        {
            if (FB.IsLoggedIn)
            {
                Token = AccessToken.CurrentAccessToken.TokenString;
                Debug.Log($"Facebook Login token: {Token}");
            }
            else
            {
                Error = "User cancelled login";
                Debug.Log("[Facebook Login] User cancelled login");
            }
        });
    }
}
```

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

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

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

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

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

## 将玩家帐户从匿名更新为 Facebook 帐户##update-a-player-from-anonymous-to-a-facebook-account

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

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

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

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

如果玩家通过登录或创建新玩家配置文件而触发 Facebook 登录，并且您已收到 Facebook 访问令牌，调用以下 API 来对玩家进行身份验证。

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

## 实现 Facebook 登录身份验证##implement-a-facebook-sign-in-authentication

如果玩家通过登录或创建新玩家帐户而触发 Facebook 登录，并且您已收到 Facebook 访问令牌，调用以下 API 来实现玩家登录：`SignInWithFacebookAsync(string accessToken)`

## 取消 Facebook 帐户关联##unlink-facebook-account

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

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