HoloLens チュートリアル (Holograms 101E - 3 Gestures)


## はじめに

「[HoloLens チュートリアル (Holograms 101E - 2 Gaze) - Qiita](http://qiita.com/Suna/items/f1bc81063cfc4d75c72d)」の続きになります。
「[Holograms 101E: Introduction with Emulator](https://developer.microsoft.com/ja-jp/windows/holographic/holograms_101e)」の「[Chapter 3 - Gestures](https://developer.microsoft.com/JA-JP/WINDOWS/HOLOGRAPHIC/holograms_101e#chapter_3_-_gestures)」を試してみます。

## チュートリアル「Gestures」

### GazeGestureManager の作成

#### C# スクリプトの作成

![601b.png](https://qiita-image-store.s3.amazonaws.com/0/20418/2511c149-f4ad-7ef8-06f5-c6a606b3c709.png "601b.png")

- Project パネルから 「Scripts」 を選択
- 右クリックを押下し、 **「Create」-「C# Script」** を選択
- 名前を「GazeGestureManager」に変更

![602.png](https://qiita-image-store.s3.amazonaws.com/0/20418/542841d3-2e2f-40ca-6d8f-37e4e55a3cd7.png "602.png")

- 作成した「GazeGestureManager」を、Hierarchy パネルの「OrigamiCollection」オブジェクトにドロップ
- 「GazeGestureManager」をダブルクリック (-> Visual Studio が起動)

---

#### C# スクリプトの編集

![604.png](https://qiita-image-store.s3.amazonaws.com/0/20418/01c00717-a494-2095-ede5-664763e0dbd5.png "604.png")

```C#:GazeGestureManager.cs
using UnityEngine;
using UnityEngine.VR.WSA.Input;

public class GazeGestureManager : MonoBehaviour
{
    public static GazeGestureManager Instance { get; private set; }

    // Represents the hologram that is currently being gazed at.
    public GameObject FocusedObject { get; private set; }

    GestureRecognizer recognizer;

    // Use this for initialization
    void Start()
    {
        Instance = this;

        // Set up a GestureRecognizer to detect Select gestures.
        recognizer = new GestureRecognizer();
        recognizer.TappedEvent += (source, tapCount, ray) =>
        {
            // Send an OnSelect message to the focused object and its ancestors.
            if (FocusedObject != null)
            {
                FocusedObject.SendMessageUpwards("OnSelect");
            }
        };
        recognizer.StartCapturingGestures();
    }

    // Update is called once per frame
    void Update()
    {
        // Figure out which hologram is focused this frame.
        GameObject oldFocusObject = FocusedObject;

        // Do a raycast into the world based on the user's
        // head position and orientation.
        var headPosition = Camera.main.transform.position;
        var gazeDirection = Camera.main.transform.forward;

        RaycastHit hitInfo;
        if (Physics.Raycast(headPosition, gazeDirection, out hitInfo))
        {
            // If the raycast hit a hologram, use that as the focused object.
            FocusedObject = hitInfo.collider.gameObject;
        }
        else
        {
            // If the raycast did not hit a hologram, clear the focused object.
            FocusedObject = null;
        }

        // If the focused object changed this frame,
        // start detecting fresh gestures again.
        if (FocusedObject != oldFocusObject)
        {
            recognizer.CancelGestures();
            recognizer.StartCapturingGestures();
        }
    }
}
```

- [GestureRecognizer](https://docs.unity3d.com/ScriptReference/VR.WSA.Input.GestureRecognizer.html)

> Manager class with API for recognizing user gestures.

- [GestureRecognizer.TappedEvent](https://docs.unity3d.com/ScriptReference/VR.WSA.Input.GestureRecognizer.TappedEvent.html)

> Occurs when a Tap gesture is recognized.

- [GestureRecognizer.StartCapturingGestures](https://docs.unity3d.com/550/Documentation/ScriptReference/VR.WSA.Input.GestureRecognizer.StartCapturingGestures.html)

> Call to begin receiving gesture events on this recognizer. No events will be received until this method is called.

- [GestureRecognizer.CancelGestures](https://docs.unity3d.com/ScriptReference/VR.WSA.Input.GestureRecognizer.CancelGestures.html)

> Cancels any pending gesture events. Additionally this will call StopCapturingGestures.

- [GameObject.SendMessageUpwards](https://docs.unity3d.com/ja/current/ScriptReference/GameObject.SendMessageUpwards.html)

> ゲームオブジェクトと親（の親、さらに親 ... ）にアタッチされているすべての MonoBehaviour にある methodName と名付けたメソッドを呼び出します

---

### ShpereCommands の作成

#### C# スクリプトの作成

- Project パネルから 「Scripts」 を選択
- 右クリックを押下し、 **「Create」-「C# Script」** を選択
- 名前を「SphereCommands」に変更

![603.png](https://qiita-image-store.s3.amazonaws.com/0/20418/f1c8e288-edcb-b67e-a479-2dcda09115da.png "603.png")

- 作成した「ShpereCommands」を、Hierarchy パネルの「OrigamiCollection」-「Sphere1」「Spere2」オブジェクトにドロップ
- 「ShpereCommands」をダブルクリック (-> Visual Studio が起動)

---

#### C# スクリプトの編集

```C#:SphereCommands.cs
using UnityEngine;

public class SphereCommands : MonoBehaviour
{
    // Called by GazeGestureManager when the user performs a Select gesture
    void OnSelect()
    {
        // If the sphere has no Rigidbody component, add one to enable physics.
        if (!this.GetComponent<Rigidbody>())
        {
            var rigidbody = this.gameObject.AddComponent<Rigidbody>();
            rigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous;
        }
    }
}
```

- [Rigidbody](https://docs.unity3d.com/ja/current/Manual/class-Rigidbody.html)

> Rigidbody を使うと、__ゲームオブジェクト__を物理特性によって制御する事ができるようになります。

- [Rigidbody.collisionDetectionMode](https://docs.unity3d.com/ja/current/ScriptReference/Rigidbody-collisionDetectionMode.html)

> Rigidbody の衝突検出モード。Rigidbody の継続的な衝突判定を設定するためにこれを使用します。 

- [CollisionDetectionMode.Continuous](https://docs.unity3d.com/ja/current/ScriptReference/CollisionDetectionMode.Continuous.html)

> このモードは静的メッシュジオメトリと衝突しているときに検出されるようになります。

---

### Visual Studio のプロジェクト生成

- 「File」メニューから「Build Settings」を選択
- 「Build Settings」ウィンドウから「Build」ボタンを押下

---

### ビルド・実行環境設定の確認、実行

- ソリューション構成 **「Release」**
- プラットフォーム **「X86」**
- 実行環境 **「HoloLens Emulator」**
- 「デバッグ」メニューから **「デバッグなしで開始」** を選択

---

### エミュレータ操作

![605.png](https://qiita-image-store.s3.amazonaws.com/0/20418/94cfbb94-91bf-d9b6-50dd-43f934964db9.png "605.png")

![606.png](https://qiita-image-store.s3.amazonaws.com/0/20418/971e3224-cbaf-865f-7143-9b8d376fe5e1.png "606.png")

Gaze のマークを Sphere に合わせて、スペースボタンを押すと、Sphere がポロリと落ちて、台の上を転がって、台からも落ちていきます。