Unity ユーザーマニュアルのこのセクションでは、仮想現実 (VR)、拡張現実 (AR)、Windows Mixed Reality アプリケーションのために Unity がサポートするすべての入力デバイスに関する情報を提供します。このページでは、以下のトピックについて説明します。
XR プラットフォームには豊富な種類の入力機能があり、ユーザーインタラクションを設計するときに便利です。アプリケーションは、位置、回転、タッチ、ボタン、ジョイスティック、指センサーを参照する特定のデータを使用できます。ただし、これらの入力機能へのアクセスは、プラットフォームによって大きく異なります。例えば、Vive と Oculus Rift の間には多少違いがありますが、VR 対応のデスクトッププラットフォームと Daydream のようなモバイルプラットフォームでは、さらに多くの違いがあります。
Unity は、InputFeatureUsage と呼ばれる C# 構造体を提供しています。これは、任意のプラットフォームでユーザー入力にアクセスするための物理デバイス制御 (ボタンやトリガーなど) の標準セットを定義します。これらは開発者が入力タイプを名前で識別するために役立ちます。各 InputFeatureUsage の定義については、XR.Input.CommonUsages を参照してください。
各 InputFeatureUsage は、一般的な入力アクションまたはタイプに対応しています。例えば、Unity では、trigger と呼ばれる InputFeatureUsage は、使用する XR プラットフォームに関係なく、人差し指で制御する 1 軸の入力として定義されます。InputFeatureUsage を使用して、その名前で trigger の状態を取得できるため、従来の Unity Input System に軸 (一部の XR プラットフォームではボタン) を設定する必要はありません。
以下の表は、標準コントローラーの InputFeatureUsage の名前と、それらが一般的な XR システムのコントローラーにどのようにマップされるかを示しています。
| InputFeatureUsage | 機能タイプ | 古い入力インデックス (左コントローラー/右コントローラー) | WMR | Oculus | GearVR | Daydream | OpenVR (全般) | Vive | OpenVR 経由の Oculus | OpenVR 経由の WMR | |:—|:—|:—|:—|:—|:—|:—|:—|:—|:—|:—| | 主要 2D 軸 | 2D 軸 | [(1,2)/(4,5)] | タッチパッド | ジョイスティック | タッチパッド | タッチパッド | トラックパッド/ジョイスティック | トラックパッド | ジョイスティック | ジョイスティック | | トリガー | 軸 | [9/10] | トリガー | トリガー | トリガー | トリガー | トリガー | トリガー | トリガー | トリガー | | グリップ | 軸 | [11/12] | グリップ | グリップ | | バンパー | グリップ | グリップ | グリップ | グリップ | | 補助的な 2D 軸 | 2D 軸 | [(17,18)/(19,20)] | ジョイスティック | | | | | | | タッチパッド | | secondary2DAxisClick|ボタン|[18/19]|ジョイスティック - クリック| | | | | | | | | 主要ボタン | ボタン | [2/0] | | [X/A] - 押す | | アプリケーション | 主要 | プライマリ(サンドイッチボタン)(1) | 主要 [Y/B] | メニュー | | primaryTouch | ボタン | [12/10] | | [X/A] - タッチ | | | | | | | | 補助的なボタン | ボタン | [3/1] | | [Y/B] - 押す | | | 代替 | | 代替 (X/A) | | | 補助的なタッチ | ボタン | [13/11] | | [Y/B] - タッチ | | | | | | | | グリップボタン | ボタン | [4/5] | グリップ - 押す | グリップ - 押す | | | グリップ - 押す | グリップ - 押す | グリップ - 押す | グリップ - 押す | | triggerButton | ボタン | [14/15] | トリガー - 押す | トリガー - 押す | トリガー - 押す | トリガー - 押す | トリガー - 押す | トリガー - 押す | トリガー - タッチ | トリガー - 押す | | メニューボタン | ボタン | [6/7] | メニュー | スタート (左コントローラーのみ) | | | | | | | | 主要 2D 軸クリック | ボタン | [8/9] | タッチパッド - クリック | サムスティック - 押す | タッチパッド - 押す | タッチパッド - 押す | トラックパッド/ジョイスティック - 押す | トラックパッド - 押す | ジョイスティック - 押す | タッチパッド - 押す | | 主要 2D 軸タッチ | ボタン | [16/17] | タッチパッド - タッチ | サムスティック - タッチ | タッチパッド - タッチ | タッチパッド - タッチ | トラックパッド/ジョイスティック - タッチ | トラックパッド - タッチ | ジョイスティック - タッチ | タッチパッド - タッチ | | batteryLevel| 軸| | バッテリー残量 | | | | | | | | | userPresence| ボタン | | ユーザープレゼンス | ユーザープレゼンス | | | | | | |
(1) サンドイッチボタンは Vive のメニューボタンを指します。このボタンは、クロスプラットフォームアプリケーションをより適切に処理するために、menuButton ではなく primaryButton にマップされます。
各 InputFeatureUsage の定義については、XR.Input.CommonUsages を参照してください。
InputDevice は、コントローラー、携帯電話、ヘッドセットなどの物理的なデバイスを表します。デバイストラッキング、ボタン、ジョイスティック、その他の入力制御に関する情報が含まれます。InputDevice API の詳細については、InputDevice に関するドキュメントを参照してください。
現在 XR システムに接続されている入力デバイスにアクセスするには、XR.InputDevices クラスを使用します。接続されているすべてのデバイスのリストを取得するには、InputDevices.GetDevices を使用します。
var inputDevices = new List<UnityEngine.XR.InputDevice>();
UnityEngine.XR.InputDevices.GetDevices(inputDevices);
foreach (var device in inputDevices)
{
Debug.Log(string.Format("Device found with name '{0}' and role '{1}'", device.name, device.role.ToString()));
}
入力デバイスは、XR システムがそれを切断するまで、フレーム全体で有効です。InputDevice.IsValid プロパティを使用して、InputDevice がまだアクティブなコントローラーを表しているかどうかを確認します。
以下の方法で入力デバイスにアクセスできます。
デバイスの特性 (Characteristics) は、デバイスの機能や使用目的 (例えばヘッドマウントかどうかなど) を表します。InputDeviceCharacteristics は、特定の仕様に適合するデバイスを検索するためにコードに追加できる一連のフラグです。以下の特性でデバイスをフィルタリングできます。
| Device | 特徴 |
|---|---|
| HeadMounted | デバイスはユーザーの頭に装着されます。デバイストラッキングとセンターアイトラッキングがあります。このフラグは通常、ヘッドマウントディスプレイ (HMD) を識別するために使用されます。 |
| Camera | デバイスにはカメラトラッキングがあります。 |
| HeldInHand | ユーザーはデバイスを手に持っています。 |
| HandTracking | デバイスは、物理的に追跡される手を表します。デバイストラッキングがあり、手とボーンのデータが含まれている場合があります。 |
| EyeTracking | デバイスはアイトラッキングを実行でき、EyesData 機能を備えています。 |
| TrackedDevice | デバイスは 3D スペースで追跡されます。デバイストラッキング機能があります。 |
| Controller | デバイスはボタンと軸の入力 データを持ち、 コントローラーとして使用できます。 |
| TrackingReference | デバイスは静的トラッキング参照オブジェクトを表します。デバイストラッキング機能がありますが、トラッキングデータを変更しないでください。 |
| 左 | この特性をHeldInHandまたはHandTracking特性と組み合わせて使用して、 デバイスを左手に関連付けられていると識別します 。 |
| 右 | この特性をHeldInHandまたはHandTracking特性と組み合わせて使用して、 デバイスを右手に関連付けられていると識別します 。 |
| Simulated6DOF | デバイスからは 6DOF データがレポートされますが、3DOF センサーしかありません。Unity によって位置データがシミュレートされます。 |
基礎となる XR SDK によってこれらの特性がレポートされ、ユーザーはこれを InputDevice.Characteristics で確認できます。デバイスは複数の特性を持つことができ、多くの場合、それらをフィルタリングしてビットフラグでアクセスできます。
InputDevices.GetDevicesWithCharacteristics を使用すると、特定の特性を持つすべてのデバイスを検索できます。例えば、システムで使用可能な Left、HeldInHand、Controller InputDevices は、以下のコードで検索できます。
var leftHandedControllers = new List<UnityEngine.XR.InputDevice>();
var desiredCharacteristics = UnityEngine.XR.InputDeviceCharacteristics.HeldInHand | UnityEngine.XR.InputDeviceCharacteristics.Left | UnityEngine.XR.InputDeviceCharacteristics.Controller;
UnityEngine.XR.InputDevices.GetDevicesWithCharacteristics(desiredCharacteristics, leftHandedControllers);
foreach (var device in leftHandedControllers)
{
Debug.Log(string.Format("Device name '{0}' has characteristics '{1}'", device.name, device.characteristics.ToString()));
}
この関数が検出するデバイスには、少なくとも指定された特性が含まれますが、追加の特性も含まれる場合があります。例えば、左利きのコントローラーを見つけるには、InputDeviceCharacteristic.Left のみを検索し、InputDeviceCharacteristic.Controller は検索しません。
デバイスロールは、入力デバイスの一般的な機能を説明します。InputDeviceRole 列挙型を使用して、デバイスロールを指定します。定義されているロールは以下のとおりです。
| ロール | 説明 |
|---|---|
| GameController | コンソールスタイルのゲームコントローラー |
| Generic | ヘッドマウントディスプレイ 、またはモバイルデバイスのようなコアXRデバイス。 |
| HardwareTracker | トラッキングデバイス。 |
| LeftHanded | ユーザーの左手に関連付けられたデバイス。 |
| RightHanded | ユーザーの右手に関連付けられたデバイス。 |
| TrackingReference | Oculus トラッキングカメラなどの他のデバイスを追跡するデバイス。 |
基礎となる XR SDK によってこれらのロールがレポートされますが、プロバイダーによってデバイスロールの編成が異なる場合があります。さらに、ユーザーは手を切り替えることができるため、ユーザーが入力デバイスを持っている手とロールの割り当てがマッチしない場合があります。例えば、ユーザーは Daydream コントローラーを右利き、または左利きに設定する必要がありますが、コントローラーを反対の手に持つこともできます。
GetDevicesWithRole は、特定の InputDeviceRole を持つデバイスのリストを提供します。例えば、InputDeviceRole.GameController を使用して、接続されている任意の GameController デバイスを取得できます。
var gameControllers = new List<UnityEngine.XR.InputDevice>();
UnityEngine.XR.InputDevices.GetDevicesWithRole(UnityEngine.XR.InputDeviceRole.GameController, gameControllers);
foreach (var device in gameControllers)
{
Debug.Log(string.Format("Device name '{0}' has role '{1}'", device.name, device.role.ToString()));
}
XRノードは、XRシステムでの物理的な基準点(例えば、ユーザーの頭の位置、右手と左手、Oculusカメラなどのトラッキング基準)を表します。
XRNode 列挙型は以下のノードを定義します。
| XRノード | 説明 |
|---|---|
| CenterEye | ユーザーの目の瞳孔の中間点。 |
| GameController | コンソールスタイルのゲームコントローラーです。アプリケーションは複数のゲームコントローラーデバイスを持つことができます。 |
| HardwareTracker | ハードウェアトラッキングデバイスです。通常、ユーザーや物理的なアイテムに取り付けられます。複数のハードウェアトラッカーノードが可能です。 |
| ヘッド | XRシステムによって計算された、ユーザーの頭の中心点。 |
| LeftEye | ユーザーの左目。 |
| LeftHand | ユーザーの左手。 |
| RightEye | ユーザーの右目。 |
| RightHand | ユーザーの右手。 |
| TrackingReference | Oculus カメラなど、トラッキングの参照位置。複数のトラッキング参照ノードが可能です。 |
InputDevices.GetDevicesAtXRNode を使用して、特定の XRNode に関連付けられたデバイスのリストを取得します。以下の例は、左利きのコントローラーを取得する方法を示しています。
var leftHandDevices = new List<UnityEngine.XR.InputDevice>();
UnityEngine.XR.InputDevices.GetDevicesAtXRNode(UnityEngine.XR.XRNode.LeftHand, leftHandDevices);
if(leftHandDevices.Count == 1)
{
UnityEngine.XR.InputDevice device = leftHandDevices[0];
Debug.Log(string.Format("Device name '{0}' with role '{1}'", device.name, device.role.ToString()));
}
else if(leftHandDevices.Count > 1)
{
Debug.Log("Found more than one left hand!");
}
入力デバイスはフレームごとに一貫していますが、いつでも接続や切断が可能です。デバイスがプラットフォームに接続されているかどうかを繰り返し確認しないようにするには、InputDevices.deviceConnected と InputDevices.deviceDisconnected を使用して、デバイスが接続または切断されたときにアプリケーションに通知します。これらのコードにより、新しく接続された入力デバイスへの参照もできます。
複数のフレームにわたってこれらの参照を保持できるため、デバイスが切断される場合や、何らかの理由で使用できなくなることがあります。デバイスの入力がまだ使用可能かどうかを確認するには、InputDevice.isValid を使用します。入力デバイスにアクセスするスクリプトは、デバイスを使用する前の各フレームの開始時に、これをチェックする必要があります。
トリガーボタンの状態などの入力機能を特定の InputDevice から読み取ることができます。例えば、正しいトリガーの状態を読み取るには、以下のステップに従います。
TryGetFeatureValue() は機能の現在の値へのアクセスを試み、以下を返します。
特定のボタン、タッチ入力、またはジョイスティック軸の値を取得するには、CommonUsages クラスを使用します。CommonUsages には、位置や回転などのトラッキング機能だけでなく、XR 入力マッピングテーブルの各 InputFeatureUsage が含まれます。以下のコード例は、CommonUsages.triggerButton を使用して、ユーザーが現在、特定の InputDevice インスタンスのトリガーボタンを押しているかどうかを検出します。
bool triggerValue;
if (device.TryGetFeatureValue(UnityEngine.XR.CommonUsages.triggerButton, out triggerValue) && triggerValue)
{
Debug.Log("Trigger button is pressed.");
}
InputDevice.TryGetFeatureUsages メソッドを使用して、デバイスが提供するすべての InputFeatureUsage のリストを取得することもできます。この関数は、特徴を説明する type プロパティと name プロパティのある InputFeatureUsage アイテムのリストを返します。以下の例では、特定の入力デバイスが提供するすべてのブーリアン機能を列挙します。
var inputFeatures = new List<UnityEngine.XR.InputFeatureUsage>();
if (device.TryGetFeatureUsages(inputFeatures))
{
foreach (var feature in inputFeatures)
{
if (feature.type == typeof(bool))
{
bool featureValue;
if (device.TryGetFeatureValue(feature.As<bool>(), out featureValue))
{
Debug.Log(string.Format("Bool feature {0}'s value is {1}", feature.name, featureValue.ToString()));
}
}
}
}
コントローラーの設定によって、使用できる機能は異なります。例えば、1 つのシステムに複数のコントローラーを配置したり、異なるシステムに異なるコントローラーを配置したり、同じ SDK の異なるコントローラーに異なるボタンを配置したりできます。この多様性により、さまざまな XR システムからの入力をサポートすることがより複雑になります。Unity InputFeatureUsage APIは、プラットフォームに依存しない入力を取得するのに役立ちます。
以下の例では、提供するコントローラーや入力デバイスにかかわらず、primaryButton という InputFeatureUsage にアクセスします。この例には、接続時に primaryButton で使用可能なデバイスをスキャンするクラスが含まれています。クラスは接続されたデバイスの機能の値を監視し、値が変更された場合にクラスは UnityEvent をディスパッチします。
このクラスを使用するには、シーン内の任意のゲームオブジェクトにコンポーネントとして追加します。 例:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.XR;
[System.Serializable]
public class PrimaryButtonEvent : UnityEvent<bool> { }
public class PrimaryButtonWatcher : MonoBehaviour
{
public PrimaryButtonEvent primaryButtonPress;
private bool lastButtonState = false;
private List<InputDevice> devicesWithPrimaryButton;
private void Awake()
{
if (primaryButtonPress == null)
{
primaryButtonPress = new PrimaryButtonEvent();
}
devicesWithPrimaryButton = new List<InputDevice>();
}
void OnEnable()
{
List<InputDevice> allDevices = new List<InputDevice>();
InputDevices.GetDevices(allDevices);
foreach(InputDevice device in allDevices)
InputDevices_deviceConnected(device);
InputDevices.deviceConnected += InputDevices_deviceConnected;
InputDevices.deviceDisconnected += InputDevices_deviceDisconnected;
}
private void OnDisable()
{
InputDevices.deviceConnected -= InputDevices_deviceConnected;
InputDevices.deviceDisconnected -= InputDevices_deviceDisconnected;
devicesWithPrimaryButton.Clear();
}
private void InputDevices_deviceConnected(InputDevice device)
{
bool discardedValue;
if (device.TryGetFeatureValue(CommonUsages.primaryButton, out discardedValue))
{
devicesWithPrimaryButton.Add(device); // Add any devices that have a primary button.
}
}
private void InputDevices_deviceDisconnected(InputDevice device)
{
if (devicesWithPrimaryButton.Contains(device))
devicesWithPrimaryButton.Remove(device);
}
void Update()
{
bool tempState = false;
foreach (var device in devicesWithPrimaryButton)
{
bool primaryButtonState = false;
tempState = device.TryGetFeatureValue(CommonUsages.primaryButton, out primaryButtonState) // did get a value
&& primaryButtonState // the value we got
|| tempState; // cumulative result from other controllers
}
if (tempState != lastButtonState) // Button state changed since last frame
{
primaryButtonPress.Invoke(tempState);
lastButtonState = tempState;
}
}
}
以下の PrimaryReactor クラスは、PrimaryButtonWatcher を使用して主ボタンが押されたことを検出し、押されたことに応答して、親ゲームオブジェクトを回転させます。このクラスを使用するには、それを Cube などの表示可能なゲームオブジェクトに追加し、PrimaryButtonWatcher 参照を Watcher プロパティにドラッグします。
using System.Collections;
using UnityEngine;
public class PrimaryReactor : MonoBehaviour
{
public PrimaryButtonWatcher watcher;
public bool IsPressed = false; // used to display button state in the Unity Inspector window
public Vector3 rotationAngle = new Vector3(45, 45, 45);
public float rotationDuration = 0.25f; // seconds
private Quaternion offRotation;
private Quaternion onRotation;
private Coroutine rotator;
void Start()
{
watcher.primaryButtonPress.AddListener(onPrimaryButtonEvent);
offRotation = this.transform.rotation;
onRotation = Quaternion.Euler(rotationAngle) * offRotation;
}
public void onPrimaryButtonEvent(bool pressed)
{
IsPressed = pressed;
if (rotator != null)
StopCoroutine(rotator);
if (pressed)
rotator = StartCoroutine(AnimateRotation(this.transform.rotation, onRotation));
else
rotator = StartCoroutine(AnimateRotation(this.transform.rotation, offRotation));
}
private IEnumerator AnimateRotation(Quaternion fromRotation, Quaternion toRotation)
{
float t = 0;
while (t < rotationDuration)
{
transform.rotation = Quaternion.Lerp(fromRotation, toRotation, t / rotationDuration);
t += Time.deltaTime;
yield return null;
}
}
}
InputDevices はハンドトラッキングデバイスをサポートします。ハンドトラッキングデバイスには常に、
ハンドトラッキングデータは、Hand オブジェクトと一連の最大 21 ボーンの入力機能で構成されます。各ボーンには位置と方向があり、階層内の親ボーンと子ボーン両方への参照があります。Hand オブジェクトは、ルートのボーン、または個々の指のボーンのリストのいずれかを取得できます。
Hand.TryGetRootBone がルートのボーンを取得すると、手首の真上にあるボーンを表すオブジェクトを取得します。個々の指を表すボーンのリストを取得することもできます。Hand.TryGetFingerBones を呼び出すと、指を表すボーンの指関節から先端までのリストを返します。
入力デバイスは、アイトラッキングデバイスとハンドトラッキングデバイスをサポートしています。アイトラッキングは、左目と右目の位置、ユーザーが見ている 3D スペースの位置、個々の目が点滅している量で構成されます。データ型は Eyes です。デバイスから取得するには、CommonUsages.eyesData を使用します。
Unity には、古い Input System と、2019.2 で導入された XRプラグインアーキテクチャの、2 つの入力システムがあります。新しい設定では、各 InputDevice は XRInputSubsystem に関連付けられています。これらのサブシステムオブジェクトは、特定の入力デバイスに関連付けられていないグローバルな入力動作を制御します (例えば、追跡元の管理や追跡されたデバイスのリセンターなど)。
各 InputDevice には、関連するサブシステムへのリファレンスが含まれています。このリファレンスは、統合プラットフォームからのデバイスの場合は null です。また、すべてのアクティブな XRInputSubsystem オブジェクトは SubsystemManager.GetInstances<XRInputSubsystem> で取得でき、各 XRInputSubsystem は XRInputSubsystem.TryGetInputDevices でデバイスを取得できます。
Input Subsystem を使って、UnityEngine.XR.XRInputSubsystem を持つデバイスをリセンターできます。リセンターは、HMD の現在の位置をすべてのデバイスの新しい原点として設定します。リセンターできないデバイスの場合、またはプラットフォームがリセンター機能をサポートしていない場合は、false を返します。
トラッキング境界を取得するには、TryGetBoundaryPoints を使用します。これは一連の右回りの 3D 位置で構成され、Y 値はフロアレベルにあり、ユーザーが指定した “セーフゾーン” をマークしてコンテンツとインタラクションを配置します。XRInputSubsystem.boundaryChanged を使用して、この境界の変更をリッスンできます。
XRInputSubsystem はトラッキング原点モードも把握します。トラッキング原点モードは、トラッキングワールドの原点のコンテキストを提供します。Unity は以下のトラッキング原点モードをサポートしています。
トラッキング元モードの管理に使用できる API は 3 つあります。
Input と XR.InputTracking で構成した古い入力システムを使用して XR 入力特性を取得することもできます。これには、このページの XR 入力マッピングの表から、適切な古い入力インデックスを使用します。Player Settings の Input セクション (メニュー: Edit > Project Settings > Input) で軸のマッピングを行い、入力名からプラットフォームデバイス機能の軸インデックスに適切なマッピングを追加します。ボタンや軸の値を取得するには、Input.GetAxis または Input.GetButton を使用し、マップされた軸またはボタン名にパスします。
ボタンとジョイスティックの軸の使い方の詳細は、InputManager のドキュメントを参照してください。
InputDevice に触覚イベントを送信できます。ハプティクスは、振幅と継続時間によるインパルスの形をとります。
すべてのプラットフォームがすべてのタイプのハプティクスに対応しているわけではありませんが、デバイスにハプティックの能力を照会することができます。以下の例では、右手用の入力デバイスを使用し、デバイスがハプティクスに対応できるかどうかを確認します。次に、それが可能な場合は、インパルスを再生します。
List<UnityEngine.XR.InputDevice> devices = new List<UnityEngine.XR.InputDevice>();
UnityEngine.XR.InputDevices.GetDevicesWithRole(UnityEngine.XR.InputDeviceRole.RightHanded, devices);
foreach (var device in devices)
{
UnityEngine.XR.HapticCapabilities capabilities;
if (device.TryGetHapticCapabilities(out capabilities))
{
if (capabilities.supportsImpulse)
{
uint channel = 0;
float amplitude = 0.5f;
float duration = 1.0f;
device.SendHapticImpulse(channel, amplitude, duration);
}
}
}