本日はアプリ作成枠です。
HoloLens2でホロモンアプリを作る進捗を書き留めていきます。
今回はホロモンが指さしたところを見るメモです。
前提条件
以下の記事で検証したハンドレイのポインター座標を検出する方法を利用します。
bluebirdofoz.hatenablog.com
また、今回は手の形を「ピストル」の形にしたときのみホロモンが指さしたところを見るようにします。
手の形を検出する方法は以下の記事で紹介しています。
bluebirdofoz.hatenablog.com
実装コード
前提条件の記事で作成したスクリプトを改修し、以下のスクリプトを作成しました。
手が「ピストル」の形をしているときのみ、ポインター座標のオブジェクトを有効化します。
・HandRayTracker.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using Microsoft.MixedReality.Toolkit; using Microsoft.MixedReality.Toolkit.Utilities; using Microsoft.MixedReality.Toolkit.Input; using HoloMonApp.DataFormatSpace; namespace HoloMonApp.Player { public class HandRayTracker : MonoBehaviour, IMixedRealityHandJointHandler, IMixedRealitySourceStateHandler { [SerializeField, Tooltip("参照するハンドタイプの指定")] private Handedness p_HandednessType; [SerializeField, Tooltip("参照するハンド状態")] private ObjectFeatures p_HandFeatureRef; /// <summary> /// ポインターオブジェクトの参照 /// </summary> [SerializeField, Tooltip("ポインターオブジェクトの参照")] private GameObject p_Pointer; /// <summary> /// 現在参照中のハンドレイ /// </summary> private ShellHandRayPointer p_ShellHandRayPointer; /// <summary> /// 手の検出時に発生するイベント(IMixedRealitySourceStateHandler) /// </summary> /// <param name="eventData"></param> public void OnSourceDetected(SourceStateEventData eventData) { // 既に対象を検出済みの場合は処理しない if (p_ShellHandRayPointer != null) return; // 現在監視対象のポインターが存在するか ShellHandRayPointer handRayPointer = DetectionTargetHandRay(); if (handRayPointer == null) return; // 対象が見つかった場合参照を取得しておく p_ShellHandRayPointer = handRayPointer; } /// <summary> /// 手のロスト時に発生するイベント(IMixedRealitySourceStateHandler) /// </summary> /// <param name="eventData"></param> public void OnSourceLost(SourceStateEventData eventData) { // 既に対象を削除済みの場合は処理しない if (p_ShellHandRayPointer == null) return; // 現在監視対象のポインターが存在するか ShellHandRayPointer handRayPointer = DetectionTargetHandRay(); if (handRayPointer != null) return; // 対象が見つからなくなっている場合ロスト処理を行う p_ShellHandRayPointer = null; } /// <summary> /// 手の更新時に発生するイベント(IMixedRealityHandJointHandler) /// </summary> /// <param name="eventData"></param> public void OnHandJointsUpdated(InputEventData<IDictionary<TrackedHandJoint, MixedRealityPose>> eventData) { // 監視対象のポインターが取得済みか if (p_ShellHandRayPointer == null) return; // ハンドオブジェクトの状態を取得する ObjectStatusHand handStatus = ObjectStatusHand.Nothing; switch (p_HandednessType) { case Handedness.Right: handStatus = p_HandFeatureRef?.Features?.ObjectUnderstandFriendRightHandData?.HandStatus ?? ObjectStatusHand.Nothing; break; case Handedness.Left: handStatus = p_HandFeatureRef?.Features?.ObjectUnderstandFriendLeftHandData?.HandStatus ?? ObjectStatusHand.Nothing; break; default: break; } // 手の形がピストルでなければポインター座標は有効化しない if (handStatus != ObjectStatusHand.Hand_Pistol) { // ポインターオブジェクトを無効化する p_Pointer.SetActive(false); return; } // ポインターオブジェクトを有効化する p_Pointer.SetActive(true); // ポインターのレイキャスト座標にポインターオブジェクトを移動する Vector3 handRayPosition = p_ShellHandRayPointer?.BaseCursor?.Position ?? new Vector3(); p_Pointer.transform.position = handRayPosition; } /// <summary> /// 有効時処理 /// </summary> private void OnEnable() { // ハンドラ登録 CoreServices.InputSystem?.RegisterHandler<IMixedRealityHandJointHandler>(this); CoreServices.InputSystem?.RegisterHandler<IMixedRealitySourceStateHandler>(this); } /// <summary> /// 無効時処理 /// </summary> private void OnDisable() { // ハンドラ解除 CoreServices.InputSystem?.UnregisterHandler<IMixedRealityHandJointHandler>(this); CoreServices.InputSystem?.UnregisterHandler<IMixedRealitySourceStateHandler>(this); } // Start is called before the first frame update void Start() { // デフォルトはポインターOFF p_Pointer.SetActive(false); } // Update is called once per frame void Update() { } /// <summary> /// MRTKのInputSystemから監視対象のハンドレイポインターを取得する /// </summary> /// <returns></returns> private ShellHandRayPointer DetectionTargetHandRay() { ShellHandRayPointer handRayPointer = null; // 現在のInputSystemに対象が存在するかチェックする foreach (IMixedRealityInputSource inputSource in CoreServices.InputSystem.DetectedInputSources) { foreach (IMixedRealityPointer pointer in inputSource.Pointers) { // ハンドレイでなければ対象外 if (pointer.GetType() != typeof(ShellHandRayPointer)) continue; // 指定のハンドタイプでなければ対象外 if (((ShellHandRayPointer)pointer).Handedness != p_HandednessType) continue; handRayPointer = (ShellHandRayPointer)pointer; } } return handRayPointer; } } }