Add plugin skeleton with versioned skill directories, TODO SKILL.md scaffolds with goals for skill-creator, and copy over bevy-skill-research reports from spacecraft into docs/workpad/research/.
3.4 KiB
Bevy Skill Research: Input System
Bevy version: 0.18, with 0.19 notes
Date: 2026-07-07
Keyboard Input (Res<ButtonInput<KeyCode>>)
| Method | Returns | Purpose |
|---|---|---|
pressed(KeyCode) |
bool |
Held this frame |
just_pressed(KeyCode) |
bool |
First frame pressed |
just_released(KeyCode) |
bool |
First frame released |
any_pressed(impl IntoIterator) |
bool |
Any of these held |
any_just_pressed(...) |
bool |
Any of these just pressed |
all_pressed(...) |
bool |
All of these held |
get_pressed() |
impl Iterator |
Iterate all held keys |
get_just_pressed() |
impl Iterator |
Iterate newly pressed |
clear_just_pressed(KeyCode) |
bool |
Consume the event |
Also available: ButtonInput<Key> for logical/locale-aware keys.
Updated by keyboard_input_system from KeyboardInput events.
Mouse Input
Buttons: Res<ButtonInput<MouseButton>> — same API as keyboard.
Variants: Left, Right, Middle, Back, Forward, Other(u16).
Motion:
| Type | Kind | Purpose |
|---|---|---|
MouseMotion |
Event | delta: Vec2 per raw motion event |
AccumulatedMouseMotion |
Resource | Total delta this frame, reset each frame |
MouseWheel |
Event | Scroll with MouseScrollUnit (Line/Pixel) |
AccumulatedMouseScroll |
Resource | Total scroll this frame |
Cursor position: Read from Window component:
fn cursor(windows: Query<&Window>) {
if let Ok(window) = windows.single() {
if let Some(pos) = window.cursor_position() {
// pos is Vec2 in logical pixels, origin top-left
}
}
}
Gamepad Input
Buttons: Res<ButtonInput<GamepadButton>> — same pressed/just_pressed API.
Axes: Res<Axis<GamepadAxis>>:
get(GamepadAxis) -> Option<f32>— range[-1.0, 1.0]GamepadButtonmapped range[0.0, 1.0](triggers are analog)
Events: GamepadButtonStateChangedEvent, GamepadButtonChangedEvent, GamepadAxisChangedEvent, GamepadConnectionEvent.
Settings: GamepadSettings component for deadzone/threshold configuration.
Touch Input
TouchInput(Event) — touch event withTouchPhase(Began/Moved/Ended)Touches(Resource) — query active touches, analogous to ButtonInput patternForceTouch— pressure-sensitive data on supported devices- Requires
touchfeature flag in 0.18
Action Mapping
No built-in action mapping system in Bevy 0.18. Community crate leafwing-input-manager fills this role.
0.18 Change
Input sources (mouse, keyboard, gamepad, touch, gestures) are now feature-gated. Enabled by default with bevy_window/bevy_gilrs, but must be explicit with default-features = false.
Common Patterns
fn movement(
keys: Res<ButtonInput<KeyCode>>,
mouse: Res<ButtonInput<MouseButton>>,
) {
if keys.just_pressed(KeyCode::Space) { /* fire */ }
if mouse.pressed(MouseButton::Left) { /* hold fire */ }
let mut dir = Vec3::ZERO;
if keys.pressed(KeyCode::KeyW) { dir.z -= 1.0; }
if keys.pressed(KeyCode::KeyS) { dir.z += 1.0; }
if keys.pressed(KeyCode::KeyA) { dir.x -= 1.0; }
if keys.pressed(KeyCode::KeyD) { dir.x += 1.0; }
}
fn read_motion(mut motion: MessageReader<MouseMotion>) {
for ev in motion.read() {
// ev.delta.x, ev.delta.y
}
}
Note: MouseMotion uses MessageReader (not EventReader) in 0.18+.