ポインター

ポインター

この記事では、ポインター アーキテクチャと比較して、実際にポインター入力を構成して応答する方法 について説明します

ポインターは、新しいコントローラーが検出されると、実行時に自動的にインスタンス化されます。 1 つのコントローラーに複数のポインターをアタッチできます。 たとえば、既定のポインター プロファイルでは、Windows Mixed Realityコントローラーは、それぞれ通常の選択とテレポートの行と放物線ポインターの両方を取得します。

ポインターの構成

ポインターは、 を介して MRTK の入力システムの一部として構成されます MixedRealityPointerProfile 。 この種類のプロファイルは MixedRealityInputSystemProfile 、MRTK 構成インスペクターで に割り当てられます。 ポインター プロファイルは、カーソル、実行時に使用できるポインターの種類、およびそれらのポインターが相互に通信して、アクティブなポインターを決定する方法を決定します。

  • Pointing Extent - ポインターが GameObject と対話できる最大距離を定義します。

  • [Pointing Raycast Layer Masks]/( レイキャスト レイヤー マスクのポイント) - これは、指定されたポインターが対話できる GameObject の可能性と試行する操作の順序を決定するための、LayerMasks の優先順位付けされた配列です。 これは、ポインターが他のシーン オブジェクトの前に UI 要素と最初に対話する場合に役立つ場合があります。 ポインター プロファイルの例

ポインター オプションの構成

既定の MRTK ポインター プロファイル構成には、次のポインター クラスと関連するプレハブが既定で含まれています。 実行時にシステムで使用できるポインターの一覧は、ポインター プロファイルの [ポインター オプション ] で定義されます。 開発者は、この一覧を利用して、既存のポインターの再構成、新しいポインターの追加、または削除を行います。

ポインター オプション プロファイルの例

各ポインター エントリは、次のデータ セットによって定義されます。

  • コントローラーの 種類 - ポインターが有効なコントローラーのセット。

    • たとえば 、FingerePointer は指でオブジェクトを "突き付け"、既定では多関節ハンド コントローラーの種類のみをサポートするとしてマークされます。 ポインターは、コントローラーが使用可能になったときにのみインスタンス化されます。特に、コントローラーの種類によって、このポインター プレハブを作成できるコントローラーが定義されます。
  • Handedness - 特定の手 (左/右) に対してインスタンス化されるだけの ポインターを許可します

注意

ポインター エントリ の Handedness プロパティを None に設定すると、リストからそのポインターを削除する代わりに、実質的にシステムから無効になります。

  • ポインター プレハブ - このプレハブ資産は、指定されたコントローラーの種類と手渡しに一致するコントローラーの追跡が開始されるとインスタンス化されます。

コントローラーに複数のポインターを関連付けすることができます。 たとえば、 DefaultHoloLens2InputSystemProfile (Assets/MRTK/SDK/Profiles/HoloLens2/) では、多関節ハンド コントローラーは 、、GrabPointer、および DefaultControllerPointer (つまり、 ハンド レイ)。

注意

MRTK は 、Assets/MRTK/SDK/Features/UX/Prefabs/Pointers にポインター プレハブのセットを提供しますAssets/MRTK/SDK/Features/UX/Scripts/Pointers または を実装するその他のスクリプトにポインター スクリプトが含まれている限り、新しいカスタム プレハブを構築できます IMixedRealityPointer

既定のポインター クラス

次のクラスは、上で説明した既定の MRTK ポインター プロファイルで使用可能で定義されている既定の MRTK ポインターです。 Assets/MRTK/SDK/Features/UX/Prefabs/Pointers の下に用意されている各ポインター プレハブには、アタッチされているポインター コンポーネントの 1 つが含まれています。

MRTK の既定のポインター

遠方ポインター

LinePointer

基本ポインター クラスである LinePointer は、入力のソース (コントローラー) からポインターの方向に線を描画し、この方向に 1 つの光線キャストをサポートします。 一般に、 や テレポート ポインターなどの子クラスは、主に一般的な機能を提供するこのクラスではなく、インスタンス化され、利用されます (テレポートが終了する場所を示す線も描画されます)。 ShellHandRayPointer

Oculus、Vive、Windows Mixed Reality のようなモーション コントローラーの場合、回転はコントローラーの回転と一致します。 多関節手などの他HoloLens 2の場合、回転はシステムが提供する手の指し示し姿勢と一致します。

MRTK Pointer Line
CurvePointer

CurvePointer は 、曲線に沿った複数ステップのレイ キャストを可能にすることで 、LinePointer クラスを拡張します。 この基本ポインター クラスは、線が一貫して放物線に曲がるテレポート ポインターなどの曲線インスタンスに役立ちます。

ShellHandRayPointer

から拡張 される ShellHandRayPointer の実装は、MRTK ポインター プロファイル の既定値 LinePointer として使用されますDefaultControllerPointer プレハブ は、 クラスを実装 ShellHandRayPointer します。

GGVPointer

視線入力/ジェスチャ /音声 (GGV) ポインターとも呼ばれる GGVPointer は、主に視線入力とエア タップまたは視線入力と音声選択操作を介して、HoloLens 1 スタイルの外観とタップの相互作用を機能します。 GGV ポインターの位置と方向は、頭の位置と回転によって駆動されます。

TouchPointer

TouchPointer は、Unity Touch 入力 (つまり、タッチスクリーン) の操作を担当します。 これらは "遠い相互作用" です。画面に触れる操作によって、カメラからシーン内の可能性のある遠い場所に光線がキャストされます。

MousePointer

MousePointer は、 遠く離れた操作のために画面をワールド レイキャストしますが、タッチではなくマウス用です。

マウス ポインター

注意

マウスのサポートは MRTK では既定では使用できませんが、MRTK 入力プロファイルに型の新しい Input Data Provider を追加し、 をデータ プロバイダーに割り当てると有効 MouseDeviceManager MixedRealityMouseInputProfile にできます。

近くのポインター

PokePointer

"近い対話操作 がタッチ可能" をサポートするゲーム オブジェクトを操作するために、Pointer が使用されます。 これは、スクリプトがアタッチされている GameObject NearInteractionTouchable です。 UnityUI の場合、このポインターは NearInteractionTouchableUnityUI を検索します。 PointePointer は SphereCast を使用して最も近いタッチ可能な要素を決定し、押しボタンのような電源を供給するために使用されます。

コンポーネントを使用して GameObject を構成する場合は、ボタンの前面またはタッチ可能にする必要があるその他のオブジェクトを指し示す NearInteractionTouchable localForward パラメーターを構成してください。 また、タッチ可能な の 境界が、 タッチ可能なオブジェクトの境界と一致する必要があります。

便利なポリート ポインターのプロパティ:

  • TouchableDistance: タッチ可能なサーフェスを操作できる最大距離
  • ビジュアル: 指のヒントビジュアル (既定では指のリング) をレンダリングするために使用されるゲーム オブジェクト。
  • : 指先からアクティブな入力サーフェスに描画する省略可能な線。
  • レイヤー マスクを 作成する - ポインターが対話できる可能性のある GameObject と、試行する操作の順序を決定する、LayerMasks の優先順位付き配列。 GameObject には、ポキー ポインターと対話するために コンポーネントも必要 NearInteractionTouchable です。
Poke Pointer
SpherePointer

SpherePointer では、対話に最も近いオブジェクトを識別するために UnityEngine.Physics.OverlapSphereが使用されます。これは、 のような "グラブ可能な" 入力に NearInteractionGrabbable 役立ちます ManipulationHandler 。 機能ペアと同様に、Sphere ポインターと対話するには、ゲーム オブジェクトにスクリプトであるコンポーネントが含 PokePointer / NearInteractionTouchable まれている必要 NearInteractionGrabbable があります。

Grab Pointer

役に立つ Sphere ポインターのプロパティ:

  • 球のキャスト半径: つかみ取り可能なオブジェクトのクエリに使用される球の半径。
  • オブジェクトの近くの 余白: オブジェクトがポインターの近くにあるか検出するためにクエリを実行する球のキャスト半径の上の距離。 近物体検出半径の合計は球のキャスト半径 + 近くの物体の余白です
  • Near Object Sector Angle ( オブジェクトセクターの角度の近く): 近くのオブジェクトのクエリを実行するポインターの前方軸を中心にした角度。 クエリ関数 IsNearObject をコネのようにします。 これは、Hololens 2 の動作と一致するために、既定では 66 度に設定されます

前方方向のオブジェクトのみを照会するために変更された Sphere ポインター

  • Near Object Smoothing Factor:近物体検出のスムージング係数。 近距離オブジェクト半径でオブジェクトが検出された場合、クエリされた半径は近距離オブジェクト半径 * (1 + 近距離オブジェクト スムージング 係数) になり、感度が低下し、物体が検出範囲を離れるのが困難になります。
  • レイヤー マスクの 取得 - ポインターが対話できる可能性のある GameObject と、試行する操作の順序を決定する、LayerMasks の優先順位付き配列。 NearInteractionGrabbableGameObject には、SpherePointer と対話するための も必要です。

    注意

    MRTK によって提供される既定の GrabPointer プレハブでは、空間認識レイヤーは無効になっています。 これは、空間メッシュで球の重複クエリを実行した場合のパフォーマンスへの影響を軽減するために行われます。 これを有効にするには、GrabPointer プレハブを変更します。

  • FOV 内にない コライダーを無視する - ポインターの近くにある可能性があるが、実際にはビジュアル FOV 内にはないコライダーを無視するかどうか。 これにより、偶発的なつかみ取りを防ぎ、つかみ取り可能な近くで見られない場合に手の光線をオンにできます。 Visual FOV は 、パフォーマンス上の理由から、一般的な frustum の代わりに、"角" を使用して定義されます。 このコーンは中央に配置され、カメラの frustum と同じ位置に配置され、半径は半ディスプレイの高さ (または垂直 FOV) に等しくなります。
Sphere Pointer

Teleport ポインター

  • TeleportPointer は、アクションが実行された場合にテレポート要求を発生します (つまり、 ユーザーを移動するには、teleport ボタンが押されています)。
  • ParabolicTeleportPointer は、アクションが実行された場合にテレポート要求を発生します (つまり、 teleport ボタンが押されている場合)、ユーザーを移動するために、放物線レイキャストが表示されます。
Pointer Parabolic

Mixed Reality プラットフォームのポインターのサポート

次の表では、MRTK の共通プラットフォームで通常使用されるポインター型について詳しく説明します。 注: これらのプラットフォームには、さまざまなポインター型を追加できます。 たとえば、Vr に対して、1 つのポインターまたは Sphere ポインターを追加できます。 さらに、ゲームパッドを備えた VR デバイスでは、GGV ポインターを使用できます。

ポインター OpenVR Windows Mixed Reality HoloLens 1 HoloLens 2
ShellHandRayPointer 有効 有効 有効
テレポートポインター 有効 有効
GGVPointer 有効
SpherePointer 有効
PokePointer 有効

コードを使用したポインターの相互作用

ポインターイベントインターフェイス

次の1つ以上のインターフェイスを実装し、を使用して MonoBehaviours オブジェクトに割り当てられている場合、 Collider 関連付けられているインターフェイスで定義されているように、ポインター相互作用イベントを受け取ります。

Event 説明 Handler
フォーカスが変更される前、またはフォーカスが変更される前 フォーカスを失うゲームオブジェクトと、ポインターがフォーカスを変更するたびにフォーカスを取得するオブジェクトの両方で発生します。 IMixedRealityFocusChangedHandler
フォーカスの開始/終了 最初のポインターがその後に入ったときにフォーカスを取得するために、game オブジェクトで発生します。 IMixedRealityFocusHandler
ポインターを下へ移動/ドラッグ/上/クリック レポートポインターの押下、ドラッグアンドドロップに発生しました。 IMixedRealityPointerHandler
タッチの開始/更新/完了 のようなタッチ認識ポインターによって発生 PokePointer します。 IMixedRealityTouchHandler

注意

IMixedRealityFocusChangedHandlerIMixedRealityFocusHandler は、発生したオブジェクトで処理する必要があります。 フォーカスイベントはグローバルに受け取ることができますが、他の入力イベントとは異なり、グローバルイベントハンドラーはフォーカスに基づいてイベントの受信をブロックしません (イベントは、グローバルハンドラーと、フォーカスされている対応するオブジェクトの両方によって受信されます)。

操作中のポインター入力イベント

ポインター入力イベントは、 通常の入力イベントと同様の方法で、MRTK 入力システムによって認識および処理されます。 ポインター入力イベントとの違いは、入力イベントを発生させたポインターによってフォーカスされているのは、すべてのグローバル入力ハンドラーによってのみ処理されます。 通常の入力イベントは、すべてのアクティブなポインターにフォーカスがある場合に、そのオブジェクトによって処理されます。

  1. MRTK 入力システムが、入力イベントが発生したことを認識しています
  2. MRTK 入力システムは、登録されているすべてのグローバル入力ハンドラーに対して、入力イベントに関連するインターフェイス関数を起動します。
  3. 入力システムによって、イベントを発生させたポインターにフォーカスされているのはどのオブジェクトであるかが判断されます。
    1. 入力システムは、 Unity のイベントシステム を使用して、フォーカスされたオブジェクトのすべての一致するコンポーネントに関連するインターフェイス関数を起動します。
    2. 任意の時点で、入力イベントが 使用済みとしてマークされている場合、プロセスは終了し、それ以上の追加のオブジェクトはコールバックを受信しません。
      • 例: インターフェイスを実装 IMixedRealityFocusHandler するコンポーネントが、そのオブジェクトの取得またはフォーカスの喪失を検索する
      • 注: 現在のオブジェクトに対して、必要なインターフェイスに一致するコンポーネントが見つからない場合、Unity イベントシステムは、親のオブジェクトを検索するためにバブルアップします。
  4. グローバル入力ハンドラーが登録されておらず、一致するコンポーネントまたはインターフェイスを持つ接続オブジェクトが見つからない場合は、入力システムが各フォールバック登録された入力ハンドラーを呼び出します。

ポインターがフォーカスを取得したり離れたりしたとき、またはポインターがオブジェクトを選択したときに、添付されたレンダラーの色を変更するスクリプトの例を次に示します。

public class ColorTap : MonoBehaviour, IMixedRealityFocusHandler, IMixedRealityPointerHandler
{
    private Color color_IdleState = Color.cyan;
    private Color color_OnHover = Color.white;
    private Color color_OnSelect = Color.blue;
    private Material material;

    private void Awake()
    {
        material = GetComponent<Renderer>().material;
    }

    void IMixedRealityFocusHandler.OnFocusEnter(FocusEventData eventData)
    {
        material.color = color_OnHover;
    }

    void IMixedRealityFocusHandler.OnFocusExit(FocusEventData eventData)
    {
        material.color = color_IdleState;
    }

    void IMixedRealityPointerHandler.OnPointerDown(
         MixedRealityPointerEventData eventData) { }

    void IMixedRealityPointerHandler.OnPointerDragged(
         MixedRealityPointerEventData eventData) { }

    void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData)
    {
        material.color = color_OnSelect;
    }
}

クエリポインター

使用可能な入力ソースをループすることによって現在アクティブになっているすべてのポインターを収集することができます (つまり、 使用可能なコントローラーと入力) は、どのポインターがアタッチされているかを検出します。

var pointers = new HashSet<IMixedRealityPointer>();

// Find all valid pointers
foreach (var inputSource in CoreServices.InputSystem.DetectedInputSources)
{
    foreach (var pointer in inputSource.Pointers)
    {
        if (pointer.IsInteractionEnabled && !pointers.Contains(pointer))
        {
            pointers.Add(pointer);
        }
    }
}

プライマリ ポインター

開発者は、フォーカスのあるプライマリポインターが変更されたときに通知を受け取るように、FocusProviders PrimaryPointerChanged イベントにサブスクライブできます。 これは、ユーザーが現在、宝石またはハンドレイまたは別の入力ソースを使用してシーンを操作しているかどうかを特定するのに非常に便利です。

private void OnEnable()
{
    var focusProvider = CoreServices.InputSystem?.FocusProvider;
    focusProvider?.SubscribeToPrimaryPointerChanged(OnPrimaryPointerChanged, true);
}

private void OnPrimaryPointerChanged(IMixedRealityPointer oldPointer, IMixedRealityPointer newPointer)
{
    ...
}

private void OnDisable()
{
    var focusProvider = CoreServices.InputSystem?.FocusProvider;
    focusProvider?.UnsubscribeFromPrimaryPointerChanged(OnPrimaryPointerChanged);

    // This flushes out the current primary pointer
    OnPrimaryPointerChanged(null, null);
}

PrimaryPointerExample(Assets/MRTK/例/デモ/入力/シーン/PrimaryPointer) シーンは、for イベントを使用して PrimaryPointerChangedHandler 新しいプライマリポインターに応答する方法を示しています。

Primary Pointer Example

ポインターの結果

ポインタープロパティには、 Result フォーカスのあるオブジェクトを特定するために使用されるシーンクエリの現在の結果が格納されます。 モーションコントローラー用に既定で作成されたポインターや、raycast ポインターのようなポインターでは、raycast ヒットの場所と通常の位置が含まれます。

private void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData)
{
    var result = eventData.Pointer.Result;
    var spawnPosition = result.Details.Point;
    var spawnRotation = Quaternion.LookRotation(result.Details.Normal);
    Instantiate(MyPrefab, spawnPosition, spawnRotation);
}

PointerResultExampleシーン (Assets/MRTK/example/デモ/入力/シーン/ポインタの結果/ポインター Resultexample) は、ポインターを使用して、 Result ヒット位置にあるオブジェクトを生成する方法を示しています。

Pointer Result

ポインターの無効化

ポインターを有効または無効にする (たとえば、ハンドレイを無効にする) には、を使用して、指定したポインター型のをに設定し PointerBehavior PointerUtils ます。

// Disable the hand rays
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff);

// Disable hand rays for the right hand only
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Right);

// Disable the gaze pointer
PointerUtils.SetGazePointerBehavior(PointerBehavior.AlwaysOff);

// Set the behavior to match HoloLens 1
// Note, if on HoloLens 2, you must configure your pointer profile to make the GGV pointer show up for articulated hands.
public void SetHoloLens1()
{
    PointerUtils.SetPokePointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
    PointerUtils.SetGrabPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
    PointerUtils.SetRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
    PointerUtils.SetGGVBehavior(PointerBehavior.Default);
}

PointerUtils TurnPointersOnOff その他の例については、およびを参照してください。

エディターを使用したポインターの相互作用

によって処理されるポインターイベントの場合、 IMixedRealityPointerHandler mrtk はコンポーネントの形式でさらに便利な機能を提供します。これにより、 PointerHandler ポインターイベントを Unity イベントを介して直接処理できるようになります。

Pointer Handler

ポインターエクステント

遠くのポインターには、raycast してシーン内の他のオブジェクトと対話する距離を制限する設定があります。 既定では、この値は10メートルに設定されています。 この値は、HoloLens シェルの動作との一貫性を保つために選択されています。

これは、 DefaultControllerPointer prefab のコンポーネントのフィールドを更新することによって変更でき ShellHandRayPointer ます。

ポインターエクステント -ポインターが相互作用する最大距離を制御します。

既定のポインターエクステント -ポインターが何も操作していない場合にレンダリングされる、ポインターの射線/line の長さを制御します。

こちらもご覧ください