nreal developerページをざっと読んでみた (Controller編)

前回は[ImageTracking編](https://qiita.com/iwaken71/items/d7cc1edb84713c9c4a24)

今回はController編で
https://developer.nreal.ai/develop/unity/controller
を見ていきます！

Nreal Light controllerとNreal phone controller2つありますが、チュートリアルでは**Nreal Light controller**の方を見ていくみたいです。

# Introduction (導入)

Nreal Light controllerは、Bluetoothを介してNreal Lightコンピューティングユニットまたは携帯電話とペアリングできます。

Nreal phone controllerは、電話をNreal Lightのコンピューティングユニットとして使用する場合にのみ使用できます。

現在、開発者が利用できるのはNreal Light controller（Nreal Developer Kitで入手可能）だけです。Nreal phone controllerは将来使えるようになります。

# How to Use the Nreal Light Controller(使い方)

![image.png](https://nreal-public.nreal.ai/developer/img/controller01.jpg)

**表**

| 特徴 | 説明 |
|:--|:--|
| 3DoF Tracking | 3 degrees of freedom |
| Touchpad | 押す = Tigger ボタン. タッチ、スワイプ、クリックを検知できる. カスタマイズ可能(スクロールなど) |
| App Button | 通常押し=コントローラの再調整。長押し時の動作はカスタマイズ可能です(メニューを開くなど) |
| Home Button | 長押し=Nreal Launcherを開きます。通常押し時の動作はカスタマイズ可能です|
| LED Light | コントローラーのステータスを表します|

**裏**

| 特徴 | 説明 |
|:--|:--|
| Charging pins | 下向きの3本の充電ピンは、コントローラーをコンピューティングユニットに接続します。 また、計算ユニットからコントローラにデータを送信するためにも使用されます。|
| Power Switch | Nreal Lightコントローラーのオン/オフスイッチは、充電スポットの下にあります。 緑は電源がオン、赤は電源がオフであることを意味します。 |

**Nreal Light Controller LED Guide (LEDの意味)**

コントローラーとユニットの接続とバッテリーを表しているようです。
緑であれば接続しているので、使用するときは確認しましょう。

![](https://nreal-public.nreal.ai/developer/img/controller02.gif)

## Connecting the Nreal Light Controller(接続しよう)

1. Neal LightコンピューティングユニットまたはAndroid携帯電話のBluetoothがオンになっていることを確認します。 （Nreal LightコンピューティングユニットのBluetoothはデフォルトでオンになっています。）

2. Nreal Lightコントローラーの電源スイッチをオンにします。 緑色のライトが点滅し始めるまで、タッチパッドを押し続けます。

3. Nreal Lightコントローラーをコンピューティングユニットに置くと、自動的にペアリングされます。

4. ペアリングが成功すると、LEDの点滅が止まり、緑色に点灯します。 この手順を完了できない場合は、Bluetoothレコードリスト内の他のすべてのコントローラーを削除して、再試行してください。

## Charging the Nreal Light Controller (充電しよう)

こんな感じでくっつければ充電されます。
![](https://nreal-public.nreal.ai/developer/img/controller03.gif)

## How to Use Your Phone as a Controller(携帯をコントローラーにしよう)

![](https://nreal-public.nreal.ai/developer/img/controller04.jpg)

各ボタンの機能はNreal Light Controllerと同じです！

## Tutorial： Nreal Light Controller(やってみよう)

### Input in Unity (これだけは覚えとこう)

- ControllerProvider
    - 様々なコントローラーの情報(回転、ボタン押下、ジャイロなど)をNRInputに提供する
- EventSystem
    - Unityの標準EventSystemとの統合し、ユーザインタラクションを可能にする。
        - UnityのEventSystemとは別みたい
    - NRIputは、アプリケーションの実行時に自動的にEventSystemを生成します。
- Visualizations
    - コントローラー、Ray、レチクルのビジュアライズの機能はデフォルトであります。
    
### Enabling NRInput (NRInputを使えるようにする)

ここからは https://developer.nreal.ai/develop/unity/controller もちゃんと見つつ進めよう。

1. NRInputプレハブをシーンに追加
2. NRInputのインスペクターのOverride Camera Centerの項目に、Center Cameraオブジェクトをドラッグ&ドロップする
3. これでNreal Light controllersを使ったインタラクションをユーザが体験することができるようになりました。

### Raycast Modes in NRInput (Raycastモードが2つあるよ)

Raycastingには**Gaze(視線)モード**と**Rayモード**の2つある。

- **Gaze(視線)モード**
    - レイキャストはユーザーの額の中心から始まり、前方に放射します。 したがって、光線は見えなくなります。
- **Rayモード**
    - 光線はコントローラーの中心から始まります。
    
### Current Controller Features (現在のコントローラの特徴取得)

NRSDKは複数のタイプのコントローラーをサポートするため、現在のコントローラーがサポートする機能を理解するのに役立つメソッドがスクリプト化されています。

**サンプル**

```
    bool supportsPosition = NRInput.GetControllerAvailableFeature(ControllerAvailableFeature.CONTROLLER_AVAILABLE_FEATURE_POSITION);
    bool supportsGyro = NRInput.GetControllerAvailableFeature(ControllerAvailableFeature.CONTROLLER_AVAILABLE_FEATURE_GYRO);
```
Nreal Light controllerとNreal phone controllerどちらを使っているか気にせず特徴を取得しています。

### Some Common Usage of NRInput(一般的な使い方)

```csharp

void Update()
    {
        //returns a int value of how many available controllers currently
        NRInput.GetAvailableControllersCount();

        //returns true if a Trigger button is currently pressed
        NRInput.GetButton(ControllerButton.TRIGGER);

        //returns true if a Trigger button was pressed down this frame
        NRInput.GetButtonDown(ControllerButton.TRIGGER);

        //returns true if a Trigger button was released this frame
        NRInput.GetButtonUp(ControllerButton.TRIGGER);

        //returns Vector3.zero if controller is 3DoF, otherwise returns the position of the domain controller
        NRInput.GetPosition();

        //returns the rotation of the domain controller
        NRInput.GetRotation();

        //returns the ControllerType of the domain controller
        ControllerType controllerType = NRInput.GetControllerType();

        //returns a Vector2 value of the touchpad, x(-1f ~ 1f), y(-1f ~ 1f);
        NRInput.GetTouch();

        //returns a Vector3 value of gyro if supports
        NRInput.GetGyro();

        //to get what hand mode is using now, left-hand or right-hand
        ControllerHandEnum domainHand = NRInput.DomainHand;

        //the same as NRInput.GetRotation()
        NRInput.GetRotation(NRInput.DomainHand);

        //returns the rotaion of the left hand controller
        NRInput.GetRotation(ControllerHandEnum.Right);
    }
```

### Get Frequently Used Anchors (アンカーの取得)

サンプル

```
    Transform gazeAnchor = NRInput.AnchorsHelper.GetAnchor(ControllerAnchorEnum.GazePoseTrackerAnchor);
    Transform leftRayAnchor = NRInput.AnchorsHelper.GetAnchor(ControllerAnchorEnum.LeftRayAnchor);
```

### Raycasters in NRInput (レイキャスト)

- 3つのRaycastがNRInputプレハブに含まれています。
    - 1つがGazeモード用で、2つがRayモード用です。
- raycasterクラスはUnityのBaseRaycasterクラスを継承しています
- 選択したレイキャスターの最も遠いレイキャスティング距離は、インスペクターから直接変更できます
    - そのマスクのパラメーターを変更することで、どのオブジェクトを操作可能にするかをLayerで定義することもできます。 
    

![](https://nreal-public.nreal.ai/developer/img/controller06.jpg)

## Building a Project with User Input (インプットを用いたプロジェクトをビルドしよう)

- 目標
    - コントローラーを立方体に向けると、その色が緑に変わります。
    - トリガーボタンを押すと、キューブの色がランダムに変化します。
    - 立方体はコントローラーと共に回転します。
    - UGUIボタンを押して、回転のために立方体をアクティブまたは非アクティブにします。


###  最終アウトプット
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96970/c6343705-6cce-8210-b2c2-7a0824cbab38.png)

コントローラからのRayでCubeを選択したり、ボタンを押すことができます。

### 注意点

基本[Building a Project with User Input](https://developer.nreal.ai/develop/unity/controller)の通り進めてください。
しかし、一つ罠があります。

途中で登場するCubeInteractiveTest.csは、usingを正しく書かないとエラーが出ます。次のように書きましょう。

```csharp:CubeInteractiveTest.cs
using UnityEngine;
using UnityEngine.EventSystems; //忘れない
using NRKernal; //忘れない

public class CubeInteractiveTest : MonoBehaviour, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler
{
    private MeshRenderer m_MeshRender;
    void Awake () {
        m_MeshRender = GetComponent<MeshRenderer>();
    }

    void Update()
    {
        //get controller rotation, and set the value to the cube transform
        transform.rotation = NRInput.GetRotation();
    }

//when pointer click, set the cube color to random color
    public void OnPointerClick(PointerEventData eventData)
    {
        m_MeshRender.material.color = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f));
    }

//when pointer hover, set the cube color to green
    public void OnPointerEnter(PointerEventData eventData)
    {
        m_MeshRender.material.color = Color.green;
    }

//when pointer exit hover, set the cube color to white
    public void OnPointerExit(PointerEventData eventData)
    {
        m_MeshRender.material.color = Color.white;
    }
}

```

# Next Step

次はDesign Guide編です！見てね