UI サポート
Input System パッケージを使用すると、Unity UI パッケージ で作成されたあらゆるゲーム内 UI を制御できます。Input System と UI システム間のインテグレーションは InputSystemUIInputModule コンポーネントによって処理されます。
Note
Input System パッケージでは、IMGUI はサポートされません。プレイヤーコードに OnGUI
メソッドが含まれている場合でも (エディターコードは影響を受けません)、プレイヤー設定 で Active Input Handling が Input System Package に設定されていると、それらのメソッドには、どの入力イベントも通知されません。機能を復元するために設定を Both に変更することはできますが、その場合は Unity で入力が 2 回処理されます。
UI 入力の設定
InputSystemUIInputModule コンポーネントは、Unity UI でパッケージ化される StandaloneInputModule コンポーネントの完全互換品として機能します。InputSystemUIInputModule は、StandaloneInputModule と同じ機能を提供しますが、従来の Input Manager ではなく、Input System を使用して UI 入力を駆動します。
GameObject (ゲームオブジェクト) に StandaloneInputModule コンポーネントがあり、Input System がインストールされている場合は、このコンポーネントを InputSystemUIInputModule に自動的に置き換えるボタンがインスペクターに表示されます。InputSystemUIInputModule は、デフォルトの Input Action を使用して UI を駆動するように事前設定されていますが、この設定は、ニーズに合わせてオーバーライドすることができます。
InputSystemUIInputModule は、以下のプロパティを使用して設定できます。
プロパティ | 説明 |
---|---|
Move Repeat Delay | Move Action が作動し続けているときに、最初の IMoveHandler.OnMove ナビゲーションイベントが生成されてから、ナビゲーションイベントが繰り返し生成されるまでの初期遅延時間 (秒)。 |
Move Repeat Rate | Move Action が作動し続けているときに、ナビゲーションイベントが繰り返し生成される間隔 (秒)。これはフレームレートによって制限されることに注意してください。移動イベントがフレームあたり 2 回以上繰り返されることはありません。したがって、フレームレートが繰り返しレートを下回る場合、実質的な繰り返しレートはこの設定よりも低くなります。 |
Actions Asset | UI を制御するすべての Action を含む Input Action アセット。以下のプロパティを使用して、アセット内のどの Action が、どの UI 入力に対応するかを選択できます。 デフォルトでは、DefaultInputActions というビルトインアセットが参照されます。このアセットには、UI を駆動するための一般的なデフォルトの Action が含まれます。独自の Action を設定する場合は、カスタム Input Action アセットを作成 し、ここに割り当てます。インスペクターで、このフィールドに新しいアセット参照を割り当てると、エディターにより、一般的な命名規則に基づいて Action から UI 入力への自動マッピングが試みられます。 |
Deselect on Background Click | デフォルトでは、ポインターのクリック時にどの GameObject もヒットしない場合は、現在の選択が解除されます。ただし、これが原因で、現在選択されているオブジェクトから離れて動作するキーボードやゲームパッドでのナビゲーションが妨げられることがあります。自動的に選択が解除されないようにするには、このプロパティを false に設定します。 |
Pointer Behavior | 複数のポインターが UI に入力する場合の取り扱い方法を決定します。ポインタータイプの入力 を参照してください。 |
Cursor Lock Behavior | カーソルがロックされているときの UI レイキャストの原点を制御します。 |
選択されている Action アセット から UI Input Action に Action をマップするには、以下のプロパティを使用できます。インスペクターでは、これらが、アセット内のすべての Action を含む折りたたみ式のリストとして表示されます。
プロパティ | 説明 |
---|---|
Point | 2D 画面位置を伝える Action。マウススタイルの UI 操作を実装するために、UI 要素を指すカーソルとして使用します。ポインタータイプの入力 を参照してください。 PassThrough Action タイプおよび Vector2 値型に設定します。 |
Left Click | UI とのインタラクションに使用するプライマリカーソルボタンにマップされる Action。ポインタータイプの入力 を参照してください。 PassThrough Action タイプおよび Button 値型に設定します。 |
Middle Click | UI とのインタラクションに使用する中央カーソルボタンにマップされる Action。ポインタータイプの入力 を参照してください。 PassThrough Action タイプおよび Button 値型に設定します。 |
Right Click | UI とのインタラクションに使用するセカンダリカーソルボタンにマップされる Action。ポインタータイプの入力 を参照してください。 PassThrough Action タイプおよび Button 値型に設定します。 |
Scroll Wheel | UI でのスクロールを可能にするジェスチャ入力を提供する Action。ポインタータイプの入力 を参照してください。 PassThrough Action タイプおよび Vector2 値型に設定します。 |
Move | 現在アクティブな UI Selectable を選択するために使用される 2D ベクトルを提供する Action。これにより、ゲームパッドまたは矢印キースタイルの UI ナビゲーションが可能になります。ナビゲーションタイプの入力 を参照してください。 PassThrough Action タイプおよび Vector2 値型に設定します。 |
Submit | 現在選択されている UI Selectable に関与するか、それを "クリック" する Action。ナビゲーションタイプの入力 を参照してください。 Button Action タイプに設定します。 |
Cancel | 現在選択されている UI Selectable とのインタラクションを終了する Action。ナビゲーションタイプの入力 を参照してください。 Button Action タイプに設定します。 |
Tracked Device Position | XR ハンドコントローラーなど、1 つ以上の空間トラッキングデバイスの 3D 位置を伝える Action。Tracked Device Orientation と組み合わせて、空間の UI Selectable をポイントする XR スタイルの UI インタラクションを実現できます。トラッキングタイプの入力 を参照してください。 PassThrough Action タイプおよび Vector3 値型に設定します。 |
Tracked Device Orientation | XR ハンドコントローラーなど、1 つ以上の空間トラッキングデバイスの回転を表す Quaternion を伝える Action。Tracked Device Position と組み合わせて、空間の UI Selectable をポイントする XR スタイルの UI インタラクションを実現できます。トラッキングタイプの入力 を参照してください。PassThrough Action タイプおよび Quaternion 値型に設定します。 |
バインディングの動作
UI 入力モジュールは、以下の 3 つの異なるタイプの入力を扱うことができます。
- ポインタータイプの入力。
- ナビゲーションタイプの入力。
- トラッキングタイプの入力。
これらの各タイプの入力では、以下で詳しく説明するように、特定のアクションのセットから入力が与えられ、結合されます。
ポインタータイプの入力
UI にとってポインターとは、位置を表すものです。そこからクリックやスクロールをトリガーして、ポインターの位置にある UI 要素を操作することができます。ポインタータイプの入力は、point、leftClick、rightClick、middleClick、scrollWheel から発生します。
Note
UI 入力モジュールは、ポインターとカーソルとは関連付けられていません。一般に UI では、特定のポインターに対応するカーソルが存在するかどうかは認識されていません。ただし、マウス入力とペン入力では、UI 入力モジュールで Cusor.lockState が認識され、カーソルがロックされている場合は常にポインターの位置が (-1,-1)
に固定されます。この動作は、InputSystemUIInputModule の Cursor Lock Behavior プロパティを介して変更できます。
1 つの UI 入力モジュールに、複数のポインター Device が入力を与えることがあります。さらに、Touchscreen の場合は、1 つの Device に複数の同時ポインターが存在する可能性があります (それぞれの指の接触が 1 つのポインターになります)。
Important
複数のポインター Device が、同一の Action のセットに入力を与えることができるため、アクションタイプ を PassThrough に設定することが重要です。これにより、アクションへの入力にフィルタリングが適用されることなく、すべての入力がそのまま伝達されるようになります。
InputSystemUIInputModule の観点からは、1 つ以上のコントロールがポインタータイプのいずれかのアクションにバインドされている InputDevice は、それぞれが固有のポインターであると見なされます。また、各 Touchscreen デバイスについても、1 つ以上のコントロールが同様のアクションにバインドされている個別の TouchControl は、それぞれが独自の固有のポインターであると見なされます。各ポインターは、固有の pointerId を受け取ります。これは一般的に、ポインターの deviceId に対応します。ただし、タッチの場合は、deviceId と touchId の組み合わせになります。タッチイベントの ID を特定するには、ExtendedPointerEventData.touchId を使用します。
複数のポインターからの同時入力を入力モジュールがどのように取り扱うかは、Pointer Behavior 設定を使用して調整できます。
Pointer Behavior | 説明 |
---|---|
Single Mouse or Pen But Multi Touch And Track | タッチ入力またはトラッキング入力として分類されない入力はすべて、Single Unified Pointer と同様に扱われます。トラッキング入力とタッチ入力は、All Pointers As Is と同様に扱われます。 例えば、Mouse (マウス) と Pen (ペン) で同時入力が生じた場合は、両方の入力が、同じ UI ポインターインターフェースに送られます。一方の入力の位置が、もう一方の位置を上書きすることになります。ただし、タッチデバイスまたはトラッキングデバイスから入力が受け取られると、マウスとペンをまとめた単一のポインターは 削除 され、マウス/ペンカーソルがオブジェクト上にある場合に備えて、IPointerExit イベントが送信されます。 これがデフォルトの動作です。 |
Single Unified Pointer | すべてのポインター入力がまとめられ、単一のポインターのように動作します。これには、タッチ入力とトラッキング入力が含まれます。つまり、例えば、Point に入力を与えるデバイスの数に関係なく、フレーム内の最後の入力だけが有効であり、現在の UI ポインターの位置となります。 |
All Pointers As Is | ポインター入力が UI 入力モジュールによってまとめられることはありません。タッチデバイスやトラッキングデバイスなど、ポインタータイプのアクションに入力するデバイスはいずれも、独自のポインター (タッチ入力では複数のポインター) になります。 ノート: この場合、UI 上に任意の数のポインターが存在することになるため、複数のオブジェクトが同時にポイントされる可能性があります。 |
Note
Left Click などのポインタータイプのアクションにデバイスをバインドする場合は、そのデバイスを Point にもバインドしないと、UI 入力モジュールが、ポイントできるものとしてデバイスを認識せず、その入力を別のポインターの入力としてルーティングしようとします。例えば、Left Click を Space
キーにバインドし、Point をマウスの位置にバインドした場合、Space キーを押す操作は、マウスの現在位置を左クリックする操作になります。
ポインタータイプの入力 (および [トラッキングタイプの入力](#tracked-type input)) の場合、InputSystemUIInputModule は、基本の PointerEventData
の拡張バージョンである ExtendedPointerEventData インスタンスを送信します。これらのイベントには、イベントの生成元の device (デバイス) や pointerType (ポインタータイプ) などの追加データが含まれます。
ナビゲーションタイプの入力
ナビゲーションタイプの入力は、move アクションから読み取られたモーションに基づいて、現在の選択を制御します。また、
submit からの入力は、現在選択されているオブジェクトの ISubmitHandler
をトリガーし、
cancel は ICancelHandler
をトリガーします。
複数のポインター入力が同時に存在する可能性のある [ポインタータイプ](#pointer-type input) (2 本指タッチや左右の手によるトラッキング入力を考えてください) とは異なり、ナビゲーションタイプの入力には、複数の同時インスタンスはありません。つまり、単一の move ベクトルと、単一の submit および cancel 入力が、UI モジュールによってフレームごとに処理されます。ただし、これらの入力は、常に 1 つの Device に由来するものである必要はありません。任意の数の入力を、それぞれのアクションにバインドできます。
Important
move は PassThrough アクションタイプに設定する必要がありますが、submit と cancel は Button アクションタイプに設定することが重要です。
ナビゲーション入力には位置がありません。つまり、ポインタータイプの入力とは異なり、これらのアクションには画面位置が関連付けられません。ナビゲーションアクションは、常に現在の選択に基づいて動作します。
トラッキングタイプの入力
XR コントローラー や HMD などの トラッキングデバイス からの入力は、基本的には ポインタータイプの入力 と同様に動作します。主な違いは、trackedDevicePosition および trackedDeviceOrientation からは、デバイスの位置と向きがワールド空間で取得され、レイキャストによってスクリーンスペースの位置に変換されることです。
Important
複数のトラッキング Device が、同一の Action のセットに入力を与える可能性があるため、アクションタイプ を PassThrough に設定することが重要です。これにより、アクションへの入力にフィルタリングが適用されることなく、すべての入力がそのまま伝達されるようになります。
このレイキャストが機能するには、UI の Canvas
コンポーネントを含む GameObject
に TrackedDeviceRaycaster を加える必要があります。通常、この GameObject
には GraphicRaycaster
コンポーネントが含まれますが、これは、2D スクリーンスペースのレイキャストにのみ機能します。TrackedDeviceRaycaster は GraphicRaycaster
とともに配置でき、両方を同時に有効にしても悪影響はありません。
トラッキングデバイスでのクリックは、他の ポインタータイプの入力 と同じです。このため、Left Click などのアクションは、トラッキングデバイスでも、他のポインターと同様に動作します。
マルチプレイヤー UI
Input System では、画面上に複数の別々の UI インスタンスを配置して、異なる入力 Binding で個別に制御することもできます。これは、複数のローカルプレイヤーに、さまざまなコントローラーで 1 つの画面を共有させて、各プレイヤーが独自の UI インスタンスを制御できるようにする場合に役立ちます。これを実現するには、Unity の EventSystem コンポーネントを Input System の MultiplayerEventSystem コンポーネントに置き換える必要があります。
EventSystem コンポーネントとは異なり、MultiplayerEventSystem は、シーン内で複数を同時にアクティブにすることができます。このため、複数のプレイヤーのそれぞれが独自の InputSystemUIInputModule コンポーネントと MultiplayerEventSystem コンポーネントを持ち、各プレイヤーが独自の Action のセットを使用して独自の UI インスタンスを駆動することができます。PlayerInput コンポーネントを使用している場合は、PlayerInput の設定を通じて、プレイヤーのアクションを使用するように InputSystemUIInputModule を自動設定することもできます。その方法については、PlayerInput に関するドキュメントを参照してください。
MultiplayerEventSystem コンポーネントのプロパティは、EventSystem のプロパティと同じです。そのほかに、MultiplayerEventSystem コンポーネントには playerRoot プロパティが追加されています。このプロパティは、このイベントシステムがその階層構造で処理する必要のあるすべての UI Selectable を含む GameObject に設定できます。その後、このイベントシステムが処理するマウス入力では、Player Root の下の階層構造にあるどの GameObject にも属さない UI Selectable がすべて無視されます。
仮想マウスカーソル制御
Note
UI Toolkit は、VirtualMouseInput
コンポーネントから生成されるポインター入力を受け取りますが、UI Toolkit での VirtualMouseInput
コンポーネントの使用は正式にはサポートされていません。現時点では、これは、Unity UI システムとの組み合わせでのみ機能します。
ゲームパッドとジョイスティックをアプリケーションで入力として使用する場合は、ナビゲーション Action を使用して UI を操作することができます。ただし、通常、ナビゲーションに優れた UI を構築するには追加作業が必要です。そこで、UI を操作する別の方法として、ゲームパッドとジョイスティックで "仮想マウスカーソル" のカーソルを駆動できます。
Tip
VirtualMouseInput の設定の例については、Input System パッケージに付属する Gamepad Mouse Cursor サンプル を参照してください。
これを設定するには、以下のステップに従います。
Image
コンポーネントを含む UIGameObject
を作成します。これはソフトウェアマウスカーソルを表します。次に、このオブジェクトを、カーソルの操作対象となるCanvas
に子として加えます。GameObject のRectTransform
のアンカー位置を左下に設定します。他のオブジェクトの上にカーソルが描画されるように、これを、Canvas
の最後の子にします。- GameObject に VirtualMouseInput コンポーネントを加えます。次に、
Image
コンポーネントをCursor Graphic
プロパティにリンクし、カーソルの GameObject のRectTransform
をCursor Transform
プロパティにリンクします。 - 仮想マウスカーソルでシステムマウスカーソルを制御する場合は、Cursor Mode を
Hardware Cursor If Available
に設定します。このモードでは、システムのMouse
が存在する場合にCursor Graphic
が非表示になります。また、Mouse.WarpCursorPosition を使用して、ソフトウェアカーソルではなく、システムマウスカーソルを移動します。この場合、Cursor Transform
を介してリンクされた変換は更新されません。 - 仮想マウスを駆動するように入力を設定するには、さまざまなアクション (
Stick Action
など) にバインディングを加えます。またはUse Reference
を有効にし、.inputactions
アセットから既存のアクションにリンクします。
Important
UI の EventSystem
の InputSystemUIInputModule
が、VirtualMouseInput
に入力するデバイスと同じデバイスからナビゲーション入力を受け取らないようにしてください。例えば、VirtualMouseInput
がゲームパッドから入力を受け取るように設定されている場合に、InputSystemUIInputModule
の Move
、Submit
、Cancel
も、同じゲームパッドにリンクされていると、ゲームパッドからの入力を 2 つのチャネルで UI が受け取ることになります。
ランタイムには、コンポーネントによって仮想 Mouse デバイスが加えられ、それが InputSystemUIInputModule コンポーネントで使用されます。この Mouse
のコントロールには、VirtualMouseInput コンポーネントに設定されたアクションに基づいて入力が与えられます。
結果として生じる Mouse 入力は、そのマウスデバイスから入力を取得するすべてのコードで認識されます。したがって、このコンポーネントは、InputSystemUIInputModule と組み合わせるだけでなく、他の場所でマウスのシミュレーションを行うためにも使用できます。
Note
VirtualMouseInput
の使用中は、ゲームパッドとジョイスティックを ナビゲーション入力 用に設定しないでください。VirtualMouseInput
とナビゲーションの両方が設定されている場合は、入力が 2 回トリガーされます。1 回はポインター入力パスから、もう 1 回はナビゲーション入力パスからです。ボタンが 2 回押されるなどの問題が発生する場合は、これが原因であると考えられます。
UI とゲーム入力
Note
パッケージには UI vs Game Input
というサンプルが付属しており、エディターの Unity Package Manager UI からインストールできます。このサンプルは、UI への入力とゲームへの入力の区別があいまいな場合の処理方法の実例を示しています。
Unity の UI では、ゲーム/プレイヤーコードと同じメカニズムで入力が消費されます。現時点では、クリックなどの特定の入力が UI で消費された場合に、同じ入力がゲームによって再び "消費" されないように暗示的に保証するメカニズムはありません。このため、例えば、UI.Button.onClick
に応答するコードと、<Mouse>/leftButton
にバインドされた Action の InputAction.performed
に応答するコードとの間で、どちらが入力を処理するかがあいまいになる可能性があります。
このようにあいまいになっているかどうかは、UI が どのように 使用されるかによって異なります。以下のシナリオでは、あいまいさが回避されます。
- すべてのインタラクションが UI 要素を介して実行される場合。2D/3D シーンが背後にレンダリングされているが、すべてのインタラクションが UI イベント (
Canvas
での "背景" のクリックなども含む) を使用して実行される場合です。 - 2D/3D シーンの上にオーバーレイとして UI が表示されるが、UI 要素を直接操作することはできない場合。
- 2D/3D シーンの上にオーバーレイとして UI が表示されるが、UI とゲームのどちらでインタラクションが処理されるかを決定する明確な "モード" スイッチが存在する場合。例えば、デスクトップ上の一人称ゲームで カーソルロック と、ロック中のゲームへの直接入力が使用されているが、ロックされていないときはすべてのインタラクションが UI に渡される場合です。
あいまいになっているときは、その状況が ポインタータイプ と ナビゲーションタイプ で異なります。
ポインタータイプの入力でのあいまいさの処理
Note
InputAction.performed
などの InputAction
のコールバックから EventSystem.IsPointerOverGameObject
を呼び出すと警告が発生します。入力処理の 後 に UI が別に更新されるため、UI の状態は、入力が処理されていた間の 最後 のフレーム/更新の状態に対応します。
ポインター (マウス、タッチスクリーン、ペン) からの入力は、インタラクションの開始時にポインターが UI 要素の上にあるかどうかに応じて、あいまいさになる可能性があります。例えば、画面上にボタンがある場合は、そのボタンの上でクリックすることが、ゲームシーン内でボタン以外の場所をクリックすることとは異なる結果になる可能性があります。
すべてのポインター入力が UI イベントを介して処理される場合は、UI によって入力がそれぞれの受信側に暗示的にルーティングされるため、あいまいになることはありません。しかし、UI への入力が UI イベントを介して処理され、ゲーム内の入力が Action を介して処理される場合、デフォルトではポインター入力で 両方 がトリガーされることになります。
このようなあいまいさを解消する最も簡単な方法は、ゲーム内アクションに応答するときに、MonoBehaviour.Update
メソッド内から ポーリング を実行し、EventSystem.IsPointerOverGameObject
を使用して、ポインターが UI の上にあるかどうかを特定することです。もう 1 つの方法は、EventSystem.RaycastAll
を使用して、ポインターが現在 UI の上にあるかどうかを特定することです。
ナビゲーションタイプの入力でのあいまいさの処理
ゲームパッドやジョイスティック (およびキーボード) などのナビゲーションタイプの Device であいまいさが生じる状況は、ポインターの場合とは異なります。これらの Device では、UI の Move
、Submit
、Cancel
の入力として入力を使用するか、ゲームに使用するかを、アプリケーションで明示的に決定する必要があります。これは、Device でコントロールを分離するか、または明示的なモードスイッチを用意することで実現できます。
Device で入力を分離するとは、単純に、特定のコントロールを UI の操作に使用し、他のコントロールをゲームの操作に使用するということです。例えば、UI の選択操作には、ゲームパッド上の D パッドを、ゲーム内のキャラクター制御にはスティックを使用することができます。この設定では、UI Action で使用されるバインディングを適切に調整する必要があります。
明示的なモードスイッチは、ゲーム内 Action を中断すると同時に、一時的に UI 制御に切り替えることで実装します。例えば、ゲームパッドの左トリガーでアイテムの選択ホイールを呼び出してゲームのモードを切り替えることで、スティックで UI の選択を制御し、A ボタンで選択を確定し、B ボタンでアイテム選択ホイールを閉じるようにすることができます。UI が "フォアグラウンド" になっている間はゲーム内アクションが応答しないため、あいまいになることはありません。
UI Toolkit のサポート
Unity 2021.2 以降では、プレイヤーに UI を実装するために、Unity UI システムに代わるものとして UI Toolkit がサポートされています。
Unity UI と UI Toolkit の入力サポートは、どちらも同じ EventSystem および BaseInputModule サブシステムに基づいています。言い換えると、どちらの UI ソリューションも、InputSystemUIInputModule に基づく同じ入力設定によってサポートされ、他に必要となる作業はありません。
UI Toolkit の内部では、イベントリスナーが PanelEventHandler
コンポーネントの形でインストールされます。これにより、InputSystemUIInputModule
から送信されるイベントがインターセプトされ、UI Toolkit 固有のイベントに変換された後、ビジュアルツリーにルーティングされます。EventSystem.SetUITookitEventSystemOverride
を使用すると、このデフォルトのメカニズムはバイパスされます。
Note
XR (トラッキングタイプの入力) と UI Toolkit の組み合わせはまだサポートされていません。つまり、VR コントローラーなどのデバイスを使用して、UI Toolkit で作成されたインターフェースを操作することはできません。
他にも、以下のような注意事項があります。
- UI Toolkit では、レイキャストが内部で処理されます。uGUI のように別個のレイキャスターコンポーネントが必要になることはありません。したがって、UI Toolkit では TrackedDeviceRaycaster は機能しません。
- UI Toolkit では、ポインターのクリックとゲームパッドの送信アクションがイベントレベルで区別されます。つまり、例えば、
CSharp button.RegisterCallback<ClickEvent>(_ => ButtonWasClicked());
を実行すると、ゲームパッドでボタンが "クリック" されたときにハンドラーが呼び出されません (これはNavigationSubmitEvent
であり、ClickEvent
ではないためです)。ただし、CSharp button.clicked += () => ButtonWasClicked();
を実行すると、どちらの場合も呼び出されます。