bevyengine/bevy
Input
How keyboard, mouse, touch, and gamepad data flow from the OS to your systems.
Path overview
graph LR
OS -->|events| W[bevy_winit]
OS -->|gamepads| G[bevy_gilrs]
W -->|KeyboardInput, MouseButtonInput, MouseMotion, MouseWheel, TouchInput| Events
G -->|GamepadConnection, GamepadButton, GamepadAxis| Events
Events --> P[bevy_input::ButtonInput / Axis update]
P --> User[User systems]
Events --> Focus[bevy_input_focus]
Focus --> User
Events --> Picking[bevy_picking]
Picking --> UserThe data crate is bevy_input. Backends are bevy_winit (windowing/keyboard/mouse/touch) and bevy_gilrs (gamepads).
Reading input
Two patterns:
Per-frame state
fn move_player(
keys: Res<ButtonInput<KeyCode>>,
mouse: Res<ButtonInput<MouseButton>>,
) {
if keys.pressed(KeyCode::KeyW) { /* … */ }
if keys.just_pressed(KeyCode::Space) { /* … */ }
if mouse.just_released(MouseButton::Left) { /* … */ }
}ButtonInput<T> is updated each frame by bevy_input from the raw events. pressed, just_pressed, just_released are the canonical API.
Raw events
fn on_keystrokes(mut events: EventReader<KeyboardInput>) {
for event in events.read() { /* … */ }
}Use raw events when you need character data (text input), repeat-rate handling, or precise temporal ordering. The KeyboardInput event carries both KeyCode (physical key, position-independent) and Key (logical key, layout-dependent).
Mouse
Res<ButtonInput<MouseButton>>for buttons.EventReader<MouseMotion>for relative motion (delta).EventReader<MouseWheel>for scroll deltas.Window::cursor_position()for absolute position within a window.
Touch
Res<Touches> collates active touches keyed by ID. EventReader<TouchInput> gets per-event detail (start, move, end, cancel).
Gamepads
Gamepads are entities, not resources. When bevy_gilrs detects a connection, it spawns a Gamepad entity with GamepadInfo and per-button/axis components.
fn read_pads(
pads: Query<(&Gamepad, &GamepadInfo)>,
buttons: Query<&ButtonInput<GamepadButton>>,
) {
for (pad, info) in &pads {
let pressed = buttons.get(pad.entity).unwrap().pressed(GamepadButton::South);
// …
}
}This entity-based design supports multiple controllers natively — each pad is a different entity.
Focus
bevy_input_focus decides which entity receives keyboard input. UI widgets register Observer<KeyboardInput> on themselves; the dispatch system bubbles events up the focus chain. See UI for the widget angle.
Picking
bevy_picking translates pointer position + camera into entity hits and dispatches Pointer<Click> / Pointer<Drag> / Pointer<Hover> events. See Picking.
Common pitfalls
KeyCodevsKey— useKeyCodefor "the W key" semantics (physical layout-independent) andKeyfor "the character was 'a'" (layout-aware text input).mouse.just_pressedreturns nothing — check that noRunConditionis filtering the system out and thatbevy_input::InputPluginis in your plugin chain.- Multiple gamepads but only one responding — your code is reading from
Gamepad::new(0)instead of querying allGamepadentities. - Text input lossy — you're reading
KeyCode. UseKeyboardInput::logical_key(which isKey) for text.
See also
bevy_input— events and resources.bevy_winit,bevy_gilrs— backends.bevy_input_focus,bevy_picking.- UI, Picking.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.