Plugin System
godot-bevy follows Bevy's philosophy of opt-in plugins, giving you granular control over which features are included in your build. This results in smaller binaries, better performance, and clearer dependencies.
Default Behavior
By default, GodotPlugin (automatically included by the #[bevy_app] macro) only provides minimal core functionality through GodotCorePlugins:
- Scene tree management (automatic entity mirroring)
- Asset loading system
- Basic Bevy setup
All other features must be explicitly added as plugins.
Plugin Groups
-
GodotCorePlugins: Minimal required functionality- Automatically included by
#[bevy_app]macro viaGodotPlugin - Includes:
GodotBaseCorePlugin: Bevy MinimalPlugins, logging, diagnostics, schedulesGodotSceneTreePlugin: Scene tree entity mirroring and management
- Automatically included by
-
GodotDefaultPlugins: Contains all plugins typically necessary for building a game- Includes:
GodotAssetsPlugin: Godot resource loading through Bevy's asset systemGodotTransformSyncPlugin: Transform synchronizationGodotCollisionsPlugin: Collision detectionBevyInputBridgePlugin: Bevy input API supportGodotAudioPlugin: Audio systemGodotPackedScenePlugin: Runtime scene spawningGodotBevyLogPlugin: Unify/improve bevy and godot logging such thatinfo!,debug!, etc log messages are visible in the Godot Editor
- Includes:
Typed signals are opt-in per message type using GodotSignalsPlugin::<T>.
Available Plugins
Core Infrastructure (Included by Default)
-
GodotBaseCorePlugin: Foundation setup- Bevy MinimalPlugins (without ScheduleRunnerPlugin)
- Asset system with Godot resource reader
- Logging and diagnostics
- Physics update schedule
- Main thread marker resource
-
GodotSceneTreePlugin: Scene tree management- Automatic entity creation for scene nodes
- Scene tree change monitoring
- Transform component addition (configurable)
- AutoSync bundle registration
- Groups component for Godot groups
NodeEntityIndexresource for O(1) lookup from GodotInstanceIdto BevyEntity
Additional Plugins
-
GodotAssetsPlugin: Asset loading- Load Godot resources through Bevy's AssetServer
- Supports .tscn, .tres, textures, sounds, etc.
- Development and export path handling
-
GodotTransformSyncPlugin: Transform synchronization- Configure sync mode:
Disabled,OneWay(default), orTwoWay - Synchronizes Bevy Transform components with Godot node transforms
- Required for moving/positioning nodes from Bevy
- Configure sync mode:
-
GodotCollisionsPlugin: Collision detection- Monitors Area2D/3D and RigidBody2D/3D collision signals
- Provides
Collisionssystem param for querying collision state - Provides
CollisionStarted/CollisionEndedevents (messages + observers)
-
GodotSignalsPlugin<T>: Typed signal bridge- Add one plugin per message type you want to emit
- Use
GodotSignals<T>to connect signals - Essential for UI interactions (button clicks, etc.)
-
GodotInputEventPlugin: Raw input events- Provides Godot input as Bevy events
- Keyboard, mouse, touch, gamepad, and action events
- Lower-level alternative to
BevyInputBridgePlugin
-
BevyInputBridgePlugin: Bevy input API- Use Bevy's standard
ButtonInput<KeyCode>, mouse events, etc. - Automatically includes
GodotInputEventPlugin - Higher-level, more ergonomic than raw events
- Use Bevy's standard
-
GodotAudioPlugin: Audio system- Channel-based audio API
- Spatial audio support
- Audio tweening and easing
- Integrates with Godot's audio engine
-
GodotPackedScenePlugin: Scene spawning- Spawn/instantiate scenes at runtime
- Support for both asset handles and paths
- Automatic transform application
-
GodotBevyLogPlugin: Improved logging by default- Log message components are color-coded for readability by default. Color coding can be disabled entirely. NOTE: There is a performance penalty for color-coding, so if your application is very performance sensitive, consider disabling this feature
- Log messages are prefixed with a short timestamp, e.g.,
12:00:36.196. Timestamps can be customized or entirely disabled - Log messages are prefixed with a short log level, e.g.,
TforTRACE,DforDEBUG,IforINFO,WforWARN,EforERROR - Log messages are suffixed with a shortened path and line number location, e.g.,
@ loading_state/systems.rs:186 - Log level filtering is
INFOand higher severity by default, this can be customized directly in your code or set at runtime usingRUST_LOG, e.g.,RUST_LOG=trace cargo run
Usage Examples
Minimal Setup (Default)
The #[bevy_app] macro automatically provides core functionality:
#![allow(unused)] fn main() { #[bevy_app] fn build_app(app: &mut App) { // GodotCorePlugins is already added // You have scene tree, assets, and basic setup app.add_systems(Update, my_game_system); } }
Adding Specific Features
Add only the plugins you need:
#![allow(unused)] fn main() { #[bevy_app] fn build_app(app: &mut App) { app.add_plugins(GodotTransformSyncPlugin::default()) .add_plugins(GodotAudioPlugin) .add_plugins(BevyInputBridgePlugin); app.add_systems(Update, my_game_systems); } }
Everything Enabled
For all features or easy migration from older versions:
#![allow(unused)] fn main() { #[bevy_app] fn build_app(app: &mut App) { app.add_plugins(GodotDefaultPlugins); app.add_systems(Update, my_game_systems); } }
Game-Specific Configurations
Pure ECS Game:
#![allow(unused)] fn main() { #[bevy_app] fn build_app(app: &mut App) { app.add_plugins(GodotTransformSyncPlugin::default()) .add_plugins(GodotAudioPlugin) .add_plugins(BevyInputBridgePlugin); } }
Physics Platformer:
#![allow(unused)] fn main() { #[bevy_app] fn build_app(app: &mut App) { app.add_plugins(GodotTransformSyncPlugin { sync_mode: TransformSyncMode::Disabled, // Use Godot physics ..Default::default() }) .add_plugins(GodotCollisionsPlugin) .add_plugins(GodotSignalsPlugin::<UiSignal>::default()) .add_plugins(GodotAudioPlugin); } }
UI-Heavy Game:
#![allow(unused)] fn main() { #[bevy_app] fn build_app(app: &mut App) { app.add_plugins(GodotSignalsPlugin::<UiSignal>::default()) .add_plugins(BevyInputBridgePlugin) .add_plugins(GodotAudioPlugin); } }
Plugin Configuration
Transform Sync Modes
#![allow(unused)] fn main() { // Default: One-way sync (Bevy → Godot) app.add_plugins(GodotTransformSyncPlugin::default()); // Two-way sync (Bevy ↔ Godot) app.add_plugins(GodotTransformSyncPlugin { sync_mode: TransformSyncMode::TwoWay, ..Default::default() }); // Disabled (use Godot physics directly) app.add_plugins(GodotTransformSyncPlugin { sync_mode: TransformSyncMode::Disabled, ..Default::default() }); }
Scene Tree Configuration
#![allow(unused)] fn main() { // Configure transform component creation app.add_plugins(GodotSceneTreePlugin::default()); }
Note: This is already included in GodotCorePlugins, so you'd need to disable the default GodotPlugin and build your own plugin setup to customize this.
Plugin Dependencies
Some plugins automatically include their dependencies:
BevyInputBridgePlugin→ includesGodotInputEventPluginGodotPlugin→ includesGodotCorePlugins
Choosing the Right Plugins
Start with GodotDefaultPlugins. It bundles everything most games need, so the first
tutorial and Query<&mut Transform> just work rather than silently matching nothing. Once
your game runs, strip the plugins you don't use for smaller binaries and fewer systems --
each one maps to a single feature:
- Load Godot resources through Bevy's asset system →
GodotAssetsPlugin - Move/position nodes from Bevy →
GodotTransformSyncPlugin - Play sounds and music →
GodotAudioPlugin - Respond to UI signals →
GodotSignalsPlugin::<YourMessage> - Detect collisions →
GodotCollisionsPlugin - Handle input →
BevyInputBridgePluginorGodotInputEventPlugin - Spawn scenes at runtime →
GodotPackedScenePlugin
In dev builds, godot-bevy prints the active plugin table to Godot's output panel at startup.
If a feature silently is not working, check there first -- a missing plugin shows up as off.
Benefits
Smaller Binaries
Only compile the features you actually use.
Better Performance
Skip unused systems and resources.
Clear Dependencies
Your plugin list shows exactly what features you're using.
Future-Proof
New optional features can be added without breaking existing code.
Migration Note
If upgrading from an older version where all features were included by default, simply add:
#![allow(unused)] fn main() { app.add_plugins(GodotDefaultPlugins); }
This restores the old behavior with all features enabled.