Bevy Plugins
Bevy uses an architecture that lets you organize your game into encapsulated features called plugins.
A plugin is any function that takes an App
and modifies it with the plugins behavior. These functions can do anything in your normal App
definition, even adding other plugins.
fn plugin(app: &mut App) {
app.add_system(some_plugin_system);
}
fn main() {
App::new().add_plugins(plugin);
}
These plugins are useful for bundling up all the setup and runtime behavior of a feature into something we can toggle on and off. Plugins encapsulate the complexity of the feature into something we can "plug-into" our app.
By performing the necessary setup such as adding systems, resources and events to your game, each plugin is responsible for injecting its behavior into your game loop.
The Plugin trait
Usually we prefer to use simple functions, but if your plugin has additional life-cycle requirements you can implement the Plugin
trait and define the life-cycle methods you are interested in.
pub struct CameraPlugin;
impl Plugin for CameraPlugin {
fn cleanup(&self, _app: &App) -> bool {
info!("Time to clean up")
true
}
fn build(&self, app: &mut App) {
app.add_systems(Startup, initialize_camera);
}
}
fn initialize_camera(mut commands: Commands) {
commands.spawn(Camera2d);
}
Plugin life-cycle
Each Plugin
will go through a life-cycle of:
- We add our plugin to the
App
withadd_plugins
- Our plugin has its
build
method called - Bevy eventually calls
ready
on our plugin - Bevy internally polls to ensure all plugins succeeded
- Finally, Bevy calls
cleanup
on our plugin.
Plugin ordering and dependencies
Plugins are run in the order they are added to the App
.
Ideally a plugin would fully encapsulate its dependencies, but that's not always possible. Plugins that have dependencies do not currently have a good way to ensure those dependencies.
Bevy will also panic (by default) if you try and add the same plugin to your app more than once. You can work around this by checking if is_plugin_added
before adding it.
fn plugin(app: &mut App) {
if !app.is_plugin_added::<physics::PhysicsPlugin>() {
app.add_plugins(physics::PhysicsPlugin);
}
if !app.is_plugin_added::<bevy::input::InputPlugin>() {
app.add_plugins(bevy::input::InputPlugin);
}
}
This is a good practice for testing so that the test for your plugin can run without running the entire app.
Plugin configuration
If your plugin becomes complicated enough to demand configuration you can add fields to the struct that implements Plugin
.
pub struct CameraPlugin {
debug: bool,
}
impl Plugin for CameraPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, initialize_camera);
if self.debug {
// Do something
}
}
}
fn main() {
App::new()
.add_plugins(CameraPlugin { debug: true })
}
Plugin groups
Having plugins call other plugins is powerful and leads to a hierarchy of plugin dependencies. This can make it hard to configure.
Collections of plugins with a complicated setup can use the PluginGroup
trait which allow us to group related plugins together and then configure them later.
This can be great choice for library authors writing plugins that others can add to their game.
pub struct GamePlugins;
impl PluginGroup for GamePlugins {
fn build(self) -> PluginGroupBuilder {
PluginGroupBuilder::start::<Self>()
.add(CameraPlugin::default())
.add(PhysicsPlugin::default())
.add(LogicPlugin)
}
}
This will let us (or anyone consuming your plugins) configure exactly how the set of plugins runs in the context of our app:
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(
game::GamePlugins
.build()
.disable::<physics::PhysicsPlugin>()
)
.run();
}
The default plugins
Bevy includes DefaultPlugins
in the bevy::prelude
which gives us all of the obvious things our game would need:
Plugin | Description |
---|---|
DiagnosticsPlugin | Adds core diagnostics |
FrameCountPlugin | Adds frame counting functionality |
HierarchyPlugin | Handles Parent and Children components |
InputPlugin | Adds keyboard and mouse input |
LogPlugin | Adds logging to apps |
PanicHandlerPlugin | Adds sensible panic handling |
ScheduleRunnerPlugin | Configures an App to run its Schedule according to a given RunMode |
TaskPoolPlugin | Setup of default task pools for multithreading |
TimePlugin | Adds time functionality |
TransformPlugin | Handles Transform components |
TypeRegistrationPlugin | Registers types for reflection (dynamic lookup of types at runtime) |
Then depending on the features you enable (all enabled by default) you have more plugins that are added:
Plugin | Feature | Description |
---|---|---|
AccessibilityPlugin | bevy_window | Adds non-GUI accessibility functionality |
AnimationPlugin | bevy_animation | Adds animation support |
AssetPlugin | bevy_asset | Adds asset server and resources to load assets |
AudioPlugin | bevy_audio | Adds support for using sound assets |
DevToolsPlugin | bevy_dev_tools | Enables developer tools in an App |
CiTestingPlugin | bevy_ci_testing | Helps instrument continuous integration |
CorePipelinePlugin | bevy_core_pipeline | The core rendering pipeline |
DebugAssetPlugin | debug_asset_server | Adds stuff that helps debugging your assets |
GltfPlugin | bevy_gltf | Adds support for loading gltf models |
GilrsPlugin | bevy_gilrs | Adds support for gamepad inputs |
GizmoPlugin | bevy_gizmos | Provides an immediate mode drawing api for visual debugging |
GltfPlugin | bevy_gltf | Allows loading gltf based assets |
ImagePlugin | bevy_render | Adds the Image asset and prepares them to render on your GPU |
PbrPlugin | bevy_pbr | Adds physical based rendering with StandardMaterial etc |
PipelinedRenderingPlugin | bevy_render | Enables pipelined rendering which makes rendering multithreaded |
RenderPlugin | bevy_render | Sets up rendering backend powered by wgpu crate |
ScenePlugin | bevy_scene | Loading and saving collections of entities and components to files |
SpritePlugin | bevy_sprite | Handling of sprites (images on our entities) |
TextPlugin | bevy_text | Supports loading fonts and rendering text |
UiPlugin | bevy_ui | Adds support for UI layouts (flex, grid, etc) |
WindowPlugin | bevy_window | Provides an interface to create and manage Window components |
WinitPlugin | bevy_winit | Interface to create operating system windows (to actually display our game) |