godot: Vibration doesn't work for some controllers


Bugsquad note: This issue has been confirmed several times already. No need to confirm it further.


Operating system or device, Godot version, GPU Model and driver (if graphics related): 1c0007b commit from master branch, Linux Mint Mate 18.2 x86_64 Issue description: (for example) Input.start_joy_vibration(0, 0.5, 1, 5) don’t do anything. Tested with connected PS, XBox and Steam Constrollers.

Bugsquad edit (keywords for easier searching): vibrate, gamepad, joystick

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 5
  • Comments: 37 (27 by maintainers)

Commits related to this issue

Most upvoted comments

Works for me on Windows 10, with an Xbox 360 controller. Might be Linux only.

Given I haven’t gotten much feedback on my comment above, I’ll plan on proceeding with the proposed option 1, Use the MacOS GameController system framework for getting MacOS vibration working. After sitting with this and learning more Godot over the past month, I think it’s a good long-term solution.

Once that’s done, I’d like to explore vibration on iOS, Android, Chrome web, and DualShock 4 on Windows after that. Help/support with DS4 on Windows would be welcome, as it’s quite a different implementation than what exists.

Just to set expectations, it may be a few weeks/months before I have time to do this. But it’s on my radar and important to me as I develop primarily on MacOS and want to add and test rumble in my games.

macOS Monterey 12.1, Macbook Pro M1 Max, Xbox One Controller over Bluetooth, Godot 3.4.2. Input.start_joy_vibration does not work. Same as the commenter above, vibration works when tested via gamepad-tester.com.

I’ve been digging into the Godot MacOS joypad vibration code and have some options for the path forward. Feedback and guidance would be much appreciated!

Current Godot MacOS Joypad Vibration Implementation

Right now the Godot Joypad implementation on MacOS uses Apple’s ForceFeedback API. See the headers and vibration code. The ForceFeedback API has been supported in MacOS since 10.2, released back in 2003. It’s not clear to me what devices this rumbles, but we do know it doesn’t work for modern game controllers.

Godot also uses the MacOS IOKit API for interfacing with joypads.

MacOS Controller Paths Forward

Here are the options I see:

  1. Use the MacOS GameController system framework — this is Apple’s robust controller API for interacting with modern controllers in all sorts of ways, including vibration/haptics. This is what Godot’s iOS Joypad implementation uses.
    • Compatibility: iOS 7.0+, iPadOS 7.0+, macOS 10.9+, Mac Catalyst 13.0+, tvOS 9.0+
    • Would be implemented in Obj-C++, like iOS Joypad
    • Pros:
      • Will work with Xbox One, PS4, etc. controllers.
      • System API
      • Similar and/or shared implementation with Godot’s iOS Joypad
      • It will be straightforward to get vibration working on iOS as a follow up
    • Cons:
      • Would require a re-implementation of the current MacOS joypad implementation, can’t just add in a rumble support.
      • Might mean dropping support for MacOS joypad support for prior operating systems prior to macOS 10.9 (2013 release), unless there’s a desire to maintain the current joypad implementation for those older operating system versions.
  2. Use the HIDAPI library — HIDAPI is a liberally licensed Human Interface Device (HID) library for interfacing with a variety of controllers. This is used by SDL, and it seems to work quite well for wide compatibility.
    • Pros:
      • Mature, stable library that’s been widely used
      • Could help enable more than XInput rumble on Windows?
    • Cons:
      • Pulling in an entire library. Would Godot just use it for MacOS or for everything?
      • Requires a re-implementation without any reference within Godot

My Thoughts

I am honestly not sure… HIDAPI seems like it could unlock DualShock 4 rumble on Windows but would require a lot of work. More than I am likely capable of taking on. Going with the Apple GameController framework seems approachable because of Godot’s iOS joypad implementation I can reference. It’s also appealing to use a system API that can be shared across Apple platforms.

Next Steps

I’m not an expert in this domain. I’m just a person who wants my controller to rumble and am willing to do the work to help make that happen. 😂 I may be missing an option for a path forward.

Are any contributors/maintainers able to give me some guidance on how to proceed with this work or conversation? The scope of the decision seems too big for me to just make and start hacking away at the implementation without guidance/feedback.

Note that–on Windows–vibration relies on the XInput API which the official docs describe as “allows applications to receive input from the Xbox Controller for Windows”–i.e. at least officially, it’s not a generic controller API.

I notice that SDL haptic support includes XInput & DirectX Input support on Windows, so adding additional controller support via DirectX may be possible.

Related issue: https://github.com/godotengine/godot/issues/30256

Related links:

For macOS, this is already fixed in the master branch~

Might mean dropping support for MacOS joypad support for prior operating systems prior to macOS 10.9 (2013 release), unless there’s a desire to maintain the current joypad implementation for those older operating system versions.

Godot 4 requires macOS 10.12 or later, so that’s fine.

I’ve continued my research and testing to better understand what’s possible and what is and isn’t working. Here are some more findings:

  • Windows:
    • XInput rumbles without issue in Godot on Windows.
    • DualShock 4 does not, as others have reported. SDL2 does with a special hint. So it should be possible to add to Godot. DS4Windows and Steam Input seem like potentially viable alternatives for immediate needs. I tested Steam Input with DS4 and confirmed rumbles work in a Godot game. A lot of people have DS4 controllers so I want to dig into this working on Windows without a need for Steam or DS4Windows.
  • MacOS:
    • Steam Input has no effect on rumble on XInput or DS4 in a Godot game running through it from my testing. But Steam can rumble everything when identifying controllers. Steam certainly has some advanced rumble integration from what I can tell. I wonder if any of it is open source…
    • Edit: DS4 does work in SDL2 on MacOS when using the SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1"); hint, so that’s promising!
  • Linux:
    • Did more testing and XInput, Switch, and DualShock 4 are all rumbling for me without issue on Ubuntu 22.04. Yay.
    • My Steam Deck appears to be having issues with all haptics and rumble, so I am going to try to fix that and then will do more Godot rumble testing on the Deck. Connected DS4, XInput, and Switch controllers rumble fine.
  • Web
    • Only Chrome (and thus Edge) supports rumble from testing on Mac, Linux, and Windows via the JS console. The API is pretty simple.
    • Firefox has an API for this but it didn’t work on any OS from my testing. Maybe one day in the future.
    • Godot web exports don’t rumble in Chrome. Seems possible though. It’s not a stable, standard API, so maybe risky to add? Would like to experiment with this more.

In summary: rumble for XInput on MacOS and DualShock 4 on Windows are my highest priorities.

Need to test Deck, iOS, and Android more. Chrome web may be possible. It’s unclear how possible DS4 on MacOS will be, needs more experimentation. I don’t have a Dual Sense controller yet, but I’d like to eventually test and support that too.

A lot of what I’ve shared is just confirming the issues reported above, but it helps me to test the issues and have a couple control groups to test against like the SDL tester and a Unity game I know rumbles. I have a pretty good grasp on what’s possible and what to do next. Will try to report back in the coming days and hopefully have a PR.

At least for Windows, controllers need to be emulated as an XInput device. I tested with my DualShock 4 controller on Windows 10 and it didn’t work, however when I used DS4Windows, which turns your DS4 into an emulated Xbox controller, it did work.

DS4Windows seems to use the ViGEmBus driver for it’s emulation, perhaps that could be a place to look.

The controllers are successfully connected, the control works without unnecessary movements. Vibration works on Steam, but not in Godot.

Hi, I just noticed that vibration doesn’t work for controllers in macOS a few days ago, so I tried to fix it. I would appreciate if someone interested could test it.

And thanks to @brettchalupa for the initial guide on how controllers work in Godot and how this issue could be addressed.

Let me know if I’m being too noisy here, but I thought I’d share some findings from the world of macOS rumble.

I tested some Unity games that I know have rumble support and none of them worked on macOS. So I dug into Apple’s haptics API and can confirm it rumbles DS4 and XInput controllers with this sample game they provided. So at the very baseline, we know that with Swift and Apple’s SDK, you can rumble a DS4 and Xbox One controller on macOS 12.6.

Then I thought, okay, let’s see if SDL2 can rumble controllers on macOS. I wrote a little SDL2 CLI tester and tested some controllers. The controllers using XInput rumbled, awesome! And a controller that emulates Switch Pro Controller rumbled too, just a bit weakly. DS4/MFi and DirectInput controllers didn’t rumble though, and SDL reports them as not supporting rumble.

So what does this mean? Well, it should at least be possible to get XInput controllers rumbling on macOS in Godot by referencing SDL’s implementation. That’s my initial goal, that way XInput controllers work on macOS, Windows, and Linux.

From there, outstanding questions are:

  • How do we get DS4 (and maybe Dual Sense?) controllers working with rumble (and maybe the triggers too)? This seems like an interesting resource: https://github.com/JibbSmart/JoyShockLibrary
  • Test on controller rumble on mobile
  • Further explore different controller APIs and rumble support for all of them on as many platforms as possible (Switch Pro Controllers, DirectInput, etc.)

But I think XInput on modern macOS probably seems like a fine starting place for now for making this a bit better.

All right, time to dig into the Godot source. 😸

On Windows, you’ll find only XInput to be working. All other controllers need directinput that is not implemented. Switch Pro controllers only work using Steam Input when connected via cable. Bluetooth seems to be working though. I dunno what they do to make that work (Windows only reads information spam). SDL has some info how to trigger vibrations on DualShock and DualSense as well as an example how to use the adaptive triggers. Maybe you’ll find some pointers there.

Is this issue up for grabs still? I’m interested in taking on trying to fix it. I’ve got a PS4 controller, Switch controller, and an Xbox One controller with access to Linux, macOS, and Windows. I’d be happy to dig into this and get it as cross-platform and cross-controller as possible.

@coelhucas There is already PR, I was able to test my Bluetooth XBox controller on Macos. https://github.com/godotengine/godot/pull/80709

that should be fine, provided you can keep compatibility with the existing gamepad mappings

@brettchalupa It’s up for grabs. I don’t think anyone else is working on this.

Vibration is not working for me using Xbox Series X controller, on macOS Big Sur over bluetooth. The vibration works using this website https://gamepad-tester.com/ but not in Godot (3.3.2 stable)

We need more information on what exact controller models and setup do not work, as so far nobody could reproduce those issues.