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 via GodotPlugin
    • Includes:
      • GodotBaseCorePlugin: Bevy MinimalPlugins, logging, diagnostics, schedules
      • GodotSceneTreePlugin: Scene tree entity mirroring and management
  • GodotDefaultPlugins: Contains all plugins typically necessary for building a game

    • Includes:
      • GodotAssetsPlugin: Godot resource loading through Bevy's asset system
      • GodotTransformSyncPlugin: Transform synchronization
      • GodotCollisionsPlugin: Collision detection
      • BevyInputBridgePlugin: Bevy input API support
      • GodotAudioPlugin: Audio system
      • GodotPackedScenePlugin: Runtime scene spawning
      • GodotBevyLogPlugin: Unify/improve bevy and godot logging such that info!, debug!, etc log messages are visible in the Godot Editor

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
    • NodeEntityIndex resource for O(1) lookup from Godot InstanceId to Bevy Entity

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), or TwoWay
    • Synchronizes Bevy Transform components with Godot node transforms
    • Required for moving/positioning nodes from Bevy
  • GodotCollisionsPlugin: Collision detection

    • Monitors Area2D/3D and RigidBody2D/3D collision signals
    • Provides Collisions system param for querying collision state
    • Provides CollisionStarted / CollisionEnded events (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
  • 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., T for TRACE, D for DEBUG, I for INFO, W for WARN, E for ERROR
    • Log messages are suffixed with a shortened path and line number location, e.g., @ loading_state/systems.rs:186
    • Log level filtering is INFO and higher severity by default, this can be customized directly in your code or set at runtime using RUST_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 → includes GodotInputEventPlugin
  • GodotPlugin → includes GodotCorePlugins

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 systemGodotAssetsPlugin
  • Move/position nodes from BevyGodotTransformSyncPlugin
  • Play sounds and musicGodotAudioPlugin
  • Respond to UI signalsGodotSignalsPlugin::<YourMessage>
  • Detect collisionsGodotCollisionsPlugin
  • Handle inputBevyInputBridgePlugin or GodotInputEventPlugin
  • Spawn scenes at runtimeGodotPackedScenePlugin

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.