⠀⠀⠀⠀⠀⠀⢸⡆⠀⣇⠀⣷⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⠀⠀⠀⠀⠀⠀⠀⢻⣧⣄⠀⠀⠀⠀⠀⠀⠀⢠⣼⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣧⡀⠀⠀⠀⠀⠀⠀⠀⢰⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⢠⣼⠀⢸⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⢸⣇⡀⣿⡆⠘⢻⣧⡄⠀⠀⠀⠀⠀⠀⠀⢸⡏⠀⠀⠀⠀⠀⠀⠀⠈⠹⢿⣧⡄⠀⠀⠀⠀⢠⣼⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢻⣧⡄⠀⠀⠀⠀⠀⢰⡿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⡇⠀⢠⣼⡏⠀⣸⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠘⢻⡇⢸⡇⠀⠘⢻⣷⡄⠀⠀⠀⠀⠀⠀⢸⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣿⣦⡀⠀⢠⣾⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢻⣧⡄⠀⠀⠀⢸⡿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣧⢀⣼⡏⠁⢰⣿⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢸⣧⣼⡇⠀⠀⠀⠹⢿⣆⡀⠀⠀⠀⢀⣼⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢻⣷⣤⣾⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢻⣧⡄⠀⣸⡿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢻⣸⡟⠃⠀⢸⡇⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣿⣧⠀⠀⠀⠀⠘⢻⣧⡄⠀⠀⢸⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣤⣴⣿⣿⣿⣿⣿⣿⣿⣷⣶⣶⣶⣦⣤⣤⣤⣤⣤⣤⣤⣤⣈⣹⣧⣸⣟⣣⣤⣤⣤⣤⣤⣤⣴⣶⣶⣾⣿⣿⣿⣿⣿⡇⠀⠀⢸⡇⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢿⣿⠀⠀⠀⠀⠀⠈⢻⣷⡆⠀⢸⡇⠀⠀⠀⠀⢀⣠⣤⣴⣶⣿⣿⡿⠟⠛⠋⢹⣧⡈⠉⠉⠉⠙⠛⠛⠛⠛⠛⠛⠛⠻⠿⠿⠿⠿⣿⣿⣿⣿⣿⡿⠿⠿⠿⠟⠛⠛⠛⠛⠛⠋⠉⢩⣽⡟⠸⢿⡆⢠⣾⡇⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⠀⠀⠀⠸⢿⣧⣸⣇⣠⣤⣴⣾⣿⣿⠿⠛⠛⠋⠁⠀⠀⠀⠀⠈⢻⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣼⡿⠋⢹⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣼⡟⠁⠀⠸⢿⣾⡟⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢻⣀⣠⣤⣤⣤⣤⣤⣤⣾⣿⣿⣿⣿⡟⠛⠋⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣰⣾⡟⠋⠁⠀⠘⢻⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣾⠏⠀⠀⠀⠀⣸⣿⡇⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⡿⠿⠟⠛⠛⠛⠛⠛⢻⣿⢿⣿⣧⣤⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢻⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣾⡟⠋⠁⠀⠀⠀⠀⠸⣷⡄⠀⠀⠀⠀⠀⠀⢀⣸⡿⠃⠀⠀⢠⣴⣾⣿⠟⠃⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠻⢿⣧⣄⠀⠀⠀⠀⠀⠘⢻⡇⠘⠛⠻⢿⣷⣦⣤⡄⠀⠀⠀⠀⠀⠀⠀⠀⢸⣧⡀⠀⠀⠀⠀⠀⠀⢠⣴⣾⡟⠋⠀⠀⠀⠀⠀⠀⠀⠀⢸⣧⡀⠀⠀⠀⠀⢠⣼⡟⠃⢀⣠⣼⣿⡿⠟⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠹⢿⣧⣄⡀⠀⠀⠀⢸⣷⡄⠀⠀⠀⠙⠛⠻⣿⣷⣦⣤⡀⠀⠀⠀⠀⠈⢻⡇⠀⠀⠀⠀⢠⣴⣾⡟⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢻⡇⠀⠀⠀⢠⣼⡟⢡⣴⣾⣿⡿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⢻⣷⣄⡀⠀⠀⢸⣧⡀⠀⠀⠀⠀⠀⠈⠙⠛⢻⣿⣷⣦⣄⡀⠀⢸⣧⠀⠀⢠⣼⣿⡟⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢿⡆⠀⢰⣾⣯⣼⣿⣿⡿⠏⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⢻⣷⣦⡀⠘⢻⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠻⢿⣿⣷⣮⣿⣠⣼⣿⡟⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣧⣸⣿⣿⣿⣿⡿⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢻⣷⣦⡜⢿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣤⣬⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢻⣿⣾⣧⠀⠀⢀⣠⣤⣤⣴⣾⣿⣿⡿⠿⠟⠛⠋⠉⠸⣷⡆⠈⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⢉⣩⣽⣿⣿⡟⣻⣿⣿⡟⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠻⣿⣾⣿⣿⣿⣿⣟⡛⠛⠉⠁⠀⠀⠀⠀⠀⠀⠀⠸⢿⣆⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣾⣿⣿⣿⣯⣥⣼⣿⡟⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠛⠛⠻⠿⢿⣿⣿⣿⣷⣶⣦⣤⣤⣤⣄⡀⠀⠀⠘⢿⣇⡀⠀⢀⣠⣤⣼⣿⣿⣿⣿⣿⣿⡿⠿⠟⠛⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠙⠛⠛⠻⠿⢿⣿⣿⣿⣷⣶⣾⣿⣧⣴⣿⣿⣿⣿⡿⠟⠛⠛⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠙⠛⠛⠛⠿⠛⠛⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
Gamepad support for Bevy on macOS through Apple's Game Controller framework.
Use it if your controller shows up as connected in Bevy on macOS but nothing happens when you press buttons or move the sticks (typical with Xbox controllers on macOS 14+):
INFO bevy_input::gamepad: Gamepad 450v0 connected.
WARN gilrs::gamepad: No mapping found for UUID 03000000-5e04-0000-ea02-000014050000
- Bevy reads gamepads with gilrs, which on macOS uses the low-level IOKit HID API.
- Since macOS 14, controllers handled by Apple's Game Controller framework (e.g. Xbox controllers) don't deliver input through IOKit. gilrs sees the device connect, but never receives events (see gilrs issues #148 and #150).
- Apple provides a compatibility layer ("Increase controller compatibility" in
System Settings → Game Controllers, per app) that exposes a synthetic Xbox 360 HID device
(Apple docs),
but gilrs 0.11 / gilrs-core 0.6.8 skips it: the synthetic device has no LocationID(Failed to get location id of device … Skipping).
This crate reads controllers with the Game Controller framework (the API Apple recommends, and the
one browsers use, which is why the web gamepad viewer
works while the native one doesn't) and feeds them into Bevy's standard gamepad pipeline: it
writes the same raw events bevy_gilrs writes. So everything else works unchanged: the Gamepad
component, GamepadSettings dead zones, pressed / just_pressed, left_stick(), etc.
No app bundle and no system setting is needed.
[dependencies]
bevy = "0.20"
bevy_apple_gamepad = { path = "crates/bevy_apple_gamepad" } # or git / crates.io once publisheduse bevy::prelude::*;
use bevy_apple_gamepad::AppleGamepadPlugin;
fn main() {
let mut app = App::new();
// On macOS, replace gilrs (otherwise you get a second gamepad that never moves).
#[cfg(target_os = "macos")]
app.add_plugins(DefaultPlugins.build().disable::<bevy::gilrs::GilrsPlugin>());
#[cfg(not(target_os = "macos"))]
app.add_plugins(DefaultPlugins);
// No-op on other platforms, so it's safe to add unconditionally.
app.add_plugins(AppleGamepadPlugin::default());
app.run();
}Then read gamepads the usual Bevy way:
fn read_gamepads(gamepads: Query<&Gamepad>) {
for gamepad in &gamepads {
let movement = gamepad.left_stick();
if gamepad.just_pressed(GamepadButton::South) {
// jump!
}
}
}AppleGamepadPlugin {
// macOS only delivers controller input to the focused app; set this to keep reading it
// while the window is in the background.
monitor_background_events: true,
}Bevy names buttons by position. With Xbox labels:
Tested with an Xbox controller over USB on macOS 15 (Sequoia). Any controller the framework exposes with the standard "extended gamepad" layout (PlayStation, Switch Pro, MFi…) should work the same way, mapped by position, but hasn't been tested yet: reports welcome.
One system runs every frame in PreUpdate (before InputSystems, like bevy_gilrs) on the main
thread (NonSendMarker):
- Reads GCController.controllers().
- New controllers → spawns an entity and writes GamepadConnectionEvent::Connected.
- For each button / axis whose value changed → writes RawGamepadButtonChangedEvent/RawGamepadAxisChangedEvent(also wrapped inRawGamepadEvent).
- Controllers that disappeared → GamepadConnectionEvent::Disconnected.
Bevy's own gamepad_event_processing_system turns those into the Gamepad component.
- macOS only (other Apple platforms aren't wired up yet).
- No rumble / haptics, battery, lights, touchpad or motion sensors yet.
- vendor_id/- product_idare- None(the framework doesn't expose them).
- Only controllers with the extended gamepad profile are reported.
Dual-licensed under MIT or Apache-2.0, at your option (same as Bevy).