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);
}
}