Migration Guide: v0.7 to v0.8

This guide covers breaking changes and new features when upgrading from godot-bevy 0.7.x to 0.8.0.

Table of Contents

Opt-in Plugin System (Breaking Change)

What Changed

In v0.8.0, godot-bevy has adopted Bevy's philosophy of opt-in plugins. This gives users granular control over which features are included in their build.

Breaking Change: GodotPlugin now only includes minimal core functionality by default (basic scene tree access and assets). Automatic entity creation and other features must be explicitly opted-in.

Migration Path

The quickest migration is to use GodotDefaultPlugins for the old behavior, but we recommend adding only the plugins you need.

Option 1: Quick Migration (Old Behavior)

Replace the #[bevy_app] macro usage with explicit plugin registration:

Before (v0.7.x):

#![allow(unused)]
fn main() {
#[bevy_app]
fn build_app(app: &mut App) {
    // GodotPlugin automatically included all features:
    // - Automatic entity creation for scene tree nodes
    // - Transform synchronization
    // - Collision detection
    // - Signal handling
    // - Input events
    // - Audio system
    app.add_systems(Update, my_game_systems);
}
}

After (v0.8.0) - Quick Fix:

#![allow(unused)]
fn main() {
#[bevy_app]
fn build_app(app: &mut App) {
    // Add all features like before
    app.add_plugins(GodotDefaultPlugins);
    app.add_systems(Update, my_game_systems);
}
}

Pure ECS game (transforms + basic features):

#![allow(unused)]
fn main() {
#[bevy_app]
fn build_app(app: &mut App) {
    app.add_plugins(GodotSceneTreeMirroringPlugin {
            add_transforms: true,
        })
        .add_plugins(GodotTransformSyncPlugin::default())  // OneWay sync
        .add_plugins(GodotAudioPlugin);                    // Audio system
    app.add_systems(Update, my_game_systems);
}
}

Platformer (no transform conflicts):

#![allow(unused)]
fn main() {
#[bevy_app]
fn build_app(app: &mut App) {
    app.add_plugins(GodotSceneTreeMirroringPlugin {
            add_transforms: false,  // Use Godot physics instead
        })
        .add_plugins(GodotCollisionsPlugin)         // Collision detection
        .add_plugins(GodotAudioPlugin)              // Audio system
        .add_plugins(GodotSignalsPlugin);           // UI signals
    app.add_systems(Update, my_game_systems);
}
}

Full-featured game:

#![allow(unused)]
fn main() {
#[bevy_app] 
fn build_app(app: &mut App) {
    app.add_plugins(GodotDefaultPlugins);   // Everything
    app.add_systems(Update, my_game_systems);
}
}

Available Plugins

Core (Always Included):

  • GodotCorePlugins - Basic scene tree access, assets, basic setup (automatically included by #[bevy_app])

Scene Tree Plugins:

  • GodotSceneTreeRefPlugin - Basic scene tree access (included in GodotCorePlugins)
  • GodotSceneTreeEventsPlugin - Monitor scene tree changes without creating entities
  • GodotSceneTreeMirroringPlugin - Auto-create entities for scene nodes (equivalent to v0.7.x behavior)

Optional Feature Plugins:

  • GodotTransformSyncPlugin - Add if you want to move/position nodes from Bevy systems
  • GodotAudioPlugin - Add if you want to play sounds and music from Bevy systems
  • GodotSignalsPlugin - Add if you want to respond to Godot signals (button clicks, etc.) in Bevy systems
  • GodotCollisionsPlugin - Add if you want to detect collisions and physics events in Bevy systems
  • GodotInputEventPlugin - Add if you want to handle input from Godot in Bevy systems
  • BevyInputBridgePlugin - Add if you prefer Bevy's input API (auto-includes GodotInputEventPlugin)
  • GodotPackedScenePlugin - Add if you want to spawn scenes dynamically from Bevy systems

Convenience Bundles:

  • GodotDefaultPlugins - All plugins enabled (equivalent to old v0.7.x behavior)

Plugin Dependencies

Some plugins automatically include their dependencies:

  • GodotSceneTreeMirroringPlugin automatically includes GodotSceneTreeEventsPlugin
  • BevyInputBridgePlugin automatically includes GodotInputEventPlugin

Benefits of the New System

  1. Smaller binaries - Only compile what you use
  2. Better performance - Skip unused systems
  3. Clearer dependencies - Explicit about what your game needs
  4. Future-proof - Easy to add new optional features

Migration Checklist

  • Quick fix: Add app.add_plugins(GodotDefaultPlugins) to your build_app function
  • Optimization: Replace GodotDefaultPlugins with only the specific plugins you need
  • Test: Ensure all features work correctly with your plugin selection
  • Consider: Whether you can disable some features (e.g., transform sync for physics games)

GodotSignals Resource (Breaking Change)

What Changed

In v0.8.0, the signal connection system has been significantly simplified and improved:

New GodotSignals SystemParam: Signal connections are now handled through a dedicated GodotSignals resource

Migration Path

The main change is switching from the standalone connect_godot_signal function to the new GodotSignals SystemParam.

Before (v0.7.x)

#![allow(unused)]
fn main() {
use godot_bevy::prelude::*;

fn connect_signals(
    mut scene_tree: SceneTreeRef,
) {
    if let Some(root) = scene_tree.get().get_root() {
        if let Some(button) = root.try_get_node_as::<Button>("UI/MyButton") {
            let mut handle = GodotNodeHandle::from_instance_id(button.instance_id());
            // Old function signature required SceneTreeRef parameter
            connect_godot_signal(&mut handle, "pressed", &mut scene_tree);
        }
    }
}
}

After (v0.8.0)

#![allow(unused)]
fn main() {
use godot_bevy::prelude::*;

fn connect_signals(
    mut scene_tree: SceneTreeRef,
    signals: GodotSignals,  // ← New SystemParam
) {
    if let Some(root) = scene_tree.get().get_root() {
        if let Some(button) = root.try_get_node_as::<Button>("UI/MyButton") {
            let mut handle = GodotNodeHandle::from_instance_id(button.instance_id());
            // New simplified API
            signals.connect(&mut handle, "pressed");
        }
    }
}
}

Breaking Changes

  1. Function signature changed: connect_godot_signal no longer requires SceneTreeRef parameter
  2. New SystemParam required: Add GodotSignals parameter to systems that connect signals
  3. Recommended API change: Use signals.connect() instead of direct connect_godot_signal() calls

Migration Checklist

  • Add GodotSignals parameter to systems that connect signals
  • Replace connect_godot_signal(&mut handle, signal_name, &mut scene_tree) with signals.connect(&mut handle, signal_name)
  • Remove unused SceneTreeRef parameters if they were only used for signal connections
  • Test that all signal connections work correctly with the new system

Summary

The v0.8.0 signal system simplifies signal connections while improving performance. The main migration step is:

  1. Add GodotSignals parameter to systems that connect signals
  2. Replace connect_godot_signal(&mut handle, signal, &mut scene_tree) with signals.connect(&mut handle, signal)
  3. Remove unused SceneTreeRef parameters

The signal event handling (EventReader<GodotSignal>) remains unchanged, so only the connection setup needs to be updated.

BevyBundle Enhanced Property Mapping (New Feature)

What's New

In v0.8.0, the BevyBundle macro has been significantly enhanced with more flexible property mapping options:

  1. Struct Component Mapping: Map multiple Godot properties to fields in a struct component
  2. Transform Functions: Apply transformation functions to convert values during mapping
  3. Improved Syntax: More intuitive syntax for single and multi-field mappings

New Mapping Options

Struct Component Mapping

You can now map multiple Godot properties to fields in a struct component:

#![allow(unused)]
fn main() {
#[derive(Component)]
struct Stats {
    health: f32,
    mana: f32,
    stamina: f32,
}

#[derive(GodotClass, BevyBundle)]
#[class(base=CharacterBody2D)]
#[bevy_bundle((Player), (Stats { health: max_health, mana: max_mana, stamina: max_stamina }))]
pub struct PlayerCharacter {
    base: Base<CharacterBody2D>,
    #[export] max_health: f32,
    #[export] max_mana: f32,
    #[export] max_stamina: f32,
}
}

Transform Functions

Apply transformation functions to convert Godot values before assigning to components:

#![allow(unused)]
fn main() {
fn percentage_to_fraction(value: f32) -> f32 {
    value / 100.0
}

#[derive(GodotClass, BevyBundle)]
#[class(base=Node2D)]
#[bevy_bundle((Enemy), (Health: health_percentage))]
pub struct Enemy {
    base: Base<Node2D>,
    #[export]
    #[bundle(transform_with = "percentage_to_fraction")]
    health_percentage: f32,  // Editor shows 0-100, component gets 0.0-1.0
}
}

Backwards Compatibility

All existing v0.7.x BevyBundle syntax remains fully supported:

#![allow(unused)]
fn main() {
// Still works in v0.8.0
#[bevy_bundle((Player), (Health: max_health))]
}

Benefits

  • Better Component Design: Create struct components that group related data
  • Editor-Friendly Values: Use transform functions to convert between editor-friendly and system-friendly values
  • Type Safety: All mappings are verified at compile time
  • Flexibility: Mix and match different mapping styles as needed

For complete documentation on the new features, see the Custom Node Markers section.