求助:使用SharpDX在C#中无法检测PlayStation控制器
解决SharpDX DirectInput无法检测PlayStation控制器的问题
问题根源
DirectInput对现代PlayStation控制器(如DualShock4)的兼容性有限:
- DS4Windows默认会将DualShock4模拟为Xbox风格的XInput设备,而DirectInput对这类模拟设备的识别逻辑与原生Gamepad不同
- 原代码仅枚举
DeviceType.Gamepad类型,部分控制器会被系统识别为Joystick而非Gamepad
修复DirectInput检测问题的步骤
1. 调整设备枚举逻辑
修改枚举参数,覆盖所有已连接的控制器类型,并只保留当前连接的设备:
var directInput = new DirectInput(); // 枚举所有已连接的控制器(包含Joystick、Gamepad等类型) var devices = directInput.GetDevices(DeviceType.All, DeviceEnumerationFlags.AttachedOnly); // 先判断是否检测到设备,避免索引越界 if (devices.Count == 0) { MessageBox.Show("未检测到任何控制器"); return; } foreach (var deviceInstance in devices) { MessageBox.Show($"检测到设备: {deviceInstance.InstanceName}"); }
2. 完善设备初始化逻辑
获取设备后,需要启用所有可用的轴和按钮,确保输入能被正常读取:
var joystick = new Joystick(directInput, devices[0].InstanceGuid); // 配置所有轴的范围 foreach (var deviceObject in joystick.GetObjects()) { if ((deviceObject.ObjectType & ObjectDeviceType.Axis) != 0) { joystick.GetObjectPropertiesById((int)deviceObject.ObjectType).SetRange(-1000, 1000); } } joystick.Acquire();
3. 优化输入读取循环
添加延迟避免CPU占用过高,同时处理空输入数据的情况:
while (true) { joystick.Poll(); var data = joystick.GetBufferedData(); if (data.Count > 0) { foreach (var state in data) { MessageBox.Show($"输入值: {state.Value}"); } } System.Threading.Thread.Sleep(16); // 约60帧间隔 }
更优替代方案
如果DirectInput方案仍有问题,推荐以下两种更适配PlayStation控制器的方案:
方案1:使用XInput(推荐)
Windows原生XInput对模拟为Xbox设备的DualShock4支持更好,API更简洁,同时支持震动输出:
using SharpDX.XInput; // 检测第一个控制器(支持UserIndex.One到Four) var controller = new Controller(UserIndex.One); if (!controller.IsConnected) { MessageBox.Show("控制器未连接"); return; } while (true) { var state = controller.GetState(); // 读取左摇杆X轴值(范围-32768到32767) int leftThumbX = state.Gamepad.LeftThumbX; // 检测Cross键(对应Xbox的A键) bool crossPressed = (state.Gamepad.Buttons & GamepadButtonFlags.A) != 0; // 设置震动:左马达低频震动,右马达高频震动 var vibration = new Vibration { LeftMotorSpeed = 0x4000, RightMotorSpeed = 0x8000 }; controller.SetVibration(vibration); System.Threading.Thread.Sleep(16); }
方案2:直接访问HID设备(支持DS4专属功能)
如果需要触控板、灯条等DS4专属功能,可以通过HID协议直接访问设备,使用SharpDX.Hid库实现:
using SharpDX.Hid; // 枚举所有HID设备,筛选DS4的硬件ID var devices = HidDevice.GetDevices(); var ds4Device = devices.FirstOrDefault(d => d.ProductId == 0x09CC && d.VendorId == 0x054C); if (ds4Device == null) { MessageBox.Show("未检测到DualShock4设备"); return; } using (var device = new HidDevice(ds4Device)) { // 读取输入报告 byte[] inputBuffer = new byte[64]; while (true) { int bytesRead = device.ReadInput(inputBuffer, 0, inputBuffer.Length); if (bytesRead > 0) { // 解析DS4输入数据,比如左摇杆X轴在inputBuffer[1]和inputBuffer[2] int leftX = (inputBuffer[1] | (inputBuffer[2] << 8)) - 0x8000; MessageBox.Show($"左摇杆X轴: {leftX}"); } System.Threading.Thread.Sleep(16); } }
内容的提问来源于stack exchange,提问作者user23066555
相关产品推荐
相关产品推荐

