PolySpatial 输入
PolySpatial软件包添加了一个新的输入设备“SpatialPointerDevice”,开发人员可以将其与输入系统动作图和API一起使用。
您可以利用Enhanced Touch API轮询触摸阶段。
Note
- 轮询状态时,SpatialPointerState阶段将永远无法有效使用。相反,请使用EnhancedTouch API 获取活动触摸并查询阶段。 *当基于“Kind.DirectPinch”的Spatial Pointer Kind枚举过滤输入时,建议在开始触摸阶段不要检查此项。这是因为通常会在检测到直接捏合之前调用“Kind.Touch”,并在稍后的触摸阶段设置直接捏合。
空间指针设备数据
SpatialPointerDevice反映了SwiftUI的SpatialEventCollection数据,是在visionOS上与内容交互的主要方式。输入数据的限制取决于应用程序的模式(有界与无界)以及您请求数据的时间。有些数据仅对执行输入的第一帧有效。
用户看着对象并用食指和拇指执行捏合手势来记录输入。这种类型的输入将注册为“Indirect Pinch”。还可以通过直接戳(“Touch”)或直接捏(“Direct Pinch”)对象来执行输入。
- 最多可同时注册两个输入。
- 用户正在查看的对象上必须有碰撞体才能捕获输入。
- “inputDevicePosition”和“inputDeviceRotation”属性描述了控制交互的输入设备的姿势。通常,这是基于用户的捏合(手指和拇指之间的点)。
- 默认情况下,交互光线基于用户的眼睛凝视。
“SpatialPointerDevice”提供以下属性:
- “.interactionPosition”:交互在世界空间中的位置。该值将在保持输入的同时更新,并且始终在碰撞体上启动。
- “.deltaInteractionPosition”:起始交互位置和当前交互位置之间的差值。
- “.startInteractionPosition”:交互的起始位置。这将始终位于碰撞体上,并且仅在输入发生时才会设置。
- “.startInteractionRayOrigin”:基于用户眼睛凝视的光线原点。仅当应用程序处于无界模式时才可用,并且仅在发生输入时才可用。
- “.startInteractionRayDirection”:基于用户眼睛凝视的光线方向。仅当应用程序处于无界模式时才可用,并且仅在发生输入时才可用。
- “.inputDevicePosition”:用户捏合的位置(在用户的拇指和食指之间)。当输入保持不变时,该值将被更新。
- “.inputDeviceRotation”:用户捏合的旋转(在用户的拇指和食指之间)。当输入保持不变时,该值将被更新。
- “.kind”:交互类型,触摸(戳),间接捏合,直接捏合,指针,手写笔。
- “.targetId”:正在交互的对象的实例ID。
- “.phase”:当前交互的空间指针触摸阶段。
- “.modifierKeys”:交互发生时处于活动状态的任何修饰键。
- “.targetObject”:对交互目标的GameObject的直接引用。
在动作图中使用空间指针
“Spatial Pointer Device”列在输入操作映射的“Other”部分中。有一个用于检测主要交互的“Primary Spatial Pointer”,以及分别用于第一和第二交互的“Spatial Pointer #0”和“Spatial Pointer #1”。
在直接代码中使用空间指针
根据活动触摸输入显示“SpatialPointerState”数据的脚本。
using Unity.PolySpatial.InputDevices;
using UnityEngine;
using UnityEngine.InputSystem.EnhancedTouch;
using UnityEngine.InputSystem.LowLevel;
using Touch = UnityEngine.InputSystem.EnhancedTouch.Touch;
public class InputScript : MonoBehaviour
{
void OnEnable()
{
EnhancedTouchSupport.Enable();
}
void Update()
{
var activeTouches = Touch.activeTouches;
// You can determine the number of active inputs by checking the count of activeTouches
if (activeTouches.Count > 0)
{
// For getting access to PolySpatial (visionOS) specific data you can pass an active touch into the EnhancedSpatialPointerSupport()
SpatialPointerState primaryTouchData = EnhancedSpatialPointerSupport.GetPointerState(activeTouches[0]);
SpatialPointerKind interactionKind = primaryTouchData.Kind;
GameObject objectBeingInteractedWith = primaryTouchData.targetObject;
Vector3 interactionPosition = primaryTouchData.interactionPosition;
}
}
}
根据类型限制交互
您可以检查空间指针设备数据以限制允许的交互类型。以下示例仅执行间接捏和戳交互的输入逻辑:
var activeTouches = Touch.activeTouches;
if (activeTouches.Count > 0)
{
SpatialPointerState primaryTouchData = EnhancedSpatialPointerSupport.GetPointerState(activeTouches[0]);
if (primaryTouchData.Kind == SpatialPointerKind.IndirectPinch || primaryTouchData.Kind == SpatialPointerKind.Touch)
{
// do input logic here
}
}
选择、移动和旋转对象
您可以基于交互位置和设备旋转更新对象的位置和旋转。以下示例显示如何根据触摸阶段选择对象、平移和旋转对象以及取消选择对象:
using UnityEngine;
using Unity.PolySpatial.InputDevices;
using UnityEngine.InputSystem.LowLevel;
using Touch = UnityEngine.InputSystem.EnhancedTouch.Touch;
using TouchPhase = UnityEngine.InputSystem.TouchPhase;
public class InputScript : MonoBehaviour
{
GameObject m_SelectedObject;
void Update()
{
var activeTouches = Touch.activeTouches;
if (activeTouches.Count > 0)
{
SpatialPointerState primaryTouchData = EnhancedSpatialPointerSupport.GetPointerState(activeTouches[0]);
if (activeTouches[0].phase == TouchPhase.Began)
{
// if the targetObject is not null, set it to the selected object
m_SelectedObject = primaryTouchData.targetObject != null ? primaryTouchData.targetObject : null;
}
if (activeTouches[0].phase == TouchPhase.Moved)
{
if (m_SelectedObject != null)
{
m_SelectedObject.transform.SetPositionAndRotation(primaryTouchData.interactionPosition, primaryTouchData.deviceRotation);
}
}
if(activeTouches[0].phase == TouchPhase.Ended || activeTouches[0].phase == TouchPhase.Canceled)
{
m_SelectedObject = null;
}
}
}
}