Unity XR自定义脚本无法识别Oculus Touch控制器如何解决
问题现象
- 开发场景:基于Oculus Quest设备、Oculus Touch控制器开发手部交互功能
- 正常表现:XR Interaction Debugger可正常识别控制器设备,XR Interaction Toolkit自带的XR Direct Interactor组件运行正常
- 异常表现:自行编写的自定义设备检测脚本无法识别Touch控制器
测试脚本代码
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.XR; public class HandController : MonoBehaviour { List<InputDevice> devices = new List<InputDevice>(); void Start() { InputDevices.GetDevices(devices); foreach (var item in devices) { Debug.Log(item.name + item.characteristics); } } void Update() { foreach(var item in devices) { Debug.Log(item.name + item.characteristics); } } }
问题原因
脚本存在两个核心逻辑问题:
- 设备枚举时机错误:
Start()生命周期执行时,XR SDK尚未完成设备初始化,Touch控制器还没完成注册,此时调用InputDevices.GetDevices()只能拿到已加载的少量设备(多数情况下仅能识别到头显,甚至头显都未完成加载),无法枚举到后初始化的控制器。 - 设备列表未动态更新:脚本仅在
Start()阶段拉取一次设备列表,后续控制器连接、重连、系统设备列表变更时,本地缓存的devices列表不会同步更新,就算后续控制器完成初始化,脚本也读不到新设备。
*补充:XR Interaction Toolkit底层是监听了InputDevices.deviceConnected/InputDevices.deviceDisconnected事件动态维护设备列表,所以不受初始化时机影响,可以正常识别控制器。
修复方案
- 监听XR设备的连接/断开事件,动态更新本地设备列表,不要只在启动时拉取一次
- 不要在初始化阶段直接拉取全量设备,注册事件监听后自动同步全量已接入设备
- 可按需通过设备特征过滤目标设备,避免无关设备干扰逻辑
修复后的参考代码:
using System.Collections.Generic; using UnityEngine; using UnityEngine.XR; public class HandController : MonoBehaviour { List<InputDevice> devices = new List<InputDevice>(); void OnEnable() { // 监听设备连接/断开事件 InputDevices.deviceConnected += OnDeviceConnected; InputDevices.deviceDisconnected += OnDeviceDisconnected; // 首次拉取已连接设备 RefreshDeviceList(); } void OnDisable() { // 移除事件监听,避免内存泄漏 InputDevices.deviceConnected -= OnDeviceConnected; InputDevices.deviceDisconnected -= OnDeviceDisconnected; } void RefreshDeviceList() { devices.Clear(); // 过滤特征:手持控制器类设备,可按需追加左右手柄、追踪器等筛选条件 InputDevices.GetDevicesWithCharacteristics(InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.HeldInHand, devices); foreach (var item in devices) { Debug.Log($"已识别设备:{item.name},特征:{item.characteristics}"); } } void OnDeviceConnected(InputDevice device) { Debug.Log($"新设备接入:{device.name},特征:{device.characteristics}"); RefreshDeviceList(); } void OnDeviceDisconnected(InputDevice device) { Debug.Log($"设备断开:{device.name}"); RefreshDeviceList(); } void Update() { // 后续输入读取逻辑直接遍历devices列表即可 } }
参考材料
- 脚本运行控制台输出截图
- XR Interaction Debugger运行界面截图
内容的提问来源于stack exchange,提问作者irlam
相关产品推荐
相关产品推荐

