What it is
Bevy is a data-driven game engine for Rust built on an Entity Component System, with a renderer, audio, input, physics integration and hot-reloading assets.
Entities are ids, components are data, and systems are functions that query for components. Bevy schedules systems in parallel automatically based on what they access.
Installation
cargo add bevyGetting started
The smallest useful thing you can do with it, and what each part means.
use bevy::prelude::*;
#[derive(Component)]
struct Velocity(Vec2);
#[derive(Component)]
struct Player;
fn movement(time: Res<Time>, mut query: Query<(&mut Transform, &Velocity)>) {
for (mut transform, velocity) in &mut query {
// Always scale by delta time, or speed depends on frame rate.
transform.translation += velocity.0.extend(0.0) * time.delta_secs();
}
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, spawn)
.add_systems(Update, (movement, handle_input))
.run();
}Advanced usage
Where the library earns its place over a simpler alternative.
// With<> and Without<> restrict the query without borrowing the data.
fn player_only(mut q: Query<&mut Transform, (With<Player>, Without<Enemy>)>) { }
#[derive(States, Default, Clone, Eq, PartialEq, Hash, Debug)]
enum GameState { #[default] Menu, Playing, Paused }
#[derive(Event)]
struct ScoreChanged(u32);
App::new()
.init_state::<GameState>()
.add_event::<ScoreChanged>()
.add_systems(Update, gameplay.run_if(in_state(GameState::Playing)))
.add_systems(OnEnter(GameState::Paused), show_pause_menu);Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- error[B0001]: Query conflicts with a previous access
- Two query parameters can match the same entity mutably. Separate them with With/Without, or use ParamSet.
- Compile times are painful
- Turn on the dynamic_linking feature for development builds, and use a fast linker such as lld or mold.
Best practices
- Multiply movement by time.delta_secs() so behaviour is frame-rate independent.
- Use With/Without filters to disambiguate overlapping queries and avoid conflicts.
- Enable dynamic_linking in development — full rebuilds are otherwise very slow.
- Expect breaking changes: Bevy iterates quickly and pins to exact versions in practice.
Background
Why it exists, and what it was reacting to.
Created by Carter Anderson, Bevy made the ECS pattern approachable through a system API that reads as ordinary Rust functions, and became the centre of Rust game development remarkably quickly.
