- 0.8 to 0.9
- Make Resource trait opt-in, requiring #[derive(Resource)] V2
- Plugins own their settings. Rework PluginGroup trait.
- Use plugin setup for resource only used at setup time
- Remove AssetServer::watch_for_changes()
- Spawn now takes a Bundle
- Accept Bundles for insert and remove. Deprecate insert/remove_bundle
- Implement Bundle for Component. Use Bundle tuples for insertion
- Replace the bool argument of Timer with TimerMode
- Add global time scaling
- Change UI coordinate system to have origin at top left corner
- Rename UiColor to BackgroundColor
- Make the default background color of NodeBundle transparent
- Clarify bevy::ui::Node field and documentation
- Remove Size and UiRect generics
- Remove margins.rs
- Move Size to bevy_ui
- Move Rect to bevy_ui and rename it to UiRect
- Move sprite::Rect into bevy_math
- Exclusive Systems Now Implement System. Flexible Exclusive System Params
- Merge TextureAtlas::from_grid_with_padding into TextureAtlas::from_grid through option arguments
- Rename play to start and add new play method that won't overwrite the existing animation if it's already playing
- Change gamepad.rs tuples to normal structs
- Add getters and setters for InputAxis and ButtonSettings
- Add GamepadInfo, expose gamepad names
- Gamepad type is Copy; do not require / return references to it in Gamepads API
- Update wgpu to 0.14.0, naga to 0.10.0, winit to 0.27.4, raw-window-handle to 0.5.0, ndk to 0.7
- Support monitor selection for all window modes.
- Rename system chaining to system piping
- Add associated constant IDENTITY to Transform and friends.
- Rename Transform::mul_vec3 to transform_point and improve docs
- Remove Transform::apply_non_uniform_scale
- Remove face_toward.rs
- Replace WorldQueryGats trait with actual gats
- Add a method for accessing the width of a Table
- Make Handle::<T> field id private, and replace with a getter
- Add TimeUpdateStrategy resource for manual Time updating
- Add methods for silencing system-order ambiguity warnings
- Remove unused DepthCalculation enum
- Make raw_window_handle field in Window and ExtractedWindow an Option.
- Fix inconsistent children removal behavior
- Entity's “ID” should be named “index” instead
- Remove ExactSizeIterator from QueryCombinationIter
- Query filter types must be ReadOnlyWorldQuery
- Add pop method for List trait.
- Remove an outdated workaround for impl Trait
- Add a change detection bypass and manual control over change ticks
- Make internal struct ShaderData non-pub
- Make Children constructor pub(crate).
- Rename Handle::as_weak() to cast_weak()
- Remove Sync bound from Local
- Add FromWorld bound to T in Local<T>
- Swap out num_cpus for std::thread::available_parallelism
- Changed diagnostics from seconds to milliseconds
- Add Exponential Moving Average into diagnostics
- Nested spawns on scope
- Extract Resources into their own dedicated storage
- Clean up Fetch code
- Rename ElementState to ButtonState
- Fix incorrect and unnecessary normal-mapping code
- Scene serialization format improvements from #6354, #6345, and #5723
- Derive Reflect + FromReflect for input types
- Relax bounds on Option<T>
- Remove ReflectMut in favor of Mut<dyn Reflect>
- remove blanket Serialize + Deserialize requirement for Reflect on generic types
- Utility methods for Val
- Allow passing glam vector types as vertex attributes
Migration Guide: 0.8 to 0.9
Before migrating make sure to run rustup update
Bevy relies heavily on improvements in the Rust language and compiler. As a result, the Minimum Supported Rust Version (MSRV) is "the latest stable release" of Rust.
Make Resource
trait opt-in, requiring #[derive(Resource)]
V2 #
Add #[derive(Resource)]
to all types you are using as a resource.
If you are using a third party type as a resource, wrap it in a tuple struct to bypass orphan rules. Consider deriving Deref
and DerefMut
to improve ergonomics.
ClearColor
no longer implements Component
. Using ClearColor
as a component in 0.8 did nothing. Use the ClearColorConfig
in the Camera3d
and Camera2d
components instead.
Plugins own their settings. Rework PluginGroup trait. #
The WindowDescriptor
settings have been moved from a resource to WindowPlugin::window
:
// Old (Bevy 0.8)
app
.insert_resource(WindowDescriptor {
width: 400.0,
..default()
})
.add_plugins(DefaultPlugins)
// New (Bevy 0.9)
app.add_plugins(DefaultPlugins.set(WindowPlugin {
window: WindowDescriptor {
width: 400.0,
..default()
},
..default()
}))
The AssetServerSettings
resource has been removed in favor of direct AssetPlugin
configuration:
// Old (Bevy 0.8)
app
.insert_resource(AssetServerSettings {
watch_for_changes: true,
..default()
})
.add_plugins(DefaultPlugins)
// New (Bevy 0.9)
app.add_plugins(DefaultPlugins.set(AssetPlugin {
watch_for_changes: true,
..default()
}))
add_plugins_with
has been replaced by add_plugins
in combination with the builder pattern:
// Old (Bevy 0.8)
app.add_plugins_with(DefaultPlugins, |group| group.disable::<AssetPlugin>());
// New (Bevy 0.9)
app.add_plugins(DefaultPlugins.build().disable::<AssetPlugin>());
PluginGroupBuilder
and the PluginGroup
trait have also been reworked.
// Old (Bevy 0.8)
impl PluginGroup for HelloWorldPlugins {
fn build(&mut self, group: &mut PluginGroupBuilder) {
group.add(PrintHelloPlugin).add(PrintWorldPlugin);
}
}
// New (Bevy 0.9)
impl PluginGroup for HelloWorldPlugins {
fn build(self) -> PluginGroupBuilder {
PluginGroupBuilder::start::<Self>()
.add(PrintHelloPlugin)
.add(PrintWorldPlugin)
}
}
Use plugin setup for resource only used at setup time #
The LogSettings
settings have been moved from a resource to LogPlugin
configuration:
// Old (Bevy 0.8)
app
.insert_resource(LogSettings {
level: Level::DEBUG,
filter: "wgpu=error,bevy_render=info,bevy_ecs=trace".to_string(),
})
.add_plugins(DefaultPlugins)
// New (Bevy 0.9)
app.add_plugins(DefaultPlugins.set(LogPlugin {
level: Level::DEBUG,
filter: "wgpu=error,bevy_render=info,bevy_ecs=trace".to_string(),
}))
The ImageSettings
settings have been moved from a resource to ImagePlugin
configuration:
// Old (Bevy 0.8)
app
.insert_resource(ImageSettings::default_nearest())
.add_plugins(DefaultPlugins)
// New (Bevy 0.9)
app.add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))
The DefaultTaskPoolOptions
settings have been moved from a resource to CorePlugin::task_pool_options
:
// Old (Bevy 0.8)
app
.insert_resource(DefaultTaskPoolOptions::with_num_threads(4))
.add_plugins(DefaultPlugins)
// New (Bevy 0.9)
app.add_plugins(DefaultPlugins.set(CorePlugin {
task_pool_options: TaskPoolOptions::with_num_threads(4),
}))
Remove AssetServer::watch_for_changes()
#
AssetServer::watch_for_changes()
was removed. Instead, set it directly on the AssetPlugin
.
app
.add_plugin(DefaultPlugins.set(AssetPlugin {
watch_for_changes: true,
..default()
}))
Spawn now takes a Bundle #
// Old (0.8):
commands
.spawn()
.insert_bundle((A, B, C));
// New (0.9)
commands.spawn((A, B, C));
// Old (0.8):
commands.spawn_bundle((A, B, C));
// New (0.9)
commands.spawn((A, B, C));
// Old (0.8):
let entity = commands.spawn().id();
// New (0.9)
let entity = commands.spawn_empty().id();
// Old (0.8)
let entity = world.spawn().id();
// New (0.9)
let entity = world.spawn_empty().id();
Accept Bundles for insert and remove. Deprecate insert
/remove_bundle
#
Replace insert_bundle
with insert
:
// Old (0.8)
commands.spawn().insert_bundle(SomeBundle::default());
// New (0.9)
commands.spawn_empty().insert(SomeBundle::default());
Replace remove_bundle
with remove
:
// Old (0.8)
commands.entity(some_entity).remove_bundle::<SomeBundle>();
// New (0.9)
commands.entity(some_entity).remove::<SomeBundle>();
Replace remove_bundle_intersection
with remove_intersection
:
// Old (0.8)
world.entity_mut(some_entity).remove_bundle_intersection::<SomeBundle>();
// New (0.9)
world.entity_mut(some_entity).remove_intersection::<SomeBundle>();
Consider consolidating as many operations as possible to improve ergonomics and cut down on archetype moves:
// Old (0.8)
commands.spawn()
.insert_bundle(SomeBundle::default())
.insert(SomeComponent);
// New (0.9) - Option 1
commands.spawn_empty().insert((
SomeBundle::default(),
SomeComponent,
))
// New (0.9) - Option 2
commands.spawn((
SomeBundle::default(),
SomeComponent,
))
Implement Bundle
for Component
. Use Bundle
tuples for insertion #
The #[bundle]
attribute is no longer required when deriving Bundle
for nested bundles.
#[derive(Bundle)]
struct PlayerBundle {
#[bundle] // Remove this line
sprite_bundle: SpriteBundle,
collider: Collider,
}
Replace the bool
argument of Timer
with TimerMode
#
- Replace
Timer::new(duration, false)
withTimer::new(duration, TimerMode::Once)
. - Replace
Timer::new(duration, true)
withTimer::new(duration, TimerMode::Repeating)
. - Replace
Timer::from_seconds(seconds, false)
withTimer::from_seconds(seconds, TimerMode::Once)
. - Replace
Timer::from_seconds(seconds, true)
withTimer::from_seconds(seconds, TimerMode::Repeating)
. - Change
timer.repeating()
totimer.mode() == TimerMode::Repeating
.
Add global time scaling #
Some Time
methods were renamed for consistency.
The values returned by most methods are now scaled by a value optionally set with set_relative_speed
. Most systems should continue to use these scaled values. If you need unscaled time, use the new methods prefixed with raw_
.
// Old (Bevy 0.8)
let dur: Duration = time.time_since_startup();
let secs: f32 = time.time_since_startup().as_secs_f32();
let secs: f64 = time.seconds_since_startup();
// New (Bevy 0.9)
let dur: Duration = time.elapsed();
let secs: f32 = time.elapsed_seconds();
let secs: f64 = time.elapsed_seconds_f64();
Change UI coordinate system to have origin at top left corner #
All flex layout should be inverted (ColumnReverse => Column, FlexStart => FlexEnd, WrapReverse => Wrap) System where dealing with cursor position should be changed to account for cursor position being based on the top left instead of bottom left
Rename UiColor
to BackgroundColor
#
UiColor
has been renamed to BackgroundColor
. This change affects NodeBundle
, ButtonBundle
and ImageBundle
. In addition, the corresponding field on ExtractedUiNode
has been renamed to background_color
for consistency.
Make the default background color of NodeBundle
transparent #
If you want a NodeBundle
with a white background color, you must explicitly specify it:
// Old (Bevy 0.8)
let node = NodeBundle {
..default()
}
// New (Bevy 0.9)
let node = NodeBundle {
background_color: Color::WHITE.into(),
..default()
}
Clarify bevy::ui::Node
field and documentation #
All references to the old size
name has been changed, to access bevy::ui::Node
size
field use calculated_size
Remove Size
and UiRect
generics #
The generic T
of Size
and UiRect
got removed and instead they both now always use Val
. If you used a Size<f32>
consider replacing it with a Vec2
which is way more powerful.
Remove margins.rs
#
The Margins
type got removed. To migrate you just have to change every occurrence of Margins
to UiRect
.
Move Size
to bevy_ui
#
The Size
type got moved from bevy::math
to bevy::ui
. To migrate you just have to import bevy::ui::Size
instead of bevy::math::Math
or use the bevy::prelude
instead.
Move Rect
to bevy_ui
and rename it to UiRect
#
The Rect
type got renamed to UiRect
. To migrate you just have to change every occurrence of Rect
to UiRect
.
Move sprite::Rect
into bevy_math
#
The bevy::sprite::Rect
type moved to the math utility crate as bevy::math::Rect
. You should change your imports from use bevy::sprite::Rect
to use bevy::math::Rect
.
Exclusive Systems Now Implement System
. Flexible Exclusive System Params #
Calling .exclusive_system()
is no longer required (or supported) for converting exclusive system functions to exclusive systems:
// Old (0.8)
app.add_system(some_exclusive_system.exclusive_system());
// New (0.9)
app.add_system(some_exclusive_system);
Converting “normal” parallel systems to exclusive systems is done by calling the exclusive ordering apis:
// Old (0.8)
app.add_system(some_system.exclusive_system().at_end());
// New (0.9)
app.add_system(some_system.at_end());
Query state in exclusive systems can now be cached via ExclusiveSystemParams, which should be preferred for clarity and performance reasons:
// Old (0.8)
fn some_system(world: &mut World) {
let mut transforms = world.query::<&Transform>();
for transform in transforms.iter(world) {
}
}
// New (0.9)
fn some_system(world: &mut World, transforms: &mut QueryState<&Transform>) {
for transform in transforms.iter(world) {
}
}
The IntoExclusiveSystem
trait was removed. Use IntoSystem
instead.
The ExclusiveSystemDescriptorCoercion
trait was removed. You can delete any imports of it.
Merge TextureAtlas::from_grid_with_padding into TextureAtlas::from_grid through option arguments #
TextureAtlas::from_grid_with_padding
was merged into from_grid
which takes two additional parameters for padding and an offset.
// 0.8
TextureAtlas::from_grid(texture_handle, Vec2::new(24.0, 24.0), 7, 1);
// 0.9
TextureAtlas::from_grid(texture_handle, Vec2::new(24.0, 24.0), 7, 1, None, None)
// 0.8
TextureAtlas::from_grid_with_padding(texture_handle, Vec2::new(24.0, 24.0), 7, 1, Vec2::new(4.0, 4.0));
// 0.9
TextureAtlas::from_grid(texture_handle, Vec2::new(24.0, 24.0), 7, 1, Some(Vec2::new(4.0, 4.0)), None)
Rename play
to start
and add new play
method that won't overwrite the existing animation if it's already playing #
If you were using play
to restart an animation that was already playing, that functionality has been moved to start
. Now, play
won’t have any effect if the requested animation is already playing.
Change gamepad.rs
tuples to normal structs #
The Gamepad
, GamepadButton
, GamepadAxis
, GamepadEvent
and GamepadEventRaw
types are now normal structs instead of tuple structs and have a new()
function. To migrate change every instantiation to use the new()
function instead and use the appropriate field names instead of .0
and .1
.
Add getters and setters for InputAxis
and ButtonSettings
#
AxisSettings
now has a new()
, which may return an AxisSettingsError
. AxisSettings
fields made private; now must be accessed through getters and setters. There’s a dead zone, from .deadzone_upperbound()
to .deadzone_lowerbound()
, and a live zone, from .deadzone_upperbound()
to .livezone_upperbound()
and from .deadzone_lowerbound()
to .livezone_lowerbound()
. AxisSettings
setters no longer panic. ButtonSettings
fields made private; now must be accessed through getters and setters. ButtonSettings
now has a new()
, which may return a ButtonSettingsError
.
Add GamepadInfo, expose gamepad names #
- Pattern matches on
GamepadEventType::Connected
will need to be updated, as the form of the variant has changed. - Code that requires
GamepadEvent
,GamepadEventRaw
orGamepadEventType
to beCopy
will need to be updated.
Gamepad
type is Copy
; do not require / return references to it in Gamepads
API #
Gamepads::iter
now returns an iterator ofGamepad
. rather than an iterator of&Gamepad
.Gamepads::contains
now accepts aGamepad
, rather than a&Gamepad
.
Update wgpu
to 0.14.0, naga
to 0.10.0
, winit
to 0.27.4, raw-window-handle
to 0.5.0, ndk
to 0.7 #
Adjust usage of bevy_window::WindowDescriptor
’s cursor_locked
to cursor_grab_mode
, and adjust its type from bool
to bevy_window::CursorGrabMode
.
Support monitor selection for all window modes. #
MonitorSelection
was moved out of WindowPosition::Centered
, into WindowDescriptor
. MonitorSelection::Number
was renamed to MonitorSelection::Index
.
// Before
.insert_resource(WindowDescriptor {
position: WindowPosition::Centered(MonitorSelection::Number(1)),
..default()
})
// After
.add_plugins(DefaultPlugins.set(WindowPlugin {
window: WindowDescriptor {
monitor: MonitorSelection::Index(1),
position: WindowPosition::Centered,
..default()
},
..default()
}))
Window::set_position
now takes a MonitorSelection
as argument.
window.set_position(MonitorSelection::Current, position);
Rename system chaining to system piping #
The .chain(handler_system)
method on systems is now .pipe(handler_system)
. The IntoChainSystem
trait is now IntoPipeSystem
, and the ChainSystem
struct is now PipeSystem
.
Add associated constant IDENTITY
to Transform
and friends. #
The method identity()
on Transform
, GlobalTransform
and TransformBundle
has been removed. Use the associated constant IDENTITY
instead.
Rename Transform::mul_vec3
to transform_point
and improve docs #
Transform::mul_vec3
has been renamed to transform_point
.
Remove Transform::apply_non_uniform_scale
#
Transform::apply_non_uniform_scale
has been removed. It can be replaced with the following snippet:
transform.scale *= scale_factor;
Remove face_toward.rs
#
The FaceToward
trait got removed. To migrate you just have to change every occurrence of Mat4::face_toward
to Mat4::look_at_rh
.
Replace WorldQueryGats
trait with actual gats #
Replace usage of WorldQueryGats
assoc types with the actual gats on WorldQuery
trait
Add a method for accessing the width of a Table
#
Any use of Table::len
should now be Table::entity_count
. Any use of Table::capacity
should now be Table::entity_capacity
.
Make Handle::<T>
field id private, and replace with a getter #
If you were accessing the value handle.id
, you can now do so with handle.id()
Add TimeUpdateStrategy
resource for manual Time
updating #
Changes the value reported by time.delta()
on startup.
Before it would be [0, 0, correct]
and this PR changes it to be [0, "approximately the time between the time_system and present_frame", correct]
.
Add methods for silencing system-order ambiguity warnings #
Ambiguity sets have been replaced with a simpler API.
// These systems technically conflict, but we don't care which order they run in.
fn jump_on_click(mouse: Res<Input<MouseButton>>, mut transforms: Query<&mut Transform>) { ... }
fn jump_on_spacebar(keys: Res<Input<KeyCode>>, mut transforms: Query<&mut Transform>) { ... }
// Old (Bevy 0.8)
#[derive(AmbiguitySetLabel)]
struct JumpSystems;
app
.add_system(jump_on_click.in_ambiguity_set(JumpSystems))
.add_system(jump_on_spacebar.in_ambiguity_set(JumpSystems));
// New (Bevy 0.9)
app
.add_system(jump_on_click.ambiguous_with(jump_on_spacebar))
.add_system(jump_on_spacebar);
Remove unused DepthCalculation enum #
Remove references to bevy_render::camera::DepthCalculation
, such as use bevy_render::camera::DepthCalculation
. Remove depth_calculation
fields from Projections.
Make raw_window_handle
field in Window
and ExtractedWindow
an Option
. #
Window::raw_window_handle()
now returns Option<RawWindowHandleWrapper>
.
Fix inconsistent children removal behavior #
- Queries with
Changed<Children>
will no longer match entities that had all of their children removed usingremove_children
. RemovedComponents<Children>
will now contain entities that had all of their children removed usingremove_children
.
Entity
's “ID” should be named “index” instead #
The Entity::id()
method was renamed to Entity::index()
.
Remove ExactSizeIterator
from QueryCombinationIter
#
len
is no longer implemented for QueryCombinationIter
. You can get the same value with size_hint().0
, but be aware that values exceeding usize::MAX
will be returned as usize::MAX
.
Query
filter types must be ReadOnlyWorldQuery
#
Query filter (F
) generics are now bound by ReadOnlyWorldQuery
, rather than WorldQuery
. If for some reason you were requesting Query<&A, &mut B>
, please use Query<&A, With<B>>
instead.
Add pop
method for List
trait. #
Any custom type that implements the List
trait will now need to implement the pop
method.
Remove an outdated workaround for impl Trait
#
The methods Schedule::get_stage
and get_stage_mut
now accept impl StageLabel
instead of &dyn StageLabel
.
Add a change detection bypass and manual control over change ticks #
Add the Inner
associated type and new methods to any type that you’ve implemented DetectChanges
for.
Make internal struct ShaderData
non-pub
#
Removed ShaderData
from the public API, which was only ever used internally. No public function was using it so there should be no need for any migration action.
Make Children
constructor pub(crate)
. #
Children::with()
is now renamed Children::from_entities()
and is now pub(crate)
Rename Handle::as_weak() to cast_weak() #
- Rename
Handle::as_weak
uses toHandle::cast_weak
The method now properly sets the associated type uuid if the handle is a direct reference (e.g. not a reference to an AssetPath
), so adjust you code accordingly if you relied on the previous behavior.
Remove Sync
bound from Local
#
Any code relying on Local<T>
having T: Resource
may have to be changed, but this is unlikely.
Add FromWorld
bound to T
in Local<T>
#
It might be possible for references to Local
s without T: FromWorld
to exist, but these should be exceedingly rare and probably dead code. In the event that one of these is encountered, the easiest solutions are to delete the code or wrap the inner T
in an Option
to allow it to be default constructed to None
.
This may also have other smaller implications (such as Debug
representation), but serialization is probably the most prominent.
Swap out num_cpus
for std::thread::available_parallelism
#
bevy_tasks::logical_core_count
and bevy_tasks::physical_core_count
have been removed. logical_core_count
has been replaced with bevy_tasks::available_parallelism
, which works identically. If bevy_tasks::physical_core_count
is required, the num_cpus
crate can be used directly, as these two were just aliases for num_cpus
APIs.
Changed diagnostics from seconds to milliseconds #
Diagnostics values are now in milliseconds. If you need seconds, simply divide it by 1000.0;
Add Exponential Moving Average into diagnostics #
LogDiagnosticsPlugin
now records the smoothed value rather than the raw value.
- For diagnostics recorded less often than every 0.1 seconds, this change to defaults will have no visible effect.
- For discrete diagnostics where this smoothing is not desirable, set a smoothing factor of 0 to disable smoothing.
- The average of the recent history is still shown when available.
Nested spawns on scope #
If you were using explicit lifetimes and Passing Scope you’ll need to specify two lifetimes now.
// 0.8
fn scoped_function<'scope>(scope: &mut Scope<'scope, ()>) {}
// 0.9
fn scoped_function<'scope>(scope: &Scope<'_, 'scope, ()>) {}
scope.spawn_local
changed to scope.spawn_on_scope
this should cover cases where you needed to run tasks on the local thread, but does not cover spawning Nonsend Futures. Spawning of NonSend futures on scope is no longer supported.
Extract Resources into their own dedicated storage #
Resources have been moved to Resources
under Storages
in World
. All code dependent on Archetype::unique_components(_mut)
should access it via world.storages().resources()
instead.
All APIs accessing the raw data of individual resources (mutable and read-only) have been removed as these APIs allowed for unsound unsafe code. All usages of these APIs should be changed to use World::{get, insert, remove}_resource
.
Clean up Fetch code #
Changed: Fetch::table_fetch
and Fetch::archetype_fetch
have been merged into a single Fetch::fetch
function.
Rename ElementState
to ButtonState
#
The ElementState
type received a rename and is now called ButtonState
. To migrate you just have to change every occurrence of ElementState
to ButtonState
.
Fix incorrect and unnecessary normal-mapping code #
prepare_normal
from the bevy_pbr::pbr_functions
shader import has been reworked.
Before:
pbr_input.world_normal = in.world_normal;
pbr_input.N = prepare_normal(
pbr_input.material.flags,
in.world_normal,
#ifdef VERTEX_TANGENTS
#ifdef STANDARDMATERIAL_NORMAL_MAP
in.world_tangent,
#endif
#endif
in.uv,
in.is_front,
);
After:
pbr_input.world_normal = prepare_world_normal(
in.world_normal,
(material.flags & STANDARD_MATERIAL_FLAGS_DOUBLE_SIDED_BIT) != 0u,
in.is_front,
);
pbr_input.N = apply_normal_mapping(
pbr_input.material.flags,
pbr_input.world_normal,
#ifdef VERTEX_TANGENTS
#ifdef STANDARDMATERIAL_NORMAL_MAP
in.world_tangent,
#endif
#endif
in.uv,
);
Scene serialization format improvements from #6354, #6345, and #5723 #
- The root of the scene is now a struct rather than a list
- Components are now a map keyed by type name rather than a list
- Type information is now omitted when possible, making scenes much more compact
Scenes serialized with Bevy 0.8 will need to be recreated, but it is possible to hand-edit scenes to match the new format.
Here's an example scene in the old and new format:
// Old (Bevy 0.8)
[
(
entity: 0,
components: [
{
"type": "bevy_transform::components::transform::Transform",
"struct": {
"translation": {
"type": "glam::vec3::Vec3",
"value": (0.0, 0.0, 0.0),
},
"rotation": {
"type": "glam::quat::Quat",
"value": (0.0, 0.0, 0.0, 1.0),
},
"scale": {
"type": "glam::vec3::Vec3",
"value": (1.0, 1.0, 1.0),
},
},
},
{
"type": "scene::ComponentB",
"struct": {
"value": {
"type": "alloc::string::String",
"value": "hello",
},
},
},
{
"type": "scene::ComponentA",
"struct": {
"x": {
"type": "f32",
"value": 1.0,
},
"y": {
"type": "f32",
"value": 2.0,
},
},
},
],
),
(
entity: 1,
components: [
{
"type": "scene::ComponentA",
"struct": {
"x": {
"type": "f32",
"value": 3.0,
},
"y": {
"type": "f32",
"value": 4.0,
},
},
},
],
),
]
// New (Bevy 0.9)
(
entities: {
0: (
components: {
"bevy_transform::components::transform::Transform": (
translation: (
x: 0.0,
y: 0.0,
z: 0.0
),
rotation: (0.0, 0.0, 0.0, 1.0),
scale: (
x: 1.0,
y: 1.0,
z: 1.0
),
),
"scene::ComponentB": (
value: "hello",
),
"scene::ComponentA": (
x: 1.0,
y: 2.0,
),
},
),
1: (
components: {
"scene::ComponentA": (
x: 3.0,
y: 4.0,
),
},
),
}
)
Derive Reflect
+ FromReflect
for input types #
Input<T>
now implementsReflect
via#[reflect]
instead of#[reflect_value]
. This means it now exposes its private fields via theReflect
trait rather than being treated as a value type. For code that relies on theInput<T>
struct being treated as a value type by reflection, it is still possible to wrap theInput<T>
type with a wrapper struct and apply#[reflect_value]
to it.- As a reminder, private fields exposed via reflection are not subject to any stability guarantees.
Relax bounds on Option<T>
#
If using Option<T>
with Bevy’s reflection API, T
now needs to implement FromReflect
rather than just Clone
. This can be achieved easily by simply deriving FromReflect
:
// OLD
#[derive(Reflect, Clone)]
struct Foo;
let reflected: Box<dyn Reflect> = Box::new(Some(Foo));
// NEW
#[derive(Reflect, FromReflect)]
struct Foo;
let reflected: Box<dyn Reflect> = Box::new(Some(Foo));
Note: You can still derive Clone
, but it’s not required in order to compile.
Remove ReflectMut
in favor of Mut<dyn Reflect>
#
- relax
T: ?Sized
bound inMut<T>
- replace all instances of
ReflectMut
withMut<dyn Reflect>
remove blanket Serialize + Deserialize
requirement for Reflect
on generic types #
.register_type
for generic types like Option<T>
, Vec<T>
, HashMap<K, V>
will no longer insert ReflectSerialize
and ReflectDeserialize
type data. Instead you need to register it separately for concrete generic types like so:
.register_type::<Option<String>>()
.register_type_data::<Option<String>, ReflectSerialize>()
.register_type_data::<Option<String>, ReflectDeserialize>()
Utility methods for Val #
It is no longer possible to use the +
, +=
, -
, or -=
operators with Val
or Size
.
Use the new try_add
and try_sub
methods instead and perform operations on Size
's height
and width
fields separately.
Allow passing glam vector types as vertex attributes #
Implementations of From<Vec<[u16; 4]>>
and From<Vec<[u8; 4]>>
for VertexAttributeValues
have been removed. I you're passing either Vec<[u16; 4]>
or Vec<[u8; 4]>
into Mesh::insert_attribute
it will now require wrapping it with right the VertexAttributeValues
enum variant.