Understanding bevy's default plugins
Tags: rust, gamedev, ecs, bevy
Published: 2022-04-13 22:19:02

[Bevy](https://bevyengine.org/) is
> A refreshingly simple data-driven game engine built in Rust
Free and Open Source Forever!

A starter bevy program might look like this:

```rust
use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .run();
}
```

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](#log-plugin)
- [CorePlugin](#core-plugin)
- [TransformPlugin](#transform-plugin)
- [DiagnosticsPlugin](#diagnostics-plugin)
- [InputPlugin](#input-plugin)
- [WindowPlugin](#window-plugin)
- [AssetPlugin](#asset-plugin)
- 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` <a name="log-plugin"></a>

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
````rust
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(),
});
```

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

```sh
# equivalent
$ RUST_LOG="error,wgpu_core::instance=info" cargo run
```

## `CorePlugin` <a name="core-plugin"></a>

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:

```rust
#[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!");
        }
    }
}
```

## `TransformPlugin` <a name="transform-plugin"></a>

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o3hb5oqhvomrcldgv40v.gif)

## `DiagnosticsPlugin` <a name="diagnostics-plugin"></a>

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.

```rust
// ...
.add_plugin(bevy::diagnostic::FrameTimeDiagnosticsPlugin::default()
.add_plugin(bevy::diagnostic::LogDiagnosticPlugin::default())
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kzsicxtsyqvz4qaw8saw.png)

## `InputPlugin` <a name="input-plugin"></a>

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:
```rust
fn my_system(
    mut events: EventReader<MouseButtonInput>,
) {
    for event in events.iter() {
        if event.state.is_pressed() {
            bevy::log::info!("{:?} pressed!", event.button);
        }
    }
}
```

## `WindowPlugin` <a name="window-plugin"></a>

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:
```rust
fn my_system(
    mut events: EventReader<CursorEntered>,
) {
    for event in events.iter() {
         bevy::log::info!("cursor entered!");
    }
}
```

We can also define some settings for the window creation:
```rust
.insert_resource(WindowDescriptor {
    width: 400.,
    height: 200.,
    ..Default::default()
})
// ...
```

## `AssetPlugin` <a name="asset-plugin"></a>

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
```rust
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 });
}
```

And request them like this
```rust
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 ...
    }
}
```

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.