不知道是我没找对地方,还是官方那个把这个藏的严,又或者用了什么XR的通用标砖?反正我在官方引导文档里找到的很少,不够,所以自己测试了以下几个,还算可以哦。
有需要的朋友可以看看试试呢。如果对你有帮助啊,麻烦点个赞哦。
一、先纠正核心:Pico SDK 3.4 的命名空间
3.4 已经完全重构,现在的核心命名空间是:
cs
using UnityEngine.XR;
using Unity.XR.PXR;
之前的 Pvr_UnitySDKAPI 已经被废弃了,现在统一用 Unity.XR.PXR 下的类。
二、Pico SDK 3.4 常用 API(头盔 / 手柄 / 按键 / 摇杆)
- 头盔(头显)数据
cs
// 获取 XR 头显设备
InputDevice headDevice = InputDevices.GetDeviceAtXRNode(XRNode.Head);
// 位置
if (headDevice.TryGetFeatureValue(CommonUsages.devicePosition, out Vector3 headPos))
{
Debug.Log("头盔位置:" + headPos);
}
// 旋转
if (headDevice.TryGetFeatureValue(CommonUsages.deviceRotation, out Quaternion headRot))
{
Debug.Log("头盔旋转:" + headRot.eulerAngles);
}
- 手柄(控制器)基础数据
cs
// 左手柄
InputDevice leftController = InputDevices.GetDeviceAtXRNode(XRNode.LeftHand);
// 右手柄
InputDevice rightController = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
// 手柄位置
if (leftController.TryGetFeatureValue(CommonUsages.devicePosition, out Vector3 leftPos))
{
Debug.Log("左手柄位置:" + leftPos);
}
// 手柄旋转
if (rightController.TryGetFeatureValue(CommonUsages.deviceRotation, out Quaternion rightRot))
{
Debug.Log("右手柄旋转:" + rightRot.eulerAngles);
}
// 手柄是否连接
bool leftConnected = leftController.isValid;
bool rightConnected = rightController.isValid;
- 按键输入(3.4 用 XR 标准键位)
cs
// 右手柄 A 键按下
if (rightController.TryGetFeatureValue(CommonUsages.primaryButton, out bool aPressed) && aPressed)
{
Debug.Log("右手柄 A 键按下");
}
// 左手柄 X 键按下
if (leftController.TryGetFeatureValue(CommonUsages.secondaryButton, out bool xPressed) && xPressed)
{
Debug.Log("左手柄 X 键按下");
}
// 扳机键(0~1 数值)
if (rightController.TryGetFeatureValue(CommonUsages.trigger, out float triggerValue))
{
Debug.Log("右扳机值:" + triggerValue);
}
// 握把键
if (leftController.TryGetFeatureValue(CommonUsages.grip, out float gripValue))
{
Debug.Log("左握把值:" + gripValue);
}
- 摇杆值获取(左右摇杆 XY)
cs
// 左摇杆(移动用)
if (leftController.TryGetFeatureValue(CommonUsages.primary2DAxis, out Vector2 leftStick))
{
Debug.Log("左摇杆:" + leftStick);
// leftStick.x: 左右(-1~1),leftStick.y: 上下(-1~1)
}
// 右摇杆(视角用)
if (rightController.TryGetFeatureValue(CommonUsages.primary2DAxis, out Vector2 rightStick))
{
Debug.Log("右摇杆:" + rightStick);
}
// 摇杆按下
if (leftController.TryGetFeatureValue(CommonUsages.primary2DAxisClick, out bool leftStickPressed) && leftStickPressed)
{
Debug.Log("左摇杆按下");
}
三、3.4 专属 API(非 XR 标准,Pico 特有)
cs
using Unity.XR.PXR;
// 获取电池电量(0~1)
float leftBattery = PXRInput.GetBatteryPercent(XRNode.LeftHand);
float rightBattery = PXRInput.GetBatteryPercent(XRNode.RightHand);
// 震动反馈(手柄震动,时长单位:秒)
PXRInput.SendHapticImpulse(XRNode.RightHand, 0.5f, 0.1f);
四、最简测试脚本(3.4 直接能用)
cs
using UnityEngine;
using UnityEngine.XR;
using Unity.XR.PXR;
public class Pico34InputTest : MonoBehaviour
{
private InputDevice leftController;
private InputDevice rightController;
private InputDevice headDevice;
void Start()
{
// 获取设备
leftController = InputDevices.GetDeviceAtXRNode(XRNode.LeftHand);
rightController = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
headDevice = InputDevices.GetDeviceAtXRNode(XRNode.Head);
}
void Update()
{
// 头显数据
if (headDevice.TryGetFeatureValue(CommonUsages.devicePosition, out Vector3 headPos))
{
Debug.Log("头盔位置:" + headPos);
}
// 左摇杆
if (leftController.TryGetFeatureValue(CommonUsages.primary2DAxis, out Vector2 leftStick))
{
Debug.Log("左摇杆:" + leftStick);
}
// 右扳机
if (rightController.TryGetFeatureValue(CommonUsages.trigger, out float trigger))
{
Debug.Log("右扳机值:" + trigger);
}
// A 键按下
if (rightController.TryGetFeatureValue(CommonUsages.primaryButton, out bool aPressed) && aPressed)
{
Debug.Log("A 键按下!");
// 震动反馈
PXRInput.SendHapticImpulse(XRNode.RightHand, 0.5f, 0.1f);
}
}
}
接下来是一些安全性的判断:
一、最基础:XR 设备是否激活(必须最先判断)
cs
using UnityEngine;
using UnityEngine.XR;
bool isXrActive = XRSettings.isDeviceActive;
Debug.Log("XR设备是否激活:" + isXrActive);
- true = 头盔已连接、XR 正常启动、可以读头显 / 手柄数据Unity
- false = 没插头盔、没开 XR、初始化失败 → 不要读任何手柄 / 头盔数据
二、判断「头盔(HMD)是否存在且有效」
cs
InputDevice head = InputDevices.GetDeviceAtXRNode(XRNode.Head);
bool headOk = head.isValid; // 是否存在且可用
更严谨一点:
cs
List<InputDevice> hmdList = new List<InputDevice>();
InputDevices.GetDevicesWithCharacteristics(InputDeviceCharacteristics.HeadMounted, hmdList);
bool hmdConnected = hmdList.Count > 0;
三、判断「头盔是否正在被追踪」(是否正常工作)
cs
bool isTracking = false;
if (headOk)
{
head.TryGetFeatureValue(CommonUsages.isTracked, out isTracking);
}
Debug.Log("头盔是否在追踪:" + isTracking);
摘下头盔、遮挡传感器、休眠时会变成 false
四、判断「用户是否戴着头盔」(非常实用)
cs
bool isWorn = false;
if (headOk)
{
head.TryGetFeatureValue(CommonUsages.userPresence, out isWorn);
}
Debug.Log("用户是否戴头盔:" + isWorn);
摘下头盔立刻 false ,戴上 true
五、手柄是否正常(左右手都可以)
cs
InputDevice left = InputDevices.GetDeviceAtXRNode(XRNode.LeftHand);
InputDevice right = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
bool leftOk = left.isValid;
bool rightOk = right.isValid;
六、「安全读取输入」的标准写法(直接用)
cs
using UnityEngine;
using UnityEngine.XR;
using Unity.XR.PXR;
public class PicoSafeInput : MonoBehaviour
{
InputDevice head, left, right;
void Start()
{
head = InputDevices.GetDeviceAtXRNode(XRNode.Head);
left = InputDevices.GetDeviceAtXRNode(XRNode.LeftHand);
right = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
}
void Update()
{
// 第一步:XR 是否激活
if (!XRSettings.isDeviceActive)
{
Debug.LogWarning("XR未激活,跳过输入读取");
return;
}
// 第二步:头盔是否有效
if (!head.isValid)
{
Debug.LogWarning("头盔无效");
return;
}
// 头盔位置(只有在追踪时才读)
if (head.TryGetFeatureValue(CommonUsages.isTracked, out bool trackOk) && trackOk)
{
if (head.TryGetFeatureValue(CommonUsages.devicePosition, out Vector3 pos))
{
// 正常使用 pos
}
}
// 右手柄按键
if (right.isValid)
{
if (right.TryGetFeatureValue(CommonUsages.primaryButton, out bool aPressed) && aPressed)
{
Debug.Log("A键按下");
}
}
}
}