Migration Guide: v0.8 to v0.9
This guide covers breaking changes and new features when upgrading from godot-bevy 0.8.x to 0.9.0.
Table of Contents
- Godot Bevy now uses standard Bevy Transforms (Breaking Change)
- Assets Plugin Moved to Optional (Breaking Change)
- Gamepad Support Now Optional
- Scene Tree Plugin Configuration Simplified
Godot Bevy now uses standard Bevy Transforms (Breaking Change)
What Changed
In v.0.9.0, we've made significant changes to how we use bevy Transform
components. We now operate directly on standard
Transform
components and you can too, whereas before, we had wrapped the Transform
component in higher level
Transform2D
and Transform3D
components and required you to use the wrappers. While wrapping provided important
benefits (change detection, dual-godot/bevy-API access with built-in multi-threaded safety) it came with some notable
drawbacks (incompatible with other bevy ecosystem plugins that operate directly on Transform
s, extra memory overhead,
less ergonomic as it required extra API calls to access the underlying data).
Migration Path
The main change is switching all of your usages of godot_bevy::prelude::Transform2D
or
godot_bevy::prelude::Transform3D
to bevy::transform::components::Transform
.
Before (v.0.9.0)
#![allow(unused)] fn main() { fn orbit_system( // The `transform` parameter is a Bevy `Query` that matches all `Transform2D` components. // `Transform2D` is a Godot-Bevy-provided component that matches all Node2Ds in the scene. // (https://docs.rs/godot-bevy/latest/godot_bevy/plugins/core/transforms/struct.Transform2D.html) mut transform: Query<(&mut Transform2D, &InitialPosition, &mut Orbiter)>, // This is equivalent to Godot's `_process` `delta: float` parameter. process_delta: Res<Time>, ) { // For single matches, you can use `single_mut()` instead: // `if let Ok(mut transform) = transform.single_mut() {` for (mut transform, initial_position, mut orbiter) in transform.iter_mut() { transform.as_godot_mut().origin = initial_position.pos + Vector2::from_angle(orbiter.angle) * 100.0; orbiter.angle += process_delta.as_ref().delta_secs(); orbiter.angle %= 2.0 * PI; } } }
After (v.0.9.0)
#![allow(unused)] fn main() { fn orbit_system( // The `transform` parameter is a Bevy `Query` that matches all `Transform` components. // `Transform` is a Godot-Bevy-provided component that matches all Node2Ds in the scene. // (https://docs.rs/godot-bevy/latest/godot_bevy/plugins/core/transforms/struct.Transform.html) mut transform: Query<(&mut Transform, &InitialPosition, &mut Orbiter)>, // This is equivalent to Godot's `_process` `delta: float` parameter. process_delta: Res<Time>, ) { // For single matches, you can use `single_mut()` instead: // `if let Ok(mut transform) = transform.single_mut() {` for (mut transform, initial_position, mut orbiter) in transform.iter_mut() { let position2d = initial_position.pos + Vector2::from_angle(orbiter.angle) * 100.0; transform.translation.x = position2d.x; transform.translation.y = position2d.y; orbiter.angle += process_delta.as_ref().delta_secs(); orbiter.angle %= 2.0 * PI; } } }
Breaking changes
godot_bevy::prelude::Transform2D
andgodot_bevy::prelude::Transform3D
were removed
Migration Checklist
-
Transform components changed: Replaced
godot_bevy::prelude::Transform2D
andgodot_bevy::prelude::Transform3D
withbevy::transform::components::Transform
. The APIs from the former must be mapped to the latter:-
Remove the now extra
as_bevy()
andas_bevy_mut()
calls, since you're operating directly on bevy Transforms, e.g.,transform.as_bevy_mut().translation.x
->transform.translation.x
. These changes should be easy. -
Remap the
as_godot()
andas_godot_mut()
calls. These changes may be tricky, as there may not be direct replacements for all Godot APIs in native Bevy transforms. One important benefit of doing this work is that it promotes a clean separation where your bevy transform systems remain portable to other Bevy projects (with or without godot-bevy). You can always fall back on using GodotNodeHandle to get at the original Godot Node APIs, then replicate position, scale, and rotation back to the bevy Transform as necessary.
-
Remove the now extra
Assets Plugin Moved to Optional (Breaking Change)
What Changed
In v0.9.0, GodotAssetsPlugin
has been moved from GodotCorePlugins
(included by default) to GodotDefaultPlugins
(optional). This change provides a cleaner architecture where core functionality is truly minimal and reduces runtime overhead for applications that don't need to load Godot resources through Bevy's asset system.
Who Is Affected
You are affected if:
- You use
GodotCorePlugins
directly (withoutGodotDefaultPlugins
) - You load Godot resources using
Handle<GodotResource>
orAssetServer
- You use
GodotAudioPlugin
orGodotPackedScenePlugin
(they require assets)
Migration Path
If you use GodotDefaultPlugins
No changes needed - GodotAssetsPlugin
is included in GodotDefaultPlugins
.
#![allow(unused)] fn main() { #[bevy_app] fn build_app(app: &mut App) { app.add_plugins(GodotDefaultPlugins); // ✅ Assets included } }
If you use GodotCorePlugins
and need asset loading
Add GodotAssetsPlugin
explicitly:
#![allow(unused)] fn main() { #[bevy_app] fn build_app(app: &mut App) { // GodotCorePlugins no longer includes assets app.add_plugins(GodotAssetsPlugin) // Add this line .add_plugins(GodotAudioPlugin) // Requires GodotAssetsPlugin .add_plugins(GodotPackedScenePlugin); // Requires GodotAssetsPlugin } }
If you don't need asset loading
No changes needed - enjoy reduced runtime overhead!
#![allow(unused)] fn main() { #[bevy_app] fn build_app(app: &mut App) { // Now truly minimal - no asset loading overhead app.add_plugins(GodotTransformSyncPlugin) .add_plugins(GodotSignalsPlugin) .add_plugins(BevyInputBridgePlugin); } }
Breaking Changes
GodotCorePlugins
no longer includesGodotAssetsPlugin
GodotAssetsPlugin
is now inGodotDefaultPlugins
GodotAudioPlugin
andGodotPackedScenePlugin
requireGodotAssetsPlugin
to function
Migration Checklist
- Using GodotDefaultPlugins: No action needed
-
Using GodotCorePlugins + asset loading: Add
app.add_plugins(GodotAssetsPlugin)
-
Using GodotAudioPlugin: Ensure
GodotAssetsPlugin
is included -
Using GodotPackedScenePlugin: Ensure
GodotAssetsPlugin
is included - Pure ECS without assets: Consider removing unused plugins for better runtime performance
Gamepad Support Now Optional
What Changed
In v0.9.0, gamepad support through Bevy's GilrsPlugin
is now controlled by an optional feature flag bevy_gamepad
. This feature is enabled by default but can be disabled to reduce compile time and dependencies for applications that don't use gamepads.
Migration Path
If you use gamepads with Bevy's input API
No changes needed if using GodotDefaultPlugins
- GilrsPlugin
is included automatically.
If using custom plugin setup: Add GilrsPlugin
manually:
#![allow(unused)] fn main() { use godot_bevy::prelude::*; // Includes bevy_prelude::GilrsPlugin #[bevy_app] fn build_app(app: &mut App) { app.add_plugins(GilrsPlugin) // Available via bevy_prelude .add_plugins(BevyInputBridgePlugin); } }
If you only use Godot's gamepad input
No changes needed - Godot's gamepad support through GodotInputEventPlugin
works regardless of the feature flag.
If you don't use gamepads at all
Optional: Disable the feature for faster compile times:
[dependencies]
godot-bevy = { version = "0.9", default-features = false, features = [...] }
What Still Works Without the Feature
- ✅ Godot's gamepad input via
GodotInputEventPlugin
- ✅ Raw gamepad events in
EventReader<GamepadButtonInput>
andEventReader<GamepadAxisInput>
- ✅ All keyboard, mouse, and touch input
What Requires the Feature
- ❌ Bevy's standard gamepad API (
ButtonInput<GamepadButton>
,Axis<GamepadAxis>
) - ❌
GilrsPlugin
functionality - ❌ Cross-platform gamepad detection outside of Godot
Note: GilrsPlugin
is included in GodotDefaultPlugins
when the feature is enabled, but must be added manually if using a custom plugin configuration.
Scene Tree Plugin Configuration Simplified
What Changed
The add_transforms
configuration option has been removed from GodotSceneTreePlugin
. Transform components are now automatically added to scene tree entities when the GodotTransformSyncPlugin
is included in your app.
Migration Path
If you were using the add_transforms
configuration option, you can simply remove it. Transform components will be automatically added if you include the transform plugin.
Before (v0.8.x)
#![allow(unused)] fn main() { app.add_plugins(GodotSceneTreePlugin { add_transforms: true, add_child_relationship: true, }); }
After (v0.9.0)
#![allow(unused)] fn main() { // Transform components are automatically added when GodotTransformSyncPlugin is included app.add_plugins(GodotSceneTreePlugin { add_child_relationship: true, }); // Add the transform plugin to get automatic transform components app.add_plugins(GodotTransformSyncPlugin::default()); }