A straightforward stateful input manager for the Bevy game engine.
Rust
971
586 commits
updated Oct 15, 2026
A straightforward but robust input-action manager for Bevy.
Inputs from various input sources (keyboard, mouse and gamepad) are collected into a common ActionState on your player entity,
which can be conveniently used in your game logic.
The mapping between inputs and actions is many-to-many, and easily configured and extended with the InputMap components on each player entity.
A single action can be triggered by multiple inputs (or set directly by UI elements or gameplay logic),
and a single input can result in multiple actions being triggered, which can be handled contextually.
| Bevy | leafwing-input-manager |
|---|---|
| 0.20 | 0.22 |
| 0.19 | 0.21 |
| 0.18 | 0.20 |
| 0.17 | 0.18..0.19 |
| 0.16 | 0.17 |
| 0.15 | 0.16 |
| 0.14 | 0.14..0.15 |
| 0.13 | 0.13 |
| 0.12 | 0.11..0.12 |
| 0.11 | 0.10 |
| 0.10 | 0.9 |
| 0.9 | 0.7..0.8 |
InputMap component
Keybindings<KeyCode>, Keybindings<Gamepad> headachesActionState component
input_map.insert(Action::Jump, KeyCode::Space) and input_map.insert(Action::Jump, GamepadButton::South)? Have both!input_map.insert(Action::Console, ButtonlikeChord::new([KeyCode::ControlLeft, KeyCode::Shift, KeyCode::KeyC]))ClashStrategy enum: stop triggering individual buttons when you meant to press a chord!ActionDiff representation to send on the wire#![forbid(missing_docs)]Gamepads resource and use InputMap::set_gamepad.leafwing-input-manager to your Cargo.toml.Actionlike trait for it.InputManagerPlugin to your App.InputMap<A: Actionlike> component to your player entity (or entities!).InputMap component on your player entity.ActionState component on your player entity to check the collected input state!use bevy::prelude::*;
use leafwing_input_manager::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
// This plugin maps inputs to an input-type agnostic action-state
// We need to provide it with an enum which stores the possible actions a player could take
.add_plugins(InputManagerPlugin::<Action>::default())
// The InputMap and ActionState components will be added to any entity with the Player component
.add_systems(Startup, spawn_player)
// Read the ActionState in your systems using queries!
.add_systems(Update, jump)
.run();
}
// This is the list of "things in the game I want to be able to do based on input"
#[derive(Actionlike, PartialEq, Eq, Hash, Clone, Copy, Debug, Reflect)]
enum Action {
Run,
Jump,
}
#[derive(Component)]
struct Player;
fn spawn_player(mut commands: Commands) {
// Describes how to convert from player inputs into those actions
let input_map = InputMap::new([(Action::Jump, KeyCode::Space)]);
commands.spawn(input_map).insert(Player);
}
// Query for the `ActionState` component in your game logic systems!
fn jump(query: Query<&ActionState<Action>, With<Player>>) {
let action_state = query.single();
if let Ok(action_state) = action_state {
// Each action has a button-like state of its own that you can check
if action_state.just_pressed(&Action::Jump) {
println!("I'm jumping!");
}
}
}
This snippet is the minimal.rs example from the examples folder: check there for more in-depth learning materials!
Please refer to the [features] section in the Cargo.toml for information about the available crate features.
(top 24 of 25)
565 followers · starred Aug 2023
98 followers · starred Mar 2023
122 followers · starred Sep 2024
18 followers · starred Feb 2025
A straightforward stateful input manager for the Bevy game engine.
Rust
971
586 commits
updated Oct 15, 2026
A straightforward but robust input-action manager for Bevy.
Inputs from various input sources (keyboard, mouse and gamepad) are collected into a common ActionState on your player entity,
which can be conveniently used in your game logic.
The mapping between inputs and actions is many-to-many, and easily configured and extended with the InputMap components on each player entity.
A single action can be triggered by multiple inputs (or set directly by UI elements or gameplay logic),
and a single input can result in multiple actions being triggered, which can be handled contextually.
| Bevy | leafwing-input-manager |
|---|---|
| 0.20 | 0.22 |
| 0.19 | 0.21 |
| 0.18 | 0.20 |
| 0.17 | 0.18..0.19 |
| 0.16 | 0.17 |
| 0.15 | 0.16 |
| 0.14 | 0.14..0.15 |
| 0.13 | 0.13 |
| 0.12 | 0.11..0.12 |
| 0.11 | 0.10 |
| 0.10 | 0.9 |
| 0.9 | 0.7..0.8 |
InputMap component
Keybindings<KeyCode>, Keybindings<Gamepad> headachesActionState component
input_map.insert(Action::Jump, KeyCode::Space) and input_map.insert(Action::Jump, GamepadButton::South)? Have both!input_map.insert(Action::Console, ButtonlikeChord::new([KeyCode::ControlLeft, KeyCode::Shift, KeyCode::KeyC]))ClashStrategy enum: stop triggering individual buttons when you meant to press a chord!ActionDiff representation to send on the wire#![forbid(missing_docs)]Gamepads resource and use InputMap::set_gamepad.leafwing-input-manager to your Cargo.toml.Actionlike trait for it.InputManagerPlugin to your App.InputMap<A: Actionlike> component to your player entity (or entities!).InputMap component on your player entity.ActionState component on your player entity to check the collected input state!use bevy::prelude::*;
use leafwing_input_manager::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
// This plugin maps inputs to an input-type agnostic action-state
// We need to provide it with an enum which stores the possible actions a player could take
.add_plugins(InputManagerPlugin::<Action>::default())
// The InputMap and ActionState components will be added to any entity with the Player component
.add_systems(Startup, spawn_player)
// Read the ActionState in your systems using queries!
.add_systems(Update, jump)
.run();
}
// This is the list of "things in the game I want to be able to do based on input"
#[derive(Actionlike, PartialEq, Eq, Hash, Clone, Copy, Debug, Reflect)]
enum Action {
Run,
Jump,
}
#[derive(Component)]
struct Player;
fn spawn_player(mut commands: Commands) {
// Describes how to convert from player inputs into those actions
let input_map = InputMap::new([(Action::Jump, KeyCode::Space)]);
commands.spawn(input_map).insert(Player);
}
// Query for the `ActionState` component in your game logic systems!
fn jump(query: Query<&ActionState<Action>, With<Player>>) {
let action_state = query.single();
if let Ok(action_state) = action_state {
// Each action has a button-like state of its own that you can check
if action_state.just_pressed(&Action::Jump) {
println!("I'm jumping!");
}
}
}
This snippet is the minimal.rs example from the examples folder: check there for more in-depth learning materials!
Please refer to the [features] section in the Cargo.toml for information about the available crate features.
(top 24 of 25)
565 followers · starred Aug 2023
98 followers · starred Mar 2023
122 followers · starred Sep 2024
18 followers · starred Feb 2025