HoloLens 用に Navigate ジェスチャで 3D オブジェクトを配置する Unity アプリを作る
※ これは 2016/04/27 Unity HoloLens Technical Preview ver.5.4.0beta14(Windows版) 時点の情報です
最新版では動作が異なる可能性がありますのでご注意ください
前回は回り込んでくるねこの動きを作りましたが、今度は下記の動画にも出てくるようなドラッグ的な動作(Manipuration または Navigation)を試す実装を作ってみたいと思います
今回は Navigation(相対的な座標移動)ジェスチャを検知して 3D ボールを落とす動作を作ります
HoloLens のジェスチャは UnityEngine.VR.WSA.Input.GestureRecognizer を利用すれば簡単に検知できます
GestureRecognizer.StartCapturingGestures() メソッドを呼び出すことでジェスチャを検知できるようになり、NavigationStartedEvent でドラッグの開始、NavigationUpdatedEvent でドラッグ中、NavigationCompletedEvent でドラッグ完了、NavigationCanceledEvent でキャンセル時のイベントハンドラを指定できるようです
この API を利用して書いてみたのが下記のコード
using UnityEngine; using UnityEngine.VR.WSA.Input; /// <summary> /// ボール生成ビヘイビア /// </summary> public class BallCreater : MonoBehaviour { /// <summary> /// HoloLens Gesture Recognizer /// </summary> private GestureRecognizer recognizer; /// <summary> /// ボールのモデル /// </summary> [SerializeField] private GameObject ballPrefab; /// <summary> /// ボールを追いかけるネコ /// </summary> [SerializeField] private BallChaser chaser; /// <summary> /// ボールのインスタンス /// </summary> private GameObject ball; /// <summary> /// カメラ /// </summary> private Camera mainCamera; /// <summary> /// Navigation 中フラグ /// </summary> private bool navigationStarting = false; /// <summary> /// 初期処理 /// </summary> public void Awake() { this.mainCamera = Camera.main; this.recognizer = new GestureRecognizer(); this.recognizer.NavigationStartedEvent += this.OnNavigationStarted; this.recognizer.StartCapturingGestures(); this.chaser.Ball = null; } /// <summary> /// Navigation ジェスチャの開始 /// </summary> /// <param name="source">入力種別</param> /// <param name="normalizedOffset">標準化座標移動量</param> /// <param name="headRay">頭の向き</param> private void OnNavigationStarted(InteractionSourceKind source, Vector3 normalizedOffset, Ray headRay) { this.navigationStarting = false; this.chaser.Ball = null; this.recognizer.NavigationUpdatedEvent += this.OnNavigationUpdated; this.recognizer.NavigationCompletedEvent += this.OnNavigationCompleted; if (this.ball != null) { Destroy(this.ball); this.ball = null; } this.ball = Instantiate<GameObject>(this.ballPrefab); this.MoveBall(normalizedOffset); } /// <summary> /// Navigation ジェスチャの移動 /// </summary> /// <param name="source">入力種別</param> /// <param name="normalizedOffset">標準化座標移動量</param> /// <param name="headRay">頭の向き</param> private void OnNavigationUpdated(InteractionSourceKind source, Vector3 normalizedOffset, Ray headRay) { this.navigationStarting = true; this.MoveBall(normalizedOffset); } /// <summary> /// Navigation ジェスチャの完了 /// </summary> /// <param name="source">入力種別</param> /// <param name="normalizedOffset">標準化座標移動量</param> /// <param name="headRay">頭の向き</param> private void OnNavigationCompleted(InteractionSourceKind source, Vector3 normalizedOffset, Ray headRay) { this.navigationStarting = false; this.recognizer.NavigationUpdatedEvent -= this.OnNavigationUpdated; this.recognizer.NavigationCompletedEvent -= this.OnNavigationCompleted; this.MoveBall(normalizedOffset); this.ReleaseBall(); } /// <summary> /// ボールの移動 /// </summary> /// <param name="normalizedOffset">標準化座標移動量</param> private void MoveBall(Vector3 normalizedOffset) { this.ball.transform.position = this.mainCamera.transform.position + this.mainCamera.transform.forward * 1.8f + normalizedOffset / 4f; if (this.ball.transform.position.y < 0.3f) { this.ball.transform.position = new Vector3(this.ball.transform.position.x, 0.3f, this.ball.transform.position.z); } } /// <summary> /// ボールを落とす /// </summary> private void ReleaseBall() { this.ball.GetComponent<Rigidbody>().useGravity = true; this.chaser.Ball = this.ball; } }
BallChaser は落としたボールを追いかけるような動作を記述したコードで今回は割愛
Navigation のジェスチャでボールをドラッグ移動させ、リリースして Navigation を完了した際にボールを落としてねこ(きじとら)に追いかけさせるようにしてみました
実機がないためジェスチャの移動量調整は適当なんですが、すんなりドラッグ(エミュレーター上ではマウスの右ボタンドラッグ)によるボール落下位置の指定はできました