次の方法で共有


対話可能 — MRTK2

対話可能

Interactable コンポーネントは、任意のオブジェクトを簡単に操作でき、入力に対して応答性を高めるオールインワン コンテナーです。 Interactable は、タッチ、ハンド レイ、音声など、あらゆる種類の入力のキャッチオールとして機能し、これらの相互作用を イベント視覚的なテーマ の応答にファネルします。 このコンポーネントは、ボタンの作成、フォーカスのあるオブジェクトの色の変更などを簡単に行う方法を提供します。

Interactable を構成する方法

コンポーネントでは、構成の 3 つの主要なセクションを使用できます。

  1. 一般的な入力構成
  2. 複数の GameObject を対象とするビジュアル テーマ
  3. イベント ハンドラー

一般的な入力設定

一般的な対話可能な設定

状態

States は、操作可能なプロファイルとビジュアル テーマの操作フェーズ (プレスや観測など) を定義する ScriptableObject パラメーターです

DefaultInteractableStates (Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset) は、MRTK の既定のパラメーターであり、Interactable コンポーネントの既定のパラメーターです。

インスペクターの States ScriptableObject の例

DefaultInteractableStates 資産には 4 つの状態が含まれており、InteractableStates状態モデルの実装を利用します。

  • 既定値: 何も行われません。これは最も分離された基本状態です。

  • フォーカス: オブジェクトが指し示されています。 これは単一の状態であり、他の状態は現在設定されていませんが、ランク Default になります。

  • 押す: オブジェクトが指し示され、ボタンまたは手が押されています。 [Press state out]\(プレスステートアウト\) は、[既定値] と [フォーカス] をランク付けします。 この状態は、物理プレスへのフォールバックとしても設定されます。

  • 無効: ボタンは対話型ではなく、何らかの理由でこのボタンが現時点では使用できない場合は、視覚的なフィードバックによってユーザーに通知されます。 理論的には、無効状態には他のすべての状態が含まれる可能性がありますが、Enabled がオフの場合、Disabled 状態は他のすべての状態を切り捨てられます。

ビット値 (#) は、リスト内の順序に応じて状態に割り当てられます。

注:

一般に、Interactable コンポーネントの作成時に DefaultInteractableStates (Assets/MRTK/SDK/Features/UX/Interactable/States/DefaultInteractableStates.asset) を利用することをお勧めします。

ただし、テーマの駆動に使用できる 17 個の対話可能な状態がありますが、一部の状態は他のコンポーネントによって駆動されることを意図しています。 組み込みの機能を備えた機能の一覧を次に示します。

  • アクセス済み: [対話可能] がクリックされました。
  • トグル: ボタンが切り替え状態であるか、ディメンション インデックスが奇数です。
  • ジェスチャ: 手またはコントローラーが押され、元の位置から移動しました。
  • VoiceCommand: Speech コマンドを使用して Interactable をトリガーしました。
  • PhysicalTouch: タッチ入力が現在検出され、 NearInteractionTouchable を使用して有効にします。
  • グラブ:手は現在、オブジェクトの境界内でつかんでいる、有効にするには、 NearInteractionGrabbable を使用します

Enabled (有効)

Interactable を有効にするかどうかを切り替えます。 これは、コード内の Interactable.IsEnabled に対応します。

Interactable の有効なプロパティは、GameObject/Component (SetActive など) を使用して構成された有効なプロパティとは異なります。 GameObject または Interactable MonoBehaviour を無効にすると、入力、ビジュアル テーマ、イベントなど、クラス内のすべての実行が無効になります。 Interactable.IsEnabled を使用して無効にすると、ほとんどの入力処理が無効になり、関連する入力状態がリセットされます。 ただし、クラスは引き続きすべてのフレームを実行し、無視される入力イベントを受け取ります。 これは、Visual テーマを使用して実行できる、無効な状態で Interactable を表示する場合に役立ちます。 この典型的な例は、必要なすべての入力フィールドが完了するのを待機している送信ボタンです。

入力アクション

Interactable コンポーネントが対応する必要がある入力構成またはコントローラー マッピング プロファイルから入力アクションを選択します。

このプロパティは、実行時にコードで Interactable.InputActionを使用して構成できます。

IsGlobal

true の場合、選択した 入力アクションのグローバル入力リスナーとしてコンポーネントがマークされます。 既定の動作は false で、この Interactable コライダー/GameObject のみに入力が制限されます。

このプロパティは、実行時にコードで Interactable.IsGlobalを使用して構成できます。

Speech コマンド

音声操作のために OnClick イベントをトリガーする、MRTK 音声コマンド プロファイルの音声コマンド。

このプロパティは、実行時にコードで Interactable.VoiceCommandを使用して構成できます。

フォーカスが必要

true の場合、音声コマンドは、ポインターからのフォーカスが既にある場合にのみ 、Interactable をアクティブにします。 false の場合、 Interactable は選択した音声コマンドのグローバル リスナーとして機能します。 既定の動作は true です。複数のグローバル音声リスナーはシーン内で整理するのが困難な場合があります。

このプロパティは、実行時にコードで Interactable.VoiceRequiresFocusを使用して構成できます。

選択モード

このプロパティは、選択ロジックを定義します。 Interactable がクリックされると、次のディメンション レベルに反復処理されます。 ディメンション はランクに似ていて、入力の外部 (フォーカス、押すなど) の状態を定義します。 ボタンに関連付けられているトグル状態やその他の複数ランクの状態を定義する場合に便利です。 現在のディメンション レベルは、 Interactable.DimensionIndexによって追跡されます。

使用できる選択モードは次のとおりです。

  • ボタン - ディメンション = 1、単純なクリック可能 な対話可能
  • トグル - ディメンション = 2、オン/オフ状態間の対話可能な代替
  • 複数次元 - ディメンション>= 3、クリックするたびに現在のディメンション レベル + 1 が増加します。 ボタンの状態をリストなどに定義する場合に便利です。

対話可能ではディメンションごとに複数のテーマを定義することもできます。 たとえば 、SelectionMode=Toggle の場合、 Interactable選択が解除されたときに 1 つのテーマが適用され、コンポーネントが選択されたときに別のテーマが適用 される場合があります。

現在の選択モードは、実行時に Interactable.ButtonModeを介して照会できます。 実行時にモードを更新するには、目的の機能に合わせて Interactable.Dimensions プロパティを設定します。 さらに、 トグル モードとマルチディメンション モードに便利な現在 のディメンション には、 Interactable.CurrentDimension経由でアクセスできます。

対話可能なプロファイル

プロファイル は、GameObject と Visual Theme の間にリレーションシップを作成するアイテムです。 プロファイルは、 状態の変更が発生したときにテーマによって操作されるコンテンツを定義します。

テーマは素材とよく似ています。 現在の状態に基づいてオブジェクトに割り当てられるプロパティの一覧を含むスクリプト可能なオブジェクトです。 テーマも再利用でき、複数の Interactable UX オブジェクト間で割り当てることができます。

破棄時にリセットする

ビジュアル テーマは、選択したテーマ エンジンのクラスと種類に応じて、対象となる GameObject のさまざまなプロパティを変更します。 Interactable コンポーネントが 破棄されたときに Reset On Destroy が true の場合、コンポーネントは、アクティブなテーマから変更されたすべてのプロパティを元の値にリセットします。 それ以外の場合、破棄されると、Interactable コンポーネントは変更されたプロパティをそのまま残します。 この後者の場合、値の最後の状態は、別の外部コンポーネントによって変更されない限り保持されます。 既定値は false です。

プロファイルの設定

イベント

すべての Interactable コンポーネントには、コンポーネントが単に選択されたときに発生する OnClick イベントがあります。 ただし、 Interactable を使用すると、 OnClick 以外の入力イベントを検出できます。

[ イベントの追加] ボタンをクリックして、新しい種類のイベント レシーバー定義を追加します。 追加したら、目的のイベントの種類を選択します。

イベントの例 )

さまざまな種類の入力に応答するさまざまな種類のイベント レシーバーがあります。 MRTK には、次のレシーバーセットが付属しています。

カスタム レシーバーは、 ReceiverBaseを拡張する新しいクラスを作成することで作成できます。

イベント トグル レシーバーの例

トグル イベント レシーバーの例

対話可能なレシーバー

InteractableReceiver コンポーネントを使用すると、ソースの Interactable コンポーネントの外部でイベントを定義できます。 InteractableReceiver は、別の Interactable によって発生したフィルター処理されたイベントの種類をリッスンします。 Interactable プロパティが直接割り当てられない場合、Search Scope プロパティは、InteractableReceiver がそれ自体、親、または子 GameObject のイベントをリッスンする方向を定義します。

InteractableReceiverList は同様の方法で動作しますが、一致するイベントの一覧に対して機能します。

対話可能なリシヴァー

カスタム イベントを作成する

Visual テーマと同様に、イベントを拡張して状態パターンを検出したり、機能を公開したりできます。

カスタム イベントは、次の 2 つの主な方法で作成できます。

  1. ReceiverBase クラスを拡張して、イベントの種類のドロップダウン リストに表示されるカスタム イベントを作成します。 Unity イベントは既定で提供されますが、追加のUnity イベントを追加することも、イベントを設定してUnityイベントを非表示にすることもできます。 この機能を使用すると、デザイナーはプロジェクトのエンジニアと連携して、デザイナーがエディターで設定できるカスタム イベントを作成できます。

  2. ReceiverBaseMonoBehavior クラスを拡張して、Interactable または別のオブジェクトに存在できる完全にカスタムのイベント コンポーネントを作成します。 ReceiverBaseMonoBehaviorは、状態の変化を検出するために Interactable を参照します。

拡張の例 ReceiverBase

CustomInteractablesReceiver クラスは、Interactable に関する状態情報を表示し、カスタム イベント レシーバーを作成する方法の例です。

public CustomInteractablesReceiver(UnityEvent ev) : base(ev, "CustomEvent")
{
    HideUnityEvents = true; // hides Unity events in the receiver - meant to be code only
}

次のメソッドは、カスタム イベント レシーバーを作成するときにオーバーライドまたは実装するのに役立ちます。 ReceiverBase.OnUpdate() は、状態パターン/遷移を検出するために使用できる抽象メソッドです。 さらに、 ReceiverBase.OnVoiceCommand() メソッドと ReceiverBase.OnClick() メソッドは、 Interactable が選択されている場合にカスタム イベント ロジックを作成するのに役立ちます。

public override void OnUpdate(InteractableStates state, Interactable source)
{
    if (state.CurrentState() != lastState)
    {
        // the state has changed, do something new
        lastState = state.CurrentState();
        ...
    }
}

public virtual void OnVoiceCommand(InteractableStates state, Interactable source,
                                    string command, int index = 0, int length = 1)
{
    base.OnVoiceCommand(state, source, command, index, length);
    // voice command called, perform some action
}  

public virtual void OnClick(InteractableStates state,
                            Interactable source,
                            IMixedRealityPointer pointer = null)
{
    base.OnClick(state, source);
    // click called, perform some action
}
インスペクターでのカスタム イベント レシーバー フィールドの表示

ReceiverBase スクリプトでは、 InspectorField 属性を使用して、インスペクターでカスタム プロパティを公開します。 ヒントとラベル情報を含むカスタム プロパティである Vector3 の例を次に示します。 このプロパティは、 Interactable GameObject が選択され、関連付けられている イベント レシーバー の種類が追加されると、インスペクターで構成可能として表示されます。

[InspectorField(Label = "<Property label>",Tooltip = "<Insert tooltip info>",Type = InspectorField.FieldTypes.Vector3)]
public Vector3 EffectOffset = Vector3.zero;

Interactable の使用方法

単純なボタンを作成する

入力イベントを受信するように構成された GameObject に Interactable コンポーネントを追加することで、簡単なボタンを作成できます。 コライダーを持つか、入力を受け取る子を持つことができます。 Unity UI ベースの GameObject で Interactable を使用する場合は、Canvas GameObject の下にある必要があります。

新しいプロファイルを作成し、GameObject 自体を割り当て、新しいテーマを作成することで、ボタンをさらに 1 歩進めます。 さらに、 OnClick イベントを使用して何かを発生させます。

注:

ボタンを 押せる には、 PressableButton コンポーネントが必要です。 さらに、イベントを Interactable コンポーネントにファネルするには、PhysicalPressEventRouter コンポーネントが必要です。

トグル ボタンとマルチディメンション ボタンの作成

トグル ボタン

ボタンをトグル可能にするには、 Selection Mode フィールドを「 Toggle」と入力するように変更します。 [ プロファイル ] セクションでは、 Interactable がオンに切り替えられたときに使用されるプロファイルごとに、切り替えられた新しいテーマが追加されます。

SelectionModeが Toggle に設定されている間、[IsToggled チェック] ボックスを使用して、実行時の初期化時にコントロールの既定値を設定できます。

CanSelect、Interactable がオフからオンに切 り替 えられるの に対、CanDeselect は逆を意味します。

プロファイルトグルビジュアルテーマの例

開発者は、 SetToggled インターフェイスと IsToggled インターフェイスを利用して、コードを介して Interactable のトグル状態を取得/設定できます。

// If using SelectionMode = Toggle (i.e Dimensions == 2)

// Make the Interactable selected and toggled on
myInteractable.IsToggled = true;

// Get whether the Interactable is selected or not
bool isSelected = myInteractable.IsToggled;
トグル ボタン コレクション

一般的に、トグル ボタンの一覧があり、一度にアクティブにできるトグル ボタンは 1 つだけです(放射状セットやラジオ ボタンなどとも呼ばれます)。

この機能を有効にするには、 InteractableToggleCollection コンポーネントを使用します。 このコントロールにより、常に 1 つの Interactable のみがオンに切り替えられます。 RadialSet (Assets/MRTK/SDK/Features/UX/Interactable/Prefabs/RadialSet.prefab) も、すぐに使用できる優れた出発点です。

カスタムの放射状ボタン グループを作成するには:

  1. 複数の 対話可能な ゲームオブジェクト/ボタンを作成する
  2. SelectionMode = Toggle、CanSelect = true、CanDeselect = false を使用して各 Interactable を設定する
  3. すべての Interactables に空の親 GameObject を作成し、 InteractableToggleCollection コンポーネントを 追加します
  4. InteractableToggleCollectionToggleList にすべての Interactable を追加する
  5. InteractableToggleCollection.CurrentIndex プロパティを設定して、起動時に既定で選択されているボタンを決定します
コレクションの切り替え

多次元ボタン

複数次元選択モードは、連続したボタン、または 3 つの値 (高速 (1x)、高速 (2x) または最速 (3x) で速度を制御するなど、2 つ以上のステップを持つボタンを作成するために使用されます。

ディメンションが数値である場合は、ステップごとに異なるテーマを使用して、各速度設定のボタンのテキスト ラベルまたはテクスチャを制御するために、最大 9 つのテーマを追加できます。

すべてのクリック イベントは、Dimensions値に達するまで、実行時にDimensionIndexを 1 進めます。 その後、サイクルは 0 にリセットされます。

多次元プロファイルの例

開発者は、 DimensionIndex を評価して、現在アクティブなディメンションを決定できます。

// If using SelectionMode = Multi-dimension (i.e Dimensions >= 3)

//Access the current DimensionIndex
int currentDimension = myInteractable.CurrentDimension;

//Set the current DimensionIndex to 2
myInteractable.CurrentDimension = 2;

// Promote Dimension to next level
myInteractable.IncreaseDimension();

実行時に Interactable を作成する

対話可能な 操作は、実行時に任意の GameObject に簡単に追加できます。 次の例では、 ビジュアル テーマを使用してプロファイルを割り当てる方法を示します。

var interactableObject = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
var interactable = interactableObject.AddComponent<Interactable>();

// Get the default configuration for the Theme engine InteractableColorTheme
var newThemeType = ThemeDefinition.GetDefaultThemeDefinition<InteractableColorTheme>().Value;

// Define a color for every state in our Default Interactable States
newThemeType.StateProperties[0].Values = new List<ThemePropertyValue>()
{
    new ThemePropertyValue() { Color = Color.black},  // Default
    new ThemePropertyValue() { Color = Color.black}, // Focus
    new ThemePropertyValue() { Color = Random.ColorHSV()},   // Pressed
    new ThemePropertyValue() { Color = Color.black},   // Disabled
};

interactable.Profiles = new List<InteractableProfileItem>()
{
    new InteractableProfileItem()
    {
        Themes = new List<Theme>()
        {
            Interactable.GetDefaultThemeAsset(new List<ThemeDefinition>() { newThemeType })
        },
        Target = interactableObject,
    },
};

// Force the Interactable to be clicked
interactable.TriggerOnClick()

コードを使用した対話可能なイベント

次の例を使用して、コードを使用して基本 Interactable.OnClick イベントにアクションを追加できます。

public static void AddOnClick(Interactable interactable)
{
    interactable.OnClick.AddListener(() => Debug.Log("Interactable clicked"));
}

Interactable.AddReceiver<T>()関数を使用して、実行時にイベント レシーバーを動的に追加します。

次のコード例は、フォーカスの開始/終了をリッスンする InteractableOnFocusReceiver を追加し、さらにイベント インスタンスが起動したときに実行するアクション コードを定義する方法を示しています。

public static void AddFocusEvents(Interactable interactable)
{
    var onFocusReceiver = interactable.AddReceiver<InteractableOnFocusReceiver>();

    onFocusReceiver.OnFocusOn.AddListener(() => Debug.Log("Focus on"));
    onFocusReceiver.OnFocusOff.AddListener(() => Debug.Log("Focus off"));
}

次のコード例は、トグル可能な Interactable で選択または選択解除された状態遷移をリッスンする InteractableOnToggleReceiver を追加する方法と、イベント インスタンスが発生したときに実行するアクション コードをさらに定義する方法を示しています。

public static void AddToggleEvents(Interactable interactable)
{
    var toggleReceiver = interactable.AddReceiver<InteractableOnToggleReceiver>();

    // Make the interactable have toggle capability, from code.
    // In the gui editor it's much easier
    interactable.Dimensions = 2;
    interactable.CanSelect = true;
    interactable.CanDeselect  = true;

    toggleReceiver.OnSelect.AddListener(() => Debug.Log("Toggle selected"));
    toggleReceiver.OnDeselect.AddListener(() => Debug.Log("Toggle un-selected"));
}

関連項目