DEV Community

Cover image for Understanding bevy's default plugins
Eduard
Eduard

Posted on

Understanding bevy's default plugins

Bevy is

A refreshingly simple data-driven game engine built in Rust
Free and Open Source Forever!

A starter bevy program might look like this:

use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .run();
}
Enter fullscreen mode Exit fullscreen mode

this will add the core functionality and give us a window.

But what exactly are these "default plugins" doing ? We will explore just that in this post.


The exact list of plugins included is the following:

  • LogPlugin
  • CorePlugin
  • TransformPlugin
  • DiagnosticsPlugin
  • InputPlugin
  • WindowPlugin
  • AssetPlugin
  • ScenePlugin
  • RenderPlugin - with feature bevy_render
  • SpritePlugin - with feature bevy_sprite
  • PbrPlugin - with feature bevy_pbr
  • UiPlugin - with feature bevy_ui
  • TextPlugin - with feature bevy_text
  • AudioPlugin - with feature bevy_audio
  • GilrsPlugin - with feature bevy_gilrs
  • GltfPlugin - with feature bevy_gltf
  • WinitPlugin - with feature bevy_winit

LogPlugin

This plugin is really simple, it will add an appropriate logger for your target (e.g. log to console when targeting wasm) and this will allow all logs to go to the right place.

It can be configured with a resource like this

app.insert_resource(bevy::log::LogSettings {
    // filter logs lower than ERROR
    level: bevy::log::Level::ERROR,
    // also include INFO logs of module wgpu_core::instance
    filter: "wgpu_core::instance=info".to_owned(),
});
Enter fullscreen mode Exit fullscreen mode

You can also pass a log config via environment variable RUST_LOG, this will override whatever settings where selected.

# equivalent
$ RUST_LOG="error,wgpu_core::instance=info" cargo run
Enter fullscreen mode Exit fullscreen mode

CorePlugin

The core plugin doesn't do anything too interesting. It will register some types, setup the time system, and setup the task pool.

One can use it to create timed systems, e.g. a system that does something every X amount of seconds:

#[derive(Component)]
struct Foo { pub timer: Timer }

// startup system to initialize timed component
fn my_setup(mut commands: Commands) {
    commands
        .spawn()
        .insert(Foo {
            // true to indicate a repeating timer
            timer: Timer::from_seconds(5., true),
        });
}

// system that does something based on timer
fn my_system(
    mut query: Query<&mut Foo>,
    time: Res<Time>,
) {
    for mut item in query.iter_mut() {
        // progress timers
        item.timer.tick(time.delta()); 
        if item.timer.finished() {
            bevy::log::info!("this prints every 3 seconds!");
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

TransformPlugin

This plugin sets up a transform model that allows objects to have a position, described as a hierarchy of parent-children relationships, similar to other game engines.

Every entity with GlobalTransform and Transform components gets this functionality. The GlobalTransform describes the entity's position globally, and is immutable by the user. The Transform describes the entity position in respect to its "parent" (or the global reference if there isn't one); this is the component we can modify to change an entity's position.

Whenever a Transform is updated, all its children get updated so their GlobalTransform reflects their new position.

Image description

DiagnosticsPlugin

The diagnostics plugin allows us to record any metric of interest, bevy comes with two plugins EntityCountDiagnosticsPlugin and FrameTimeDiagnosticsPlugin that we can use to record some useful data, as well as LogDiagnosticsPlugin, to log this diagnostics.

// ...
.add_plugin(bevy::diagnostic::FrameTimeDiagnosticsPlugin::default()
.add_plugin(bevy::diagnostic::LogDiagnosticPlugin::default())
Enter fullscreen mode Exit fullscreen mode

Image description

InputPlugin

This plugin is very straight forward, we can read input events in our systems to react according to user actions.

As an example, here we are catching all mouse button input:

fn my_system(
    mut events: EventReader<MouseButtonInput>,
) {
    for event in events.iter() {
        if event.state.is_pressed() {
            bevy::log::info!("{:?} pressed!", event.button);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

WindowPlugin

The window plugin is responsible for 2 things:

  1. Creating a window
  2. Managing window events

This means that just how we can react to mouse clicks, we can react to window events such as leaving or entering the window:

fn my_system(
    mut events: EventReader<CursorEntered>,
) {
    for event in events.iter() {
         bevy::log::info!("cursor entered!");
    }
}
Enter fullscreen mode Exit fullscreen mode

We can also define some settings for the window creation:

.insert_resource(WindowDescriptor {
    width: 400.,
    height: 200.,
    ..Default::default()
})
// ...
Enter fullscreen mode Exit fullscreen mode

AssetPlugin

This plugin allows us to load any asset and easily use them throughout our program. It features background IO which means our app won't lag from loading assets.

We can load an asset like this

fn load_something(
    mut commands: Commands,
    loader: Res<AssetServer>,
) {
    // this won't block us until the resource is loaded !
    let image: Handle<Image> = loader.load("image.png");
    commands.insert_resource(MyAsset { image });
}
Enter fullscreen mode Exit fullscreen mode

And request them like this

fn use_something(
    assets: Res<MyAsset>,
    images: Res<Assets<Image>>,
) {
    // at this point the asset could be loaded or not yet
    if let Some(loaded) = images.get(assets.image) {
        // do something ...
    }
}
Enter fullscreen mode Exit fullscreen mode

The asset server provides features like filesystem watching, which enables hot reload of assets during development.

Asset loaders can be implemented for any kind of asset, images, text, anything.


There are still many more plugins to explore and how they interact with each other, I plan to make more posts about them and also about what using bevy's ECS looks like.

Top comments (0)