Unityユーザーマニュアルのこのセクションでは、仮想現実 (VR)、 拡張現実 (AR)、 Windows Mixed Reality アプリケーションのために Unity がサポートするすべての入力デバイスに関する情報を提供します。このページでは、以下のトピックについて説明します。
XR プラットフォームには豊富な種類の入力機能があり、 ユーザーインタラクションを設計するときに便利です。アプリケーションは、位置、回転、タッチ、ボタン、ジョイスティック、指センサーを参照する特定のデータを使用できます。ただし、これらの入力機能へのアクセスは、プラットフォームによって大きく異なります。例えば、Vive と Oculus Rift の間には多少違いがありますが、VR 対応のデスクトッププラットフォームと Daydream のようなモバイルプラットフォームでは、さらに多くの違いがあります。
Unity は InputFeatureUsage と呼ばれる C# 構造体を提供します。これは、任意のプラットフォームの ユーザー入力にアクセスするための標準の一群の物理的なデバイス制御 (ボタンやトリガーなど) を定義します。これらは、名前によって入力タイプを識別するのに役立ちます。各 InputFeatureUsage
定義については XR.Input.CommonUsages を参照してください。
各 InputFeatureUsage
は、一般的な入力アクションまたはタイプに対応します。例えば、Unity は、人差し指で制御する (使用する XR プラットフォームに関係なく)、シングル軸の入力に trigger
と呼ばれる InputFeatureUsage
を定義します。InputFeatureUsage
を使用すると、その名前を使用して trigger
状態を取得できます。そのため、従来の Unity Input システムの軸 (または、一部の XR プラットフォームではボタン) を設定する必要はありません。
以下の表は、標準コントローラーの InputFeatureUsage
の名前と、それらが一般的な XR システムのコントローラーにどのようにマップされるかを示しています。
InputFeatureUsage | 機能タイプ | 古い入力インデックス (左コントローラー/右コントローラー) | WMR | Oculus | GearVR | Daydream | OpenVR (全般) | Vive | OpenVR 経由の Oculus | OpenVR 経由の WMR |
---|---|---|---|---|---|---|---|---|---|---|
primary2DAxis | 2D 軸 | [(1,2)/(4,5)] | タッチパッド | ジョイスティック | タッチパッド | タッチパッド | トラックパッド/ジョイスティック | トラックパッド | ジョイスティック | ジョイスティック |
trigger | 軸 | [9/10] | トリガー | トリガー | トリガー | トリガー | トリガー | トリガー | トリガー | トリガー |
grip | 軸 | [11/12] | グリップ | グリップ | バンパー | グリップ | グリップ | グリップ | グリップ | |
secondary2DAxis | 2D 軸 | [(17,18)/(19,20)] | ジョイスティック | タッチパッド | ||||||
secondary2DAxisClick | ボタン | [18/19] | ジョイスティック - クリック | |||||||
primaryButton | ボタン | [2/0] | [X/A] - 押す | アプリケーション | 主要 | プライマリ(サンドイッチボタン)(1) | 主要 [Y/B] | メニュー | ||
primaryTouch | ボタン | [12/10] | [X/A] - タッチ | |||||||
secondaryButton | ボタン | [3/1] | [Y/B] - 押す | 代替 | 代替 (X/A) | |||||
secondaryTouch | ボタン | [13/11] | [Y/B] - タッチ | |||||||
gripButton | ボタン | [4/5] | グリップ - 押す | グリップ - 押す | グリップ - 押す | グリップ - 押す | グリップ - 押す | グリップ - 押す | ||
triggerButton | ボタン | [14/15] | トリガー - 押す | トリガー - 押す | トリガー - 押す | トリガー - 押す | トリガー - 押す | トリガー - 押す | トリガー - タッチ | トリガー - 押す |
menuButton | ボタン | [6/7] | メニュー | スタート (左コントローラーのみ) | ||||||
primary2DAxisClick | ボタン | [8/9] | タッチパッド - クリック | サムスティック - 押す | タッチパッド - 押す | タッチパッド - 押す | トラックパッド/ジョイスティック - 押す | トラックパッド - 押す | ジョイスティック - 押す | タッチパッド - 押す |
primary2DAxisTouch | ボタン | [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
がまだアクティブなコントローラーを示しているかを判断するには、InputDevice.IsValid プロパティを使用します。
以下の方法で入力デバイスにアクセスできます。
デバイスの特性 (Characteristics) は、 デバイスの機能や使用目的 (ヘッドマウントかどうかなど) を表します。 InputDeviceCharacteristics は、特定の仕様に適合するデバイスを検索するためにコードに追加できる一連のフラグです。以下の特性でデバイスをフィルタリングできます。
デバイス | 特徴 |
---|---|
HeadMounted | デバイスはユーザーの頭に装着されます。 デバイストラッキングとセンターアイトラッキングがあります。このフラグは、大抵、ヘッドマウントディスプレイ (HMD) を識別するために使用されます。 |
Camera | デバイスにはカメラトラッキングがあります。 |
HeldInHand | ユーザーはデバイスを手に持っています。 |
HandTracking | デバイスは、物理的に追跡される手を表します。 デバイストラッキングがあり、手とボーンの データが含まれている場合があります。 |
EyeTracking | このデバイスはアイトラッキングを実行でき、 EyesData 機能を備えています。 |
TrackedDevice | デバイスは 3D スペースで追跡されます。 デバイストラッキング機能があります。 |
Controller | デバイスはボタンと軸の入力 データを持ち、 コントローラーとして使用できます。 |
TrackingReference | デバイスは静的トラッキング参照オブジェクトを表します。 デバイスのトラッキング機能がありますが、トラッキングデータを変更しないでください。 |
Left | この特性をHeldInHandまたはHandTracking特性と組み合わせて使用して、 デバイスを左手に関連付けられていると識別します 。 |
Right | この特性を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 | ハードウェアトラッキングデバイス。通常、ユーザーや物理的なアイテムに取り付けられます。複数のハードウェアトラッカーノードが可能です。 |
Head | 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
リストを取得することもできます。この関数は、InputFeatureUsage 項目のリストを返します。項目は、機能を説明するtypeとname プロパティを持っています。次の例では、指定された入力デバイスが提供するすべてのブール機能を列挙します。
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は、プラットフォームに依存しない入力を取得するのに役立ちます。
次の例では、アクセス InputFeatureUsage
呼ば primaryButton
、 コントローラーや入力 デバイスがそれを提供しない物質を。この例には、接続時に 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
オブジェクトに追加し、 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のBone 入力機能で構成されます。各Boneには位置と方向があり、階層内の親Boneと子Boneの両方への参照があります。 Hand オブジェクトは、 ルートの ボーン、または個々の指のボーンのリストのいずれかを取得できます。
Hand.TryGetRootBone がルートのボーンを取得すると、手首の真上にあるボーンを表すオブジェクトを取得します。個々の指を表すボーンのリストを取得することもできます。Hand.TryGetFingerBones を呼び出すと、指を表すボーンの指関節 (knuckle) から先端までのリストを返します。
入力デバイスは、アイトラッキングデバイスとハンドトラッキングデバイスをサポートしています。アイトラッキングは、左目と右目の位置、 ユーザーが見ている3D スペースの位置、個々の目が点滅している量で構成されます。データ型は Eyesです。デバイスから取得するにはCommonUsages.eyesDataを使用します。
Unity は 2 つの入力システムを提供します。古い入力システムと 2019.2 で導入されたXR プラグインアーキテクチャです。新しい設定では、各 InputDevice は XRInputSubsystem に関連付けられています。これらのサブシステムオブジェクトは、特定の入力デバイスに関連付けられていないグローバルな入力動作を制御します (例えば、追跡元の管理や追跡されたデバイスのリセンターなど)。
各 InputDevice には、関連するサブシステムへの参照が含まれています。統合プラットフォームのデバイスの場合、この参照は null です。また、SubsystemManager.GetInstances<XRInputSubsystem> を使って、すべてのアクティブな 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 input mappings table の適切な古い入力インデックスを使います。Player 設定 (Edit > Project Settings > Input) の 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);
}
}
}