- 0.5 to 0.6
- Rust 2021 now required
- "AppBuilder" was merged into "App"
- The "Component" trait now needs to be derived
- Setting the Component Storage is now done in "Component" Trait
- Calling ".system()" on a system is now optional
- ".single()" and ".single_mut()" are now infallible
- "Light" and "LightBundle" are now "PointLight" and "PointLightBundle"
- System Param Lifetime Split
- QuerySet declare "QueryState" instead of "Query"
- "Input<T>.update()" is renamed to "Input<T>.clear()"
- "SystemState" is now "SystemMeta"
- Vector casting functions are now named to match return type
- StandardMaterial's "roughness" is renamed to "perceptual_roughness"
- SpriteBundle and Sprite
- Visible is now Visibility
Migration Guide: 0.5 to 0.6
Rust 2021 now required #
Bevy has been updated to use Rust 2021. This means we can take advantage of the new Cargo feature resolver by default (which both Bevy and the new wgpu version require). Make sure you update your crates to Rust 2021 or you will need to manually enable the new feature resolver with `resolver = "2" in your Cargo.toml.
[package]
name = "your_app"
version = "0.1.0"
edition = "2021"
Note that "virtual Cargo workspaces" still need to manually define resolver = "2"
, even in Rust 2021. Refer to the Rust 2021 documentation for details.
[workspace]
resolver = "2" # Important! wgpu/Bevy needs this!
members = [ "my_crate1", "my_crate2" ]
"AppBuilder" was merged into "App" #
All functions of AppBuilder
were merged into App
.
In practice this means that you start constructing an App
by calling App::new
instead of App::build
and Plugin::build
takes a App
instead of a AppBuilder
.
// 0.5
fn main() {
App::build()
.add_plugin(SomePlugin)
.run();
}
impl Plugin for SomePlugin {
fn build(&self, app: &mut AppBuilder) {
}
}
// 0.6
fn main() {
App::new()
.add_plugin(SomePlugin)
.run();
}
impl Plugin for SomePlugin {
fn build(&self, app: &mut App) {
}
}
The "Component" trait now needs to be derived #
Bevy no longer has a blanket implementation for the Component
trait. Instead you need to derive (or manually implement) the trait for every Type that needs it.
// 0.5
struct MyComponent;
// 0.6
#[derive(Component)]
struct MyComponent;
In order to use foreign types as components, wrap them using the newtype pattern.
#[derive(Component)]
struct Cooldown(std::time::Duration);
Setting the Component Storage is now done in "Component" Trait #
The change to deriving Component
, enabled setting the Component Storage at compiletime instead of runtime.
// 0.5
appbuilder
.world
.register_component(ComponentDescriptor::new::<MyComponent>(
StorageType::SparseSet,
))
.unwrap();
// 0.6
#[derive(Component)]
#[component(storage = "SparseSet")]
struct MyComponent;
Calling ".system()" on a system is now optional #
When adding a system to Bevy it is no longer necessary to call .system()
beforehand.
// 0.5
fn main() {
App::new()
.add_system(first_system.system())
.add_system(second_system.system())
.run();
}
// 0.6
fn main() {
App::new()
.add_system(first_system)
.add_system(second_system.system())
.run();
}
System configuration Functions like .label()
or .config()
can now also be directly called on a system.
// 0.5
fn main() {
App::new()
.add_system(first_system.system().label("FirstSystem"))
.add_system(second_system.system().after("FirstSystem"))
.run();
}
// 0.6
fn main() {
App::new()
.add_system(first_system.label("FirstSystem"))
.add_system(second_system.after("FirstSystem"))
.run();
}
".single()" and ".single_mut()" are now infallible #
The functions Query::single()
and Query::single_mut()
no longer return a Result
and instead panic unless exactly one entity was found.
If you need the old behavior you can use the fallible [Query::get_single()
] and [Query_get_single_mut()
] instead.
// 0.5
fn player_system(query: Query<&Transform, With<Player>>) {
let player_position = query.single().unwrap();
// do something with player_position
}
// 0.6
fn player_system_infallible(query: Query<&Transform, With<Player>>) {
let player_position = query.single();
// do something with player_position
}
fn player_system_fallible(query: Query<&Transform, With<Player>>) {
let player_position = query.get_single().unwrap();
// do something with player_position
}
"Light" and "LightBundle" are now "PointLight" and "PointLightBundle" #
// 0.5
commands.spawn_bundle(LightBundle {
light: Light {
color: Color::rgb(1.0, 1.0, 1.0),
depth: 0.1..50.0,
fov: f32::to_radians(60.0),
intensity: 200.0,
range: 20.0,
},
..Default::default()
});
// 0.6
commands.spawn_bundle(PointLightBundle {
light: PointLight {
color: Color::rgb(1.0, 1.0, 1.0),
intensity: 200.0,
range: 20.0,
},
..Default::default()
});
The Light
and LightBundle
types were renamed to PointLight
and PointLightBundle
to more clearly communicate the behavior of the Light Source. At the same time the fov
and depth
fields were removed from PointLight
as they were unused.
System Param Lifetime Split #
The Lifetime of SystemParam
was split in two separate Lifetimes.
// 0.5
type SystemParamAlias<'a> = (Res<'a, AssetServer>, Query<'a, &'static Transform>, Local<'a, i32>);
#[derive(SystemParam)]
struct SystemParamDerive<'a> {
res: Res<'a, AssetServer>,
query: Query<'a, &Transform>,
local: Local<'a, i32>,
}
// 0.6
type SystemParamAlias<'w, 's> = (Res<'w, AssetServer>, Query<'w, 's, &'static Transform>, Local<'s, i32>);
#[derive(SystemParam)]
struct SystemParamDerive<'w, 's> {
res: Res<'w, AssetServer>,
query: Query<'w, 's, &'static Transform>,
local: Local<'s, i32>,
}
QuerySet declare "QueryState" instead of "Query" #
Due to the System Param Lifetime Split, QuerySet
system parameters now need to specify their Queries with QueryState
instead of Query
.
// 0.5
fn query_set(mut queries: QuerySet<(Query<&mut Transform>, Query<&Transform>)>) {
}
// 0.6
fn query_set(mut queries: QuerySet<(QueryState<&mut Transform>, QueryState<&Transform>)>) {
}
"Input<T>.update()" is renamed to "Input<T>.clear()" #
The Input::update
function was renamed to Input::clear
.
"SystemState" is now "SystemMeta" #
The struct formerly known as SystemState
, which stores the metadata of a System, was renamed to SystemMeta
.
This was done to accommodate the new SystemState
which allows easier cached access to SystemParam
outside of a regular System.
Vector casting functions are now named to match return type #
The casting functions for IVec2
, DVec2
, UVec2
, and Vec2
have all been changed from being named after their inner elements' cast target to what the entire "Vec" is being casted into. This affects all the different dimensions of the math vectors (i.e., Vec2
, Vec3
and Vec4
).
// 0.5
let xyz: Vec3 = Vec3::new(0.0, 0.0, 0.0);
let xyz: IVec3 = xyz.as_i32();
// 0.6
let xyz: Vec3 = Vec3::new(0.0, 0.0, 0.0);
let xyz: IVec3 = xyz.as_ivec3();
StandardMaterial's "roughness" is renamed to "perceptual_roughness" #
The StandardMaterial
field roughness
was renamed to perceptual_roughness
.
SpriteBundle and Sprite #
The SpriteBundle
bundle type now uses a texture
handle rather than a material
. The color
field of the material is now directly available inside of the Sprite
struct, which also had its resize_mode
field replaced with a custom_size
. The following example shows how to spawn a tinted sprite at a particular size. For simpler cases, check out the updated sprite and rect examples.
// 0.5
SpriteBundle {
sprite: Sprite {
size: Vec2::new(256.0, 256.0),
resize_mode: SpriteResizeMode::Manual,
..Default::default()
},
material: materials.add(ColorMaterial {
color: Color::RED,
texture: Some(asset_server.load("branding/icon.png")),
}),
..Default::default()
}
// 0.6
SpriteBundle {
sprite: Sprite {
custom_size: Some(Vec2::new(256.0, 256.0)),
color: Color::RED,
..Default::default()
},
texture: asset_server.load("branding/icon.png"),
..Default::default()
}
Visible is now Visibility #
The Visible
struct, which is used in a number of components to set visibility, was renamed to Visibility
. Additionally, the field is_transparent
was removed from the struct. For 3D, transparency can be set using the alpha_mode
field on a material. Transparency is now automatically enabled for all objects in 2D.
// 0.5
let material_handle = materials.add(StandardMaterial {
base_color_texture: Some(texture.clone()),
..Default::default()
});
commands.spawn_bundle(PbrBundle {
material: material_handle,
visible: Visible {
is_visible: true,
is_transparent: true,
},
..Default::default()
});
// 0.6
let material_handle = materials.add(StandardMaterial {
base_color_texture: Some(texture.clone()),
alpha_mode: AlphaMode::Blend,
..Default::default()
});
commands.spawn_bundle(PbrBundle {
material: material_handle,
visibility: Visibility {
is_visible: true,
},
..Default::default()
});