参考资料
https://docs.unity3d.com/cn/2022.2/Manual/class-InputManager.html
学习路线
-
了解Unity在PC端如何获取鼠标键盘的输入事件,了解Input
-
了解Unity如何获取XR的输入事件,了解InputDevices
-
了解XR Interaction Toolkit,了解Unity的输入的高阶用法
名词解释
HMD:头戴,Head Mounted Display
Unity的两套独立的输入系统
InputManager:旧版的输入系统
InputSystem:新版的输入系统
输入系统不影响API的使用。
Unity 支持来自多种输入设备的输入,包括:
-
键盘和鼠标
-
游戏杆
-
控制器
-
触摸屏
-
加速度计或陀螺仪等移动设备的运动感应功能
-
VR 和 AR 控制器
float horizontalInput = Input.GetAxis ("Horizontal");
float moveSpeed = 10;
//定义对象移动的速度。
float horizontalInput = Input.GetAxis("Horizontal");
//获取水平输入轴的数值。
float verticalInput = Input.GetAxis("Vertical");
//获取垂直输入轴的数值。
transform.Translate(new Vector3(horizontalInput, verticalInput, 0) * moveSpeed * Time.deltaTime);
//将对象移动到 XYZ 坐标,分别定义为 horizontalInput、0 以及 verticalInput。
移动端输入:触碰点
void Update()
{
foreach(Touch touch in Input.touches)
{
if (touch.phase == TouchPhase.Began)
{
// 从当前触摸坐标构造一条射线
Ray ray = Camera.main.ScreenPointToRay(touch.position);
if (Physics.Raycast(ray))
{
// 如果命中,则创建一个粒子
Instantiate(particle, transform.position, transform.rotation);
}
}
}
}
加速度计
using UnityEngine;
public class Accelerometer : MonoBehaviour
{
float speed = 10.0f;
void Update()
{
Vector3 dir = Vector3.zero;
// 我们假设设备与地面平行,
// 主屏幕按钮位于右侧
// 将设备的加速度轴重新映射到游戏坐标:
// 1) 设备的 XY 平面映射到 XZ 平面
// 2) 绕 Y 轴旋转 90 度
dir.x = -Input.acceleration.y;
dir.z = Input.acceleration.x;
// 将加速度矢量限制为单位球体
if (dir.sqrMagnitude > 1)
dir.Normalize();
// 使其每秒移动 10 米而不是每帧 10 米...
dir *= Time.deltaTime;
// 移动对象
transform.Translate(dir * speed);
}
}
XR输入系统
Unity的输入系统一般只通过Input这个类就能够实现。
但是对于XR,目前推荐使用InputDevices这个类作为入口类。
Unity的Input、XR.InputTracking这两个类也能够获取XR输入,但是不鼓励使用,尽量使用InputDevices,这样语义更明确、语法更简洁。Input的缺点在于没法以向量的形式获取数据。
以Input为例,要想获取primaryAxis,就需要Input.GetAxis(1),Input.GetAxis(2),这样才能获取左手的摇杆位置;Input.GetAxis(4),Input.GetAxis(5)才能够获取右手的摇杆位置。
primary2DAxis [(1,2)/(4,5)]
InputDevices
InputDevices
静态
InputDevices的静态函数只有一个目标:获取InputDevice。它提供了几种检索InputDevice的方式
-
通过XRNode获取,这也是最常用的方式
-
通过Role获取,对应枚举InputDeviceRole
-
通过Characteristics获取,对应枚举InputDeviceCharacteristics
-
GetDeviceAtXRNode:根据XRNode获取InputDevice
-
GetDevicesAtRole:根据Role获取设备
-
GetDevicesWithCharacteristics:根据设别的特性获取设备。
成员
-
DeviceRole:设备的角色,InputDeviceRole
-
TryGet+(InputFeatureType中的数据类型):从设备读取数据
事件:
-
设备连接
-
设备断连
-
设备配置发生变化
获取全部的可用设备
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()));
}
XRNode
-
左眼
-
右眼
-
中心眼
-
头
-
左手
-
右手
-
游戏控制器
-
跟踪参照物
-
硬件跟踪器
XRNode跟InputDeviceRole基本上是同一类东西。
InputDeviceCharacteristics
一个设备可能包含多种特性,使用一个int值表示一个设备的特性,例如HeldInHand|Left表示左右持有的设备。就像使用rwx表示一个文件的特性一样。
-
HeadMounted
-
Camera
-
HeldInHand
-
HandTracking
-
EyeTracking
-
TrackedDevice
-
Controller
-
TrackingReference
-
Left
-
Right
InputDeviceRole
输入设备的角色,包括:
-
左手持有
-
右手持有
-
游戏控制器
-
跟踪参照物
-
硬件跟踪器
public enum InputDeviceRole : uint
{
/// <summary>
/// <para>This device does not have a known role.</para>
/// </summary>
Unknown,
/// <summary>
/// <para>This device is typically a HMD or Camera.</para>
/// </summary>
Generic,
/// <summary>
/// <para>This device is a controller that represents the left hand.</para>
/// </summary>
LeftHanded,
/// <summary>
/// <para>This device is a controller that represents the right hand.</para>
/// </summary>
RightHanded,
/// <summary>
/// <para>This device is a game controller.</para>
/// </summary>
GameController,
/// <summary>
/// <para>This device is a tracking reference used to track other devices in 3D.</para>
/// </summary>
TrackingReference,
/// <summary>
/// <para>This device is a hardware tracker.</para>
/// </summary>
HardwareTracker,
/// <summary>
/// <para>This device is a legacy controller.</para>
/// </summary>
LegacyController,
}
触觉
Haptic是触觉的意思,有些游戏手柄支持触觉。
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);
}
}
}
XR Input Tracking:Unity旧版XR输入接口
InputTracking
Unity.Xr.InputTracking是Unity旧版的输入入口类。
设备事件
输入设备的跟踪有四个事件
-
trackingAcquired:获取设备跟踪
-
trackingLost:设备丢失
-
nodeAdded:设备添加
-
nodeRemoved:设备移除
读取数据
-
获取XRNode的位置
-
获取XRNode的Rotation
-
获取XRNode的DeviceId
从InputTracking中读取数据已经不鼓励使用了,请使用InputDevices。例如获取设备地址。
[NativeConditional("ENABLE_VR", "Vector3f::zero")]
[Obsolete("This API is obsolete, and should no longer be used. Please use InputDevice.TryGetFeatureValue with the CommonUsages.devicePosition usage instead.")]
public static Vector3 GetLocalPosition(XRNode node)
{
Vector3 ret;
InputTracking.GetLocalPosition_Injected(node, out ret);
return ret;
}
XRNodeState
XNode:结点的类型
AwailableTrackingData:可用的数据列表
位置
角度
速度
角速度
加速度
角加速度
tracked:是否正在跟踪
AwailableTrackingData
枚举,描述一个XRNodeState可用的数据列表可以组合这个枚举,例如位置|旋转,表示这个XRNodeState可用的数据是位置和旋转。
-
位置
-
旋转
-
速度
-
角速度
-
加速度
-
角加速度
InputFeatureUsage
InputFeatureUsage
Unity引擎里面的类,定义了一个输入类型,可以描述所有的输入。它包含的字段:
-
name:输入的名称
-
UsageType:输入的类型
InputFeatureType
internal enum InputFeatureType : uint
{
Custom = 0,//Custom类型,使用byte数组表示
Binary = 1,//bool
DiscreteStates = 2,//uint,枚举状态
Axis1D = 3,//一维浮点
Axis2D = 4,//二维浮点:例如鼠标
Axis3D = 5,//三维浮点
Rotation = 6,//角度,Quaternion,四元数
Hand = 7,//Hand类型
Bone = 8,//Bone类型
Eyes = 9,//眼睛
kUnityXRInputFeatureTypeInvalid = 4294967295, // 0xFFFFFFFF,未定义的操作类型
}
InputFeature中涉及到的结构体
Hand、Bone、Eyes
Bone
-
deviceId:设备ID
-
featureIndex:featureID
-
Position
-
Rotation
-
ParentBone:父骨骼
-
ChildBones:List
Eyes
眼睛有左眼和右眼:
-
LeftEyes
-
RightEyes
以下传感器是左眼和右眼都有的。
-
EyeRotation
-
EyePosition
-
FixationPoint:修正点的位置
-
OpenAmount:眼睛的睁开量
Hand类型
Hand是一个Bone的封装,一个Hand包含一个RootBone和多个FingerBones
-
设备Id
-
FeatureIndex
-
RootBone:Bone
-
FingerBones:List
返回手指骨骼列表
Unity支持的输入的类型:InputFeatureType。
-
bool
-
uint
-
float
CommonUsages
UnityEngine.XR中定义了一些InputFeatureUsage,与Pico XR SDK的InputFeatureUsage类似。
CommonUsage中定义的是比较通用的InputFeatureUsage,而PXR_Usage中存放的是Pico特有的InputFeatureUsage,这些featureUsage大多是与眼睛有关系。
/// <summary>
/// <para>Informs to the developer whether the device is currently being tracked.</para>
/// </summary>
public static InputFeatureUsage<bool> isTracked = new InputFeatureUsage<bool>("IsTracked");
/// <summary>
/// <para>The primary face button being pressed on a device, or sole button if only one is available.</para>
/// </summary>
public static InputFeatureUsage<bool> primaryButton = new InputFeatureUsage<bool>("PrimaryButton");
/// <summary>
/// <para>The primary face button being touched on a device.</para>
/// </summary>
public static InputFeatureUsage<bool> primaryTouch = new InputFeatureUsage<bool>("PrimaryTouch");
/// <summary>
/// <para>The secondary face button being pressed on a device.</para>
/// </summary>
public static InputFeatureUsage<bool> secondaryButton = new InputFeatureUsage<bool>("SecondaryButton");
/// <summary>
/// <para>The secondary face button being touched on a device.</para>
/// </summary>
public static InputFeatureUsage<bool> secondaryTouch = new InputFeatureUsage<bool>("SecondaryTouch");
/// <summary>
/// <para>A binary measure of whether the device is being gripped.</para>
/// </summary>
public static InputFeatureUsage<bool> gripButton = new InputFeatureUsage<bool>("GripButton");
/// <summary>
/// <para>A binary measure of whether the index finger is activating the trigger.</para>
/// </summary>
public static InputFeatureUsage<bool> triggerButton = new InputFeatureUsage<bool>("TriggerButton");
/// <summary>
/// <para>Represents a menu button, used to pause, go back, or otherwise exit gameplay.</para>
/// </summary>
public static InputFeatureUsage<bool> menuButton = new InputFeatureUsage<bool>("MenuButton");
/// <summary>
/// <para>Represents the primary 2D axis being clicked or otherwise depressed.</para>
/// </summary>
public static InputFeatureUsage<bool> primary2DAxisClick = new InputFeatureUsage<bool>("Primary2DAxisClick");
/// <summary>
/// <para>Represents the primary 2D axis being touched.</para>
/// </summary>
public static InputFeatureUsage<bool> primary2DAxisTouch = new InputFeatureUsage<bool>("Primary2DAxisTouch");
/// <summary>
/// <para>Represents the secondary 2D axis being clicked or otherwise depressed.</para>
/// </summary>
public static InputFeatureUsage<bool> secondary2DAxisClick = new InputFeatureUsage<bool>("Secondary2DAxisClick");
/// <summary>
/// <para>Represents the secondary 2D axis being touched.</para>
/// </summary>
public static InputFeatureUsage<bool> secondary2DAxisTouch = new InputFeatureUsage<bool>("Secondary2DAxisTouch");
/// <summary>
/// <para>Indicates whether the user is present and interacting with the device.</para>
/// </summary>
public static InputFeatureUsage<bool> userPresence = new InputFeatureUsage<bool>("UserPresence");
/// <summary>
/// <para>Represents the values being tracked for this device.</para>
/// </summary>
public static InputFeatureUsage<InputTrackingState> trackingState = new InputFeatureUsage<InputTrackingState>("TrackingState");
/// <summary>
/// <para>Value representing the current battery life of this device.</para>
/// </summary>
public static InputFeatureUsage<float> batteryLevel = new InputFeatureUsage<float>("BatteryLevel");
/// <summary>
/// <para>A trigger-like control, pressed with the index finger.</para>
/// </summary>
public static InputFeatureUsage<float> trigger = new InputFeatureUsage<float>("Trigger");
/// <summary>
/// <para>Represents the users grip on the controller.</para>
/// </summary>
public static InputFeatureUsage<float> grip = new InputFeatureUsage<float>("Grip");
/// <summary>
/// <para>The primary touchpad or joystick on a device.</para>
/// </summary>
public static InputFeatureUsage<Vector2> primary2DAxis = new InputFeatureUsage<Vector2>("Primary2DAxis");
/// <summary>
/// <para>A secondary touchpad or joystick on a device.</para>
/// </summary>
public static InputFeatureUsage<Vector2> secondary2DAxis = new InputFeatureUsage<Vector2>("Secondary2DAxis");
/// <summary>
/// <para>The position of the device.</para>
/// </summary>
public static InputFeatureUsage<Vector3> devicePosition = new InputFeatureUsage<Vector3>("DevicePosition");
/// <summary>
/// <para>The position of the left eye on this device.</para>
/// </summary>
public static InputFeatureUsage<Vector3> leftEyePosition = new InputFeatureUsage<Vector3>("LeftEyePosition");
/// <summary>
/// <para>The position of the right eye on this device.</para>
/// </summary>
public static InputFeatureUsage<Vector3> rightEyePosition = new InputFeatureUsage<Vector3>("RightEyePosition");
/// <summary>
/// <para>The position of the center eye on this device.</para>
/// </summary>
public static InputFeatureUsage<Vector3> centerEyePosition = new InputFeatureUsage<Vector3>("CenterEyePosition");
/// <summary>
/// <para>The position of the color camera on this device.</para>
/// </summary>
public static InputFeatureUsage<Vector3> colorCameraPosition = new InputFeatureUsage<Vector3>("CameraPosition");
/// <summary>
/// <para>The velocity of the device.</para>
/// </summary>
public static InputFeatureUsage<Vector3> deviceVelocity = new InputFeatureUsage<Vector3>("DeviceVelocity");
/// <summary>
/// <para>The angular velocity of this device, formatted as euler angles.</para>
/// </summary>
public static InputFeatureUsage<Vector3> deviceAngularVelocity = new InputFeatureUsage<Vector3>("DeviceAngularVelocity");
/// <summary>
/// <para>The velocity of the left eye on this device.</para>
/// </summary>
public static InputFeatureUsage<Vector3> leftEyeVelocity = new InputFeatureUsage<Vector3>("LeftEyeVelocity");
/// <summary>
/// <para>The angular velocity of the left eye on this device, formatted as euler angles.</para>
/// </summary>
public static InputFeatureUsage<Vector3> leftEyeAngularVelocity = new InputFeatureUsage<Vector3>("LeftEyeAngularVelocity");
/// <summary>
/// <para>The velocity of the right eye on this device.</para>
/// </summary>
public static InputFeatureUsage<Vector3> rightEyeVelocity = new InputFeatureUsage<Vector3>("RightEyeVelocity");
/// <summary>
/// <para>The angular velocity of the right eye on this device, formatted as euler angles.</para>
/// </summary>
public static InputFeatureUsage<Vector3> rightEyeAngularVelocity = new InputFeatureUsage<Vector3>("RightEyeAngularVelocity");
/// <summary>
/// <para>The velocity of the center eye on this device.</para>
/// </summary>
public static InputFeatureUsage<Vector3> centerEyeVelocity = new InputFeatureUsage<Vector3>("CenterEyeVelocity");
/// <summary>
/// <para>The angular velocity of the center eye on this device, formatted as euler angles.</para>
/// </summary>
public static InputFeatureUsage<Vector3> centerEyeAngularVelocity = new InputFeatureUsage<Vector3>("CenterEyeAngularVelocity");
/// <summary>
/// <para>The velocity of the color camera on this device.</para>
/// </summary>
public static InputFeatureUsage<Vector3> colorCameraVelocity = new InputFeatureUsage<Vector3>("CameraVelocity");
/// <summary>
/// <para>The angular velocity of the color camera on this device, formatted as euler angles.</para>
/// </summary>
public static InputFeatureUsage<Vector3> colorCameraAngularVelocity = new InputFeatureUsage<Vector3>("CameraAngularVelocity");
/// <summary>
/// <para>The acceleration of the device.</para>
/// </summary>
public static InputFeatureUsage<Vector3> deviceAcceleration = new InputFeatureUsage<Vector3>("DeviceAcceleration");
/// <summary>
/// <para>The angular acceleration of this device, formatted as euler angles.</para>
/// </summary>
public static InputFeatureUsage<Vector3> deviceAngularAcceleration = new InputFeatureUsage<Vector3>("DeviceAngularAcceleration");
/// <summary>
/// <para>The acceleration of the left eye on this device.</para>
/// </summary>
public static InputFeatureUsage<Vector3> leftEyeAcceleration = new InputFeatureUsage<Vector3>("LeftEyeAcceleration");
/// <summary>
/// <para>The angular acceleration of the left eye on this device, formatted as euler angles.</para>
/// </summary>
public static InputFeatureUsage<Vector3> leftEyeAngularAcceleration = new InputFeatureUsage<Vector3>("LeftEyeAngularAcceleration");
/// <summary>
/// <para>The acceleration of the right eye on this device.</para>
/// </summary>
public static InputFeatureUsage<Vector3> rightEyeAcceleration = new InputFeatureUsage<Vector3>("RightEyeAcceleration");
/// <summary>
/// <para>The angular acceleration of the right eye on this device, formatted as euler angles.</para>
/// </summary>
public static InputFeatureUsage<Vector3> rightEyeAngularAcceleration = new InputFeatureUsage<Vector3>("RightEyeAngularAcceleration");
/// <summary>
/// <para>The acceleration of the center eye on this device.</para>
/// </summary>
public static InputFeatureUsage<Vector3> centerEyeAcceleration = new InputFeatureUsage<Vector3>("CenterEyeAcceleration");
/// <summary>
/// <para>The angular acceleration of the center eye on this device, formatted as euler angles.</para>
/// </summary>
public static InputFeatureUsage<Vector3> centerEyeAngularAcceleration = new InputFeatureUsage<Vector3>("CenterEyeAngularAcceleration");
/// <summary>
/// <para>The acceleration of the color camera on this device.</para>
/// </summary>
public static InputFeatureUsage<Vector3> colorCameraAcceleration = new InputFeatureUsage<Vector3>("CameraAcceleration");
/// <summary>
/// <para>The angular acceleration of the color camera on this device, formatted as euler angles.</para>
/// </summary>
public static InputFeatureUsage<Vector3> colorCameraAngularAcceleration = new InputFeatureUsage<Vector3>("CameraAngularAcceleration");
/// <summary>
/// <para>The rotation of this device.</para>
/// </summary>
public static InputFeatureUsage<Quaternion> deviceRotation = new InputFeatureUsage<Quaternion>("DeviceRotation");
/// <summary>
/// <para>The rotation of the left eye on this device.</para>
/// </summary>
public static InputFeatureUsage<Quaternion> leftEyeRotation = new InputFeatureUsage<Quaternion>("LeftEyeRotation");
/// <summary>
/// <para>The rotation of the right eye on this device.</para>
/// </summary>
public static InputFeatureUsage<Quaternion> rightEyeRotation = new InputFeatureUsage<Quaternion>("RightEyeRotation");
/// <summary>
/// <para>The rotation of the center eye on this device.</para>
/// </summary>
public static InputFeatureUsage<Quaternion> centerEyeRotation = new InputFeatureUsage<Quaternion>("CenterEyeRotation");
/// <summary>
/// <para>The rotation of the color camera on this device.</para>
/// </summary>
public static InputFeatureUsage<Quaternion> colorCameraRotation = new InputFeatureUsage<Quaternion>("CameraRotation");
/// <summary>
/// <para>Value representing the hand data for this device.</para>
/// </summary>
public static InputFeatureUsage<Hand> handData = new InputFeatureUsage<Hand>("HandData");
/// <summary>
/// <para>An Eyes struct containing eye tracking data collected from the device.</para>
/// </summary>
public static InputFeatureUsage<Eyes> eyesData = new InputFeatureUsage<Eyes>("EyesData");
/// <summary>
/// <para>A non-handed 2D axis.</para>
/// </summary>
[Obsolete("CommonUsages.dPad is not used by any XR platform and will be removed.")]
public static InputFeatureUsage<Vector2> dPad = new InputFeatureUsage<Vector2>("DPad");
/// <summary>
/// <para>Represents the grip pressure or angle of the index finger.</para>
/// </summary>
[Obsolete("CommonUsages.indexFinger is not used by any XR platform and will be removed.")]
public static InputFeatureUsage<float> indexFinger = new InputFeatureUsage<float>("IndexFinger");
/// <summary>
/// <para>Represents the grip pressure or angle of the middle finger.</para>
/// </summary>
[Obsolete("CommonUsages.MiddleFinger is not used by any XR platform and will be removed.")]
public static InputFeatureUsage<float> middleFinger = new InputFeatureUsage<float>("MiddleFinger");
/// <summary>
/// <para>Represents the grip pressure or angle of the ring finger.</para>
/// </summary>
[Obsolete("CommonUsages.RingFinger is not used by any XR platform and will be removed.")]
public static InputFeatureUsage<float> ringFinger = new InputFeatureUsage<float>("RingFinger");
/// <summary>
/// <para>Represents the grip pressure or angle of the pinky finger.</para>
/// </summary>
[Obsolete("CommonUsages.PinkyFinger is not used by any XR platform and will be removed.")]
public static InputFeatureUsage<float> pinkyFinger = new InputFeatureUsage<float>("PinkyFinger");
/// <summary>
/// <para>Represents a thumbrest or light thumb touch.</para>
/// </summary>
[Obsolete("CommonUsages.thumbrest is Oculus only, and is being moved to their package. Please use OculusUsages.thumbrest. These will still function until removed.")]
public static InputFeatureUsage<bool> thumbrest = new InputFeatureUsage<bool>("Thumbrest");
/// <summary>
/// <para>Represents a touch of the trigger or index finger.</para>
/// </summary>
[Obsolete("CommonUsages.indexTouch is Oculus only, and is being moved to their package. Please use OculusUsages.indexTouch. These will still function until removed.")]
public static InputFeatureUsage<float> indexTouch = new InputFeatureUsage<float>("IndexTouch");
/// <summary>
/// <para>Represents the thumb pressing any input or feature.</para>
/// </summary>
[Obsolete("CommonUsages.thumbTouch is Oculus only, and is being moved to their package. Please use OculusUsages.thumbTouch. These will still function until removed.")]
public static InputFeatureUsage<float> thumbTouch = new InputFeatureUsage<float>("ThumbTouch");