# Oculus (Meta Quest)

> Provide an Oculus sign-in option to enable players to authenticate using their Meta Quest accounts on virtual reality platforms.

###### SDK 最低版本：2.3.1##minimum-sdk-version-231

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

* 设置 Oculus 登录
* 回归用户登录或创建新用户。
* 将用户从匿名登录更新为通过自定义 ID 提供商进行平台登录。

要在您的游戏中为玩家提供 Oculus 登录选项，请在 [Oculus Developer Dashboard](https://developer.oculus.com/manage) 中创建应用，并记录您的 App ID 和 App Secret 以及 nonce 和 userId 值。

请参阅以下部分来添加包：

## 设置 Oculus 登录

将 Oculus 设置为 Unity Authentication 的 ID 提供商：

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

您可以将以下代码作为示例，了解如何检索登录的 Oculus 用户并生成一次性密码。

1. 戴上头盔，然后访问 **Settings（设置）**> **System（系统）**> **Developer（开发者）**。
2. 启用 **USB Connection Dialog（USB 连接对话框）** 选项。
3. 使用 USB-C 线缆将头盔连接到计算机上。
4. 此时会显示提示，要求访问数据，请单击 **Allow（允许）**。
5. 为确保设备连接成功，请打开您的 Unity 项目并导航至 **File（文件）**> **Build Settings（构建设置）**。在 **Platform（平台）** 列表中，选择 **Android** 并单击 **Switch Platform（切换平台）**。
6. 在 **Run Device（运行设备）** 列表中，选择 Oculus 头盔。如果列表中没有头盔，请单击 **Refresh（刷新）**，刷新选项。
7. 设置并安装位于[此处](https://assetstore.unity.com/packages/tools/integration/oculus-integration-82022)的 Oculus Integration 软件包，此外，您也可以从 [Oculus 开发者中心](https://developer.oculus.com/documentation/unity/unity-import/#import-from-dev-center)查找该软件包。
8. 从编辑器的菜单栏导入到项目中后，请访问 **Oculus** > **Platform（平台）**> **Edit Settings（编辑设置）**。您需要输入您的 Oculus App ID。

```cs
using UnityEngine;
using Oculus.Platform;
using Oculus.Platform.Models;

public class OculusAuth : MonoBehaviour
{
    private string userId;

    private void Start()
    {
        Core.AsyncInitialize().OnComplete(OnInitializationCallback);
    }

    private void OnInitializationCallback(Message<PlatformInitialize> msg)
    {
        if (msg.IsError)
        {
            Debug.LogErrorFormat("Oculus: Error during initialization. Error Message: {0}",
                msg.GetError().Message);
        }
        else
        {
            Entitlements.IsUserEntitledToApplication().OnComplete(OnIsEntitledCallback);
        }
    }

    private void OnIsEntitledCallback(Message msg)
    {
        if (msg.IsError)
        {
            Debug.LogErrorFormat("Oculus: Error verifying the user is entitled to the application. Error Message: {0}",
                msg.GetError().Message);
        }
        else
        {
            GetLoggedInUser();
        }
    }

    private void GetLoggedInUser()
    {
        Users.GetLoggedInUser().OnComplete(OnLoggedInUserCallback);
    }

    private void OnLoggedInUserCallback(Message<User> msg)
    {
        if (msg.IsError)
        {
            Debug.LogErrorFormat("Oculus: Error getting logged in user. Error Message: {0}",
                msg.GetError().Message);
        }
        else
        {
            userId = msg.Data.ID.ToString(); // do not use msg.Data.OculusID;
            GetUserProof();
        }
    }

    private void GetUserProof()
    {
        Users.GetUserProof().OnComplete(OnUserProofCallback);
    }

    private void OnUserProofCallback(Message<UserProof> msg)
    {
        if (msg.IsError)
        {
            Debug.LogErrorFormat("Oculus: Error getting user proof. Error Message: {0}",
                msg.GetError().Message);
        }
        else
        {
            string oculusNonce = msg.Data.Value;
            // Authentication can be performed here
        }
    }
}
```

**注意**：您的 Oculus 头盔必须处于开发者模式。您可以登录要用于开发的开发者帐户实现此操作（您可以在[此处](https://developer.oculus.com/sign-up/)创建 Oculus 开发者帐户）。

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

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

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

如果您的项目中没有与凭据关联的 Unity Authentication 玩家帐户，`SignInWithOculusAsync` 将创建新的玩家帐户。如果您的项目中具有与凭据关联的 Unity Authentication 玩家帐户，`SignInWithOculusAsync` 将登录该玩家帐户。

该功能不考虑缓存的玩家帐户，`SignInWithOculusAsync` 会替换缓存的玩家帐户。

```cs
async Task SignInWithOculusAsync(string nonce, string userId)
{
  try
  {
    await AuthenticationService.Instance.SignInWithOculusAsync(nonce, userId);
    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);
  }
}
```

## 将玩家帐户从匿名更新为 Oculus 帐户##updating-a-player-from-anonymous-to-an-oculus-account

在您设置完匿名身份验证后，如果玩家想从匿名升级为 Oculus 帐户，并通过 Oculus 登录，您应在游戏中引导玩家触发 Oculus 登录并从 Oculus 获取会话工单。然后，调用 `LinkWithOculusAsync` API，将玩家帐户与 Oculus 会话票证关联。

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

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

```cs
async Task LinkWithOculusAsync(string nonce, string userId)
{
  try
  {
    await AuthenticationService.Instance.LinkWithOculusAsync(nonce, userId);
    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 (Exception ex)
  {
    Debug.LogError(“Link failed.”);
    Debug.LogException(ex);
  }
}
```

## 取消 Oculus 帐户关联##unlink-oculus-account

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

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