LoginSignup
6
7

More than 5 years have passed since last update.

UnityのHoloLensアプリにair-tapを実装する

Posted at

UnityEngine.VR.WSA.Input.GestureRecognizerクラスを使うと、HoloLensで一般的なair-tapジェスチャーを簡単にアプリに組み込むことができます。

使用例
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.VR.WSA.Input; // これを追加するのを忘れずに!

public class MyControl : MonoBehaviour
{
  private GestureRecognizer gesture;
  private bool airTapped;

  void Start()
  {
    gesture = new GestureRecognizer();

    // air-tapした時に呼ばれるイベント
    gestureRecognizer.TappedEvent += (InteractionSourceKind source, int tapCount, Ray headRay) =>
    {
      airTapped = true;
    };

    // ジェスチャー認識を開始
    gesture.StartCapturingGestures(); 
  }

  void Update()
  {
    // air-tap を検出したかどうか
    if (airTapped)
    {
      print("air-tap!");
      airTapped = false;
    }
  }
}

通常オブジェクトを動かしたりする処理はUpdateの中で行うと思うので、ジェスチャー検出した結果をフィールドに保持してUpdateから参照するようにしています。わざわざこうしなくてもイベントハンドラの中でオブジェクトを動かしたりすることもできます。

よくあるのがair-tapしたときに見ている方向に何かを出現させたり、見ている方向にあるオブジェクトを検出したりする処理だと思います。
gestureRecognizer.TappedEventに追加しているイベントハンドラ(InteractionSourceKind source, int tapCount, Ray headRay) => {...}の引数Ray headRayにはまさにこれを行うための視点から前方に向かうRayが渡されるので、これを使って処理しましょう。たとえば、視点の前方2メートル地点の座標が知りたければ、このようにして取得できます。

Vector3 position = headRay.GetPoint(2.0f);

視線の先に何かオブジェクトがあるかどうかを調べるにはPhysics.Raycastを使います。

RaycastHit hit;
if (Physics.Raycast(headRay, out hit))
{
  GameObject object = hit.collider.gameObject; // 検出したオブジェクト
}

デバッグ時にはUnityエディター上のマウスクリックで操作できるようにしておきつつ実機上ではair-tapで同じ処理をできるようにしたかったので、こんな感じで関数化してみました。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.VR.WSA.Input;

public class MyBehavior : MonoBehaviour
{
    private GestureRecognizer gestureRecognizer;

    void Start()
    {
        gestureRecognizer = new GestureRecognizer();
        gestureRecognizer.TappedEvent += (InteractionSourceKind source, int tapCount, Ray headRay) =>
        {
            OnClickHandler(headRay);
        };
        gestureRecognizer.StartCapturingGestures();
    }

    void Update()
    {
        // マウスクリックを検出
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            OnClickHandler(ray);
        }
    }

    private void OnClickHandler(Ray ray)
    {
        // 処理(例)

        // 視線の2メートル先の位置を取得
        Vector3 position = ray.GetPoint(2.0f);

        // マリオを出現させる (詳細は割愛)
        SpawnMario(position);
    }
}
6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7