MRが楽しい

MRやVRについて学習したことを書き残す

MRTK v2のドキュメントを少しずつ読み解く 入力イベント

本日は MRTKv2 の調査枠です。
MRTKv2 の Guides ドキュメントを少しずつ読み進めていきます。

MRTKv2のGuidesドキュメント

以下のドキュメントを読み進めていきます。
microsoft.github.io

以下のページでは有志による本ドキュメントの日本語翻訳が行われています。
投稿時点でこちらで未翻訳、または著者が興味のある部分について記事にしていきます。
hololabinc.github.io

本記事では以下のページを読み進めます。
microsoft.github.io
f:id:bluebirdofoz:20200215221627j:plain

入力イベント

以下のリストは、利用可能なすべての入力イベントインターフェイスの概要を示しています。
入力イベントインターフェイスはカスタムMonoBehaviorコンポーネントによって実装されています。

これらのインターフェイスはMRTK入力システムによって呼び出され、ユーザーの入力操作に基づいてアプリロジックを処理します。
デフォルトでは、スクリプトポインターによってフォーカスされている GameObject またはフォーカスされている GameObject の親である場合にのみ、入力イベントを受け取ります。









ハンドライベント説明
IMixedRealitySourceStateHandler 入力ソースの検出/ロスト 関節のある手が検出またはトラックを失ったときなど、入力ソースが検出/失われたときに発生します。
IMixedRealitySourcePoseHandler 入力ソースの姿勢変更 入力ソースの姿勢の変更で発生します。 イベントは入力ソースの一般的な姿勢を表します。 6DOFコントローラーのグリップまたはポインターポーズなどの特定のポーズは IMixedRealityInputHandler を介して取得できます。
IMixedRealityInputHandler 入力ダウン/アップ ボタンなどのバイナリ入力の変更時に発生します。
IMixedRealityInputHandler<T> 入力の変更 指定されたタイプの入力への変更で発生します。 Tは次の値を取ることができます。

IMixedRealitySpeechHandler 認識された音声キーワード Speech Commands Profileで設定されたキーワードの1つが認識されると発生します。
IMixedRealityDictationHandler ディクテーションの仮説/結果/完了/エラー ディクテーションセッションの結果を報告するためにディクテーションシステムによって発生します。
IMixedRealityGestureHandler ジェスチャーイベントの開始/更新/完了/キャンセル ジェスチャー検出で発生します。
IMixedRealityGestureHandler<T> ジェスチャーイベントの更新/完了 指定されたタイプの追加データを含むジェスチャの検出で発生します。 Tの可能な値の詳細についてはジェスチャーイベントを参照してください。
IMixedRealityHandJointHandler 手関節の更新 ハンドジョイントが更新されると、多関節ハンドコントローラーによって発生します。
IMixedRealityHandMeshHandler ハンドメッシュの更新 ハンドメッシュが更新されたときに、連結されたハンドコントローラーによって発生します。
IMixedRealityInputActionHandler アクションの開始/終了 アクションにマップされた入力のアクションの開始と終了を示すために発生します。
ポインター入力イベントは標準入力イベントタイプとわずかに異なる方法で処理されます。

アクションの入力イベント

スクリプトレベルでは、表の入力イベントインターフェイスのいずれかを実装することによって入力イベントを処理できます。
ユーザーインタラクションを介して入力イベントが発生すると、次のことが行われます。

1.MRTK入力システムは、入力イベントが発生したことを認識します。

2.MRTK入力システムは登録されたすべてのグローバル入力ハンドラーで入力イベントの関連インターフェース機能を起動します

3.入力システムに登録されているすべてのアクティブなポインターに対して以下を実行します。

3-1.入力システムは現在のポインターがフォーカスしている GameObject を決定します。

3-2.入力システムは Unity のイベントシステムを利用して、フォーカスされた GameObject 上のコンポーネントに関連するインターフェイス関数を起動します。

3-3.いずれかの時点で入力イベントが使用済みとしてマークされている場合、プロセスは終了し、それ以上の GameObject はコールバックを受け取りません。

4.グローバル入力ハンドラーが登録されておらず、一致するコンポーネント/インターフェースを持つ GameObject が見つからない場合、入力システムは各フォールバック登録済み入力ハンドラーを呼び出します

例えば、インターフェース IMixedRealitySpeechHandler を実装するコンポーネントは、音声コマンドが認識されたときに検索されます。
注意事項として、対象の GameObject で目的のインターフェイスコンポーネントが見つからない場合、UnityEvent システムはバブルアップして親 GameObject を検索します。

注意

ポインター入力イベントは上記の入力イベントインターフェイスとは少し異なる方法で処理されます。
ポインター入力イベントは入力イベントを発生させたポインターがフォーカスしているGameObjectによってのみ処理されます。
通常の入力イベントは全てのアクティブなポインターにフォーカスされている GameObjects によって処理されます。

入力イベントインターフェイスの例

以下のコードは IMixedRealitySpeechHandler インターフェースの使用方法を示しています。
この ShowHideSpeechHandler クラスを使用して GameObject に焦点を合わせながら、ユーザーが「smaller」または「bigger」という発声すると、GameObject はその大きさを半分または2倍にスケーリングします。

public class ShowHideSpeechHandler : MonoBehavior, IMixedRealitySpeechHandler
{
    ...

    void IMixedRealitySpeechHandler.OnSpeechKeywordRecognized(SpeechEventData eventData)
    {
        if (eventData.Command.Keyword == "smaller")
        {
            transform.localScale *= 0.5f;
        }
        else if (eventData.Command.Keyword == "bigger")
        {
            transform.localScale *= 2.0f;
        }
    }
}
注意

IMixedRealitySpeechHandler 入力イベントでは目的のキーワードが MRTK Speech Commands Profile に事前登録されている必要があります。

グローバル入力イベントに登録する

グローバルな入力イベントを受け取るコンポーネントを作成するには、コンポーネントを入力システムに登録する必要があります。
登録した MonoBehavior のインスタンスは現在フォーカスされてい るGameObject および、他のグローバルに登録されたリスナーとともに入力イベントを受け取ります。

入力イベントが使用済みとしてマークされている場合でも、グローバルに登録されたハンドラーは全てのコールバックを受け取ります。フォーカスされたGameObjectは使用済みのイベントを受け取りません。

public class GlobalHandListenerExample : MonoBehaviour,
    IMixedRealitySourceStateHandler, // Handle source detected and lost
    IMixedRealityHandJointHandler // handle joint position updates for hands
{
    private void OnEnable()
    {
        // Instruct Input System that we would like to receive all input events of type
        // IMixedRealitySourceStateHandler and IMixedRealityHandJointHandler
        CoreServices.InputSystem?.RegisterHandler<IMixedRealitySourceStateHandler>(this);
        CoreServices.InputSystem?.RegisterHandler<IMixedRealityHandJointHandler>(this);
    }

    private void OnDisable()
    {
        // This component is being destroyed
        // Instruct the Input System to disregard us for input event handling
        CoreServices.InputSystem?.UnregisterHandler<IMixedRealitySourceStateHandler>(this);
        CoreServices.InputSystem?.UnregisterHandler<IMixedRealityHandJointHandler>(this);
    }

    // IMixedRealitySourceStateHandler interface
    public void OnSourceDetected(SourceStateEventData eventData)
    {
        var hand = eventData.Controller as IMixedRealityHand)

        // Only react to articulated hand input sources
        if (hand != null)
        {
            Debug.Log("Source detected: " + hand.ControllerHandedness);
        }
    }

    public void OnSourceLost(SourceStateEventData eventData)
    {
        var hand = eventData.Controller as IMixedRealityHand)

        // Only react to articulated hand input sources
        if (hand != null)
        {
            Debug.Log("Source detected: " + hand.ControllerHandedness);
        }
    }

    public void OnHandJointsUpdated(
                InputEventData<IDictionary<TrackedHandJoint, MixedRealityPose>> eventData)
    {
        MixedRealityPose palmPose;
        if (eventData.InputData.TryGetValue(TrackedHandJoint.Palm, out palmPose))
        {
            Debug.Log("Hand Joint Palm Updated: " + palmPose.Position);
        }
    }
}

フォールバック入力イベントに登録する

フォールバック入力ハンドラーは入力イベント処理の最後の手段として扱われます。
グローバル入力ハンドラーが見つからず、フォーカスのあるGameObjectでも見つからない場合のみ、フォールバック入力ハンドラーが利用されます。

public class GlobalHandListenerExample : MonoBehaviour,
    IMixedRealitySourceStateHandler // Handle source detected and lost
{
    private void OnEnable()
    {
        CoreServices.InputSystem?.PushFallbackInputHandler(this);
    }

    private void OnDisable()
    {
        CoreServices.InputSystem?.PopFallbackInputHandler();
    }

    // IMixedRealitySourceStateHandler interface
    public void OnSourceDetected(SourceStateEventData eventData)
    {
        ...
    }

    public void OnSourceLost(SourceStateEventData eventData)
    {
        ...
    }
}

入力イベントを停止する方法

全ての入力イベントインターフェイスは各関数のパラメーターとして BaseInputEventData データオブジェクトを提供します。
このイベントデータオブジェクトは、Unity独自のAbstractEventDataから拡張されています。
microsoft.github.io

入力イベントがその実行を介して伝播するのを停止するために、コンポーネントは AbstractEventData.Use()を 呼び出して、イベントを使用済みとしてマークできます。
これは他のGameObjectが現在の入力イベントを受信するのを停止します。ただし、グローバル入力ハンドラーはイベントを受信します。
docs.unity3d.com

注意

Use() メソッドを呼び出すコンポーネントは、他のGameObjectがそれを受け取るのを停止します。
ただし、現在の GameObject の他のコンポーネントは引き続き入力イベントを受け取り、関連するインターフェイス関数を起動します。