PicoVR Unity Integration SDK 3.4 常用交互API

不知道是我没找对地方,还是官方那个把这个藏的严,又或者用了什么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(头盔 / 手柄 / 按键 / 摇杆)

  1. 头盔(头显)数据
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);
}
  1. 手柄(控制器)基础数据
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;
  1. 按键输入(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);
}
  1. 摇杆值获取(左右摇杆 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键按下");
            }
        }
    }
}
相关推荐
Python私教11 小时前
Godot图片怎么导入?PNG、压缩、Mipmap与Reimport一次讲清
游戏引擎·godot
寒水馨13 小时前
Linux下载、安装godot-4.7.1-stable(附安装包Godot_v4.7.1-stable_linux.x86_64.zip)
linux·游戏引擎·godot·游戏开发·2d游戏·3d游戏·godot engine
寒水馨16 小时前
macOS下载、安装godot-4.7.1-stable(附安装包Godot_v4.7.1-stable_macos.universal.zip)
macos·3d·游戏引擎·godot·跨平台·游戏开发·2d
chaoyuanl2 天前
超元力XR黑暗乘骑
科技·xr·vr·娱乐·mr
电子云与长程纠缠2 天前
UE中使用TGuardValue与TInlineComponentArray数据结构
开发语言·数据结构·学习·ue5·游戏引擎
玖玥拾2 天前
Unity 3D 笔记(十二)Unity/C# Socket 网络笔记1
网络·unity·c#
玖玥拾2 天前
Unity 3D 笔记(十五)Unity/C# Socket 网络笔记4
服务器·网络·unity·c#
xcLeigh3 天前
Unity基础:创建你的第一个游戏物体——Cube、Sphere与基本3D物体
游戏·3d·unity·教程
ellis19703 天前
C#异常相关关键字:Exceptions,throw,try,catch,finally
unity·c#
HH‘HH3 天前
Unity通过OPC UA工业协议连接工业设备实战指南
unity·游戏引擎