Expand description
§bevy-plugin-builder
Declarative plugin system for Bevy
This crate provides the define_plugin! macro that eliminates boilerplate
from Bevy plugin registration. Instead of manually implementing Plugin,
you declare your plugin’s requirements and the macro handles all registration.
§Features
- Eliminates repetitive
impl Plugin forblocks - Compile-time validation of all registrations
- Supports all Bevy registration patterns
§Quick Start
Add to your Cargo.toml:
[dependencies]
bevy-plugin-builder = "0.2"
bevy = "0.17"Then transform your plugins:
use bevy_plugin_builder::define_plugin;
use bevy::prelude::*;
// Define your game types
#[derive(Resource, Default)]
struct GameSettings;
#[derive(Resource, Default)]
struct PlayerStats;
#[derive(Message)]
struct PlayerDied;
#[derive(Message)]
struct ScoreChanged;
#[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash)]
enum GameState {
#[default]
Menu,
Playing,
}
// Define your systems
fn setup_game() {}
fn handle_input() {}
fn update_physics() {}
fn render_game() {}
define_plugin!(MyGamePlugin {
resources: [GameSettings, PlayerStats],
messages: [PlayerDied, ScoreChanged],
startup: [setup_game],
update: [
(handle_input, update_physics, render_game)
.chain()
.run_if(in_state(GameState::Playing))
]
});§Supported Configuration Options
resources: [Type1, Type2]- Initialize resources withinit_resourcemessages: [Message1, Message2]- Register messages withadd_messageplugins: [Plugin1, Plugin2]- Add sub-plugins withadd_pluginsstates: [State1]- Initialize states withinit_statesub_states: [SubState1]- Add sub-states withadd_sub_statereflect: [Type1, Type2]- Register types for reflectionstartup: [system1, system2]- Add startup systemsupdate: [system3, system4]- Add update systems (supports conditions/ordering)fixed_update: [system5]- Add fixed update systemson_enter: { State::Variant => [system6] }- Add state enter systemson_exit: { State::Variant => [system7] }- Add state exit systemscustom_init: |app| { ... }- Custom initialization logiccustom_finish: |app| { ... }- Custom finish logic
§Advanced Example
use bevy_plugin_builder::define_plugin;
use bevy::prelude::*;
#[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash)]
enum GameState {
#[default]
Menu,
Playing,
Paused,
}
#[derive(Resource, Default, Reflect)]
#[reflect(Resource)]
struct GameSettings { volume: f32 }
#[derive(Message)]
struct GameStarted;
define_plugin!(ComplexGamePlugin {
// Type registration
resources: [GameSettings],
messages: [GameStarted],
states: [GameState],
reflect: [GameSettings],
// System scheduling
startup: [initialize_audio, load_assets],
update: [
handle_menu_input.run_if(in_state(GameState::Menu)),
(update_game, process_events).chain().run_if(in_state(GameState::Playing))
],
fixed_update: [
physics_simulation.run_if(in_state(GameState::Playing))
],
// State transitions
on_enter: {
GameState::Playing => [setup_level, spawn_player],
GameState::Paused => [show_pause_menu]
},
on_exit: {
GameState::Playing => [cleanup_level]
},
// Custom logic
custom_init: |app: &mut App| {
#[cfg(debug_assertions)]
app.add_plugins(bevy::diagnostic::DiagnosticsPlugin::default());
}
});
fn initialize_audio() { /* ... */ }
fn load_assets() { /* ... */ }
fn handle_menu_input() { /* ... */ }
fn update_game() { /* ... */ }
fn process_events() { /* ... */ }
fn physics_simulation() { /* ... */ }
fn setup_level() { /* ... */ }
fn spawn_player() { /* ... */ }
fn show_pause_menu() { /* ... */ }
fn cleanup_level() { /* ... */ }§Migration Guide
Converting existing plugins is straightforward:
- Replace
impl Pluginwithdefine_plugin! - Group registrations by type (resources, events, systems)
- Use declarative syntax instead of method chains
See the examples for complete migration examples.
Macros§
- define_
plugin - Define a Bevy plugin declaratively, eliminating boilerplate registration code.
- define_
plugin_ finish - Macro for handling Plugin finish() method configuration
- define_
plugin_ internal - Internal macro for parsing and applying plugin configuration. This is separate from the main macro to allow for recursive parsing.
Structs§
- App
Appis the primary API for writing user applications. It automates the setup of a standard lifecycle and provides interface glue for plugins.- Fixed
Update - The schedule that contains most gameplay logic, which runs at a fixed rate rather than every render frame.
For logic that should run once per render frame, use the
Updateschedule instead. - OnEnter
- The label of a
Schedulethat only runs wheneverState<S>enters the provided state. - OnExit
- The label of a
Schedulethat only runs wheneverState<S>exits the provided state. - Startup
- The schedule that runs once when the app starts.
- Update
- The schedule that contains any app logic that must run once per render frame.
For most gameplay logic, consider using
FixedUpdateinstead.
Traits§
- Plugin
- A collection of Bevy app logic and configuration.