Draft Page
- 0.14 to 0.15
- Without area
- Animation
- Make AnimationPlayer::start and ::play work accordingly to documentation
- Implement animation masks, allowing fine control of the targets that animations affect.
- Remove TransformCurve
- Impose a more sensible ordering for animation graph evaluation.
- Implement additive blending for animation graphs.
- Fix additive blending of quaternions
- Replace Handle<AnimationGraph> component with a wrapper
- Curve-based animation
- Allow animation clips to animate arbitrary properties.
- App
- Assets
- AssetServer LoadState API consistency
- Cleanup unneeded lifetimes in bevy_asset
- Replace AsyncSeek trait by AsyncSeekForward for Reader to address #12880
- bevy_asset: Improve NestedLoader API
- Remove incorrect equality comparisons for asset load error types
- Faster MeshletMesh deserialization
- Split TextureAtlasSources out of TextureAtlasLayout and make TextureAtlasLayout serializable
- Export glTF skins as a Gltf struct
- Replace bevy_utils::CowArc with atomicow
- Audio
- Color
- Core
- Cross-Cutting
- Diagnostics
- ECS
- Created an EventMutator for when you want to mutate an event before reading
- Update trigger_observers to operate over slices of data
- Simplify run conditions
- Require &mut self for World::increment_change_tick
- Add FilteredAccess::empty and simplify the implementation of update_component_access for AnyOf/Or
- Track source location in change detection
- Make QueryState::transmute&co validate the world of the &Components used
- Fix soudness issue with Conflicts involving read_all and write_all
- Support more kinds of system params in buildable systems.
- Add query reborrowing
- Rename Commands::register_one_shot_system -> register_system
- Make QueryFilter an unsafe trait
- EntityRef/Mut get_components (immutable variants only)
- Removed Type Parameters from Observer
- Remove redundant information and optimize dynamic allocations in Table
- Rename push children to add children
- Rename Add to Queue for methods with deferred semantics
- change return type of World::resource_ref to Ref
- Support systems that take references as input
- Follow up to cached run_system
- List components for QueryEntityError::QueryDoesNotMatch
- Rename init_component & friends
- System param validation for observers, system registry and run once
- 15540 Make World::flush_commands private
- Enable EntityRef::get_by_id and friends to take multiple ids and get multiple pointers back
- Rename observe to observe_entity on EntityWorldMut
- Deprecate Events::oldest_id
- Allow World::entity family of functions to take multiple entities and get multiple references back
- Deprecate get_or_spawn
- bevy_ecs: Special-case Entity::PLACEHOLDER formatting
- Minimal Bubbling Observers
- Change ReflectMapEntities to operate on components before insertion
- Bubbling observers traversal should use query data
- Migrate bevy picking
- feat: Add World::get_reflect() and World::get_reflect_mut()
- Use crate: disqualified
- Migrate visibility to required components
- Migrate fog volumes to required components
- Migrate meshes and materials to required components
- Migrate motion blur, TAA, SSAO, and SSR to required components
- Migrate cameras to required components
- Synchronize removed components with the render world
- Migrate reflection probes to required components
- Migrate bevy_transform to required components
- Deprecate SpatialBundle
- Gizmos
- Making bevy_render an optional dependency for bevy_gizmos
- Consistency between Wireframe2d and Wireframe
- Fix Gizmos warnings and doc errors when a subset of features are selected
- Fix arc_2d Gizmos
- Use Isometry in bevy_gizmos wherever we can
- Improve the gizmo for Plane3d, reusing grid
- Switch rotation & translation in grid gizmos
- Make TrackedRenderPass::set_vertex_buffer aware of slice size
- Hierarchy
- Input
- Math
- Picking
- Reflection
- bevy_reflect: Nested TypeInfo getters
- Implement FromIterator/IntoIterator for dynamic types
- Dedicated Reflect implementation for Set-like things
- bevy_reflect: Add Type type
- bevy_reflect: Refactor serde module
- bevy_reflect: Add DynamicTyped trait
- bevy_reflect: Replace "value" terminology with "opaque"
- Remove Return::Unit variant
- Make drain take a mutable borrow instead of Box<Self> for reflected Map, List, and Set.
- Serialize and deserialize tuple struct with one field as newtype struct
- Use FromReflect when extracting entities in dynamic scenes
- move ShortName to bevy_reflect
- Rendering
- Lighting Should Only hold Vec<Entity> instead of TypeId<Vec<Entity>>
- Add support for skybox transformation
- Allow volumetric fog to be localized to specific, optionally voxelized, regions.
- Pack multiple vertex and index arrays together into growable buffers.
- Add support for environment map transformation
- Using Cas instead of CAS #14341
- Move Msaa to component
- Add 2d opaque phase with depth buffer
- Changed Mesh::attributes* functions to return MeshVertexAttribute
- Add RenderSet::FinalCleanup for World::clear_entities
- Add feature requirement info to image loading docs
- Fix underflow panic in InitTriInfo
- Rewrite screenshots.
- Replace the wgpu_trace feature with a field in bevy_render::settings::WgpuSettings
- Refactor AsBindGroup to use a associated SystemParam.
- Meshlet software raster + start of cleanup
- Adds ShaderStorageBuffer asset
- Return Results from Camera's world/viewport conversion methods
- Replaced implicit emissive weight with default.
- Split OrthographicProjection::default into 2d & 3d (Adopted)
- Remove OrthographicProjection.scale (adopted)
- Rename rendering components for improved consistency and clarity
- Migrate lights to required components
- Fix Mesh allocator bug and reduce Mesh data copies by two
- Added visibility bitmask as an alternative SSAO method
- Split out bevy_mesh from bevy_render
- Feature-gate all image formats
- Per-meshlet compressed vertex data
- Migrate bevy_sprite to required components
- Type safe retained render world
- Move ImageLoader and CompressedImageSaver to bevy_image.
- Attempt to remove component from render world if not extracted.
- Improve API for scaling orthographic cameras
- Fix UI texture atlas with offset
- use precomputed border values
- Inverse bevy_render bevy_winit dependency and move cursor to bevy_winit
- Scenes
- Send SceneInstanceReady when spawning any kind of scene
- Align Scene::write_to_world_with to match DynamicScene::write_to_world_with
- Align Scene::write_to_world_with to match DynamicScene::write_to_world_with
- Change SceneInstanceReady to trigger an observer.
- explicitly mention component in methods on DynamicSceneBuilder
- Migrate scenes to required components
- Text
- Time
- UI
- Clean up UiSystem system sets
- Fix error in bevy_ui when building without bevy_text
- Remove useless Direction field
- Rename BreakLineOn to LineBreak
- Add UI GhostNode
- Replace Handle<M: UiMaterial> component with UiMaterialHandle wrapper
- Clip to the UI node's content box
- Overflow clip margin
- Migrate UI bundles to required components
- Merge Style properties into Node. Use ComputedNode for computed properties.
- Explicitly order CameraUpdateSystem before UiSystem::Prepare
- Utils
- Windowing
Migration Guide: 0.14 to 0.15
Without area #
Fix asset_settings example regression #
This PR obviously requires no migration guide as this is just a bug-fix, but I believe that #15812 should mention that meta files needs updating. Proposal:
- Asset loader name must be updated in
.meta
files for images. Change:loader: "bevy_render::texture::image_loader::ImageLoader",
to:loader: "bevy_image::image_loader::ImageLoader",
It will fix the following error:no
AssetLoaderfound with the name 'bevy_render::texture::image_loader::ImageLoader
Remove AVIF feature #
AVIF images are no longer supported. They never really worked, and require system dependencies (libdav1d) to work correctly, so, it’s better to simply offer this support via an unofficial plugin instead as needed. The corresponding types have been removed from Bevy to account for this.
Animation #
Make AnimationPlayer::start
and ::play
work accordingly to documentation #
- PR #14546
- Animation
AnimationPlayer::start
now correspondingly to its docs restarts a running animation. AnimationPlayer::play
doesn’t reset the weight anymore.
Implement animation masks, allowing fine control of the targets that animations affect. #
- PR #15013
- Animation
- The serialized format of animation graphs has changed with the addition of animation masks. To upgrade animation graph RON files, add
mask
andmask_groups
fields as appropriate. (They can be safely set to zero.)
Remove TransformCurve
#
- PR #15598
- Animation
There is no released version that contains this, but we should make sure that TransformCurve
is excluded from the release notes for #15434 if we merge this pull request.
Impose a more sensible ordering for animation graph evaluation. #
- PR #15589
- Animation
This section is optional. If there are no breaking changes, you can delete this section.
- If this PR is a breaking change (relative to the last release of Bevy), describe how a user might need to migrate their code to support these changes
- Simply adding new functionality is not a breaking change.
- Fixing behavior that was definitely a bug, rather than a questionable design choice is not a breaking change.
Implement additive blending for animation graphs. #
- PR #15631
- Animation
- The
animgraph.ron
format has changed to accommodate the new additive blending feature. You’ll need to changeclip
fields to instances of the newAnimationNodeType
enum.
Fix additive blending of quaternions #
- PR #15662
- Animation
This PR changes the implementation of Quat: Animatable
, which was not used internally by Bevy prior to this release version. If you relied on the old behavior of additive quaternion blending in manual applications, that code will have to be updated, as the old behavior was incorrect.
Replace Handle<AnimationGraph>
component with a wrapper #
- PR #15742
- Animation
Handle<AnimationGraph>
is no longer a component. Instead, use the AnimationGraphHandle
component which contains a Handle<AnimationGraph>
.
Curve-based animation #
- PR #15434
- Animation
- Math
Most user code that does not directly deal with AnimationClip
and VariableCurve
will not need to be changed. On the other hand, VariableCurve
has been completely overhauled. If you were previously defining animation curves in code using keyframes, you will need to migrate that code to use curve constructors instead. For example, a rotation animation defined using keyframes and added to an animation clip like this:
animation_clip.add_curve_to_target(
animation_target_id,
VariableCurve {
keyframe_timestamps: vec![0.0, 1.0, 2.0, 3.0, 4.0],
keyframes: Keyframes::Rotation(vec![
Quat::IDENTITY,
Quat::from_axis_angle(Vec3::Y, PI / 2.),
Quat::from_axis_angle(Vec3::Y, PI / 2. * 2.),
Quat::from_axis_angle(Vec3::Y, PI / 2. * 3.),
Quat::IDENTITY,
]),
interpolation: Interpolation::Linear,
},
);
would now be added like this:
animation_clip.add_curve_to_target(
animation_target_id,
AnimatableKeyframeCurve::new([0.0, 1.0, 2.0, 3.0, 4.0].into_iter().zip([
Quat::IDENTITY,
Quat::from_axis_angle(Vec3::Y, PI / 2.),
Quat::from_axis_angle(Vec3::Y, PI / 2. * 2.),
Quat::from_axis_angle(Vec3::Y, PI / 2. * 3.),
Quat::IDENTITY,
]))
.map(RotationCurve)
.expect("Failed to build rotation curve"),
);
Note that the interface of AnimationClip::add_curve_to_target
has also changed (as this example shows, if subtly), and now takes its curve input as an impl AnimationCurve
. If you need to add a VariableCurve
directly, a new method add_variable_curve_to_target
accommodates that (and serves as a one-to-one migration in this regard).
For reviewers
The diff is pretty big, and the structure of some of the changes might not be super-obvious:
keyframes.rs
becameanimation_curves.rs
, andAnimationCurve
is based heavily onKeyframes
, with the adaptors also largely following suite.- The Curve API adaptor structs were moved from
bevy_math::curve::mod
into their own moduleadaptors
. There are no functional changes to how these adaptors work; this is just to make room for the specialized reflection implementations sincemod.rs
was getting kind of cramped. - The new module
gltf_curves
holds the additional curve constructions that are needed by the glTF loader. Note that the loader uses a mix of these and off-the-shelfbevy_math
curve stuff. animatable.rs
no longer holds logic related to keyframe interpolation, which is now delegated to the existing abstractions inbevy_math::curve::cores
.
Allow animation clips to animate arbitrary properties. #
- PR #15282
- Animation
- Reflection
- Animation keyframes are now an extensible trait, not an enum. Replace
Keyframes::Translation(...)
,Keyframes::Scale(...)
,Keyframes::Rotation(...)
, andKeyframes::Weights(...)
withBox::new(TranslationKeyframes(...))
,Box::new(ScaleKeyframes(...))
,Box::new(RotationKeyframes(...))
, andBox::new(MorphWeightsKeyframes(...))
respectively.
App #
Remove second generic from .add_before
, .add_after
#
- PR #14285
- App
Removed second generic from PluginGroupBuilder
methods: add_before
and add_after
.
// Before:
DefaultPlugins
.build()
.add_before::<WindowPlugin, _>(FooPlugin)
.add_after::<WindowPlugin, _>(BarPlugin)
// After:
DefaultPlugins
.build()
.add_before::<WindowPlugin>(FooPlugin)
.add_after::<WindowPlugin>(BarPlugin)
Remove need for EventLoopProxy to be NonSend #
- PR #14198
- App
EventLoopProxy
has been renamed to EventLoopProxyWrapper
and is now Send
, making it an ordinary resource.
Before:
event_loop_system(event_loop: NonSend<EventLoopProxy<MyEvent>>) {
event_loop.send_event(MyEvent);
}
After:
event_loop_system(event_loop: Res<EventLoopProxy<MyEvent>>) {
event_loop.send_event(MyEvent);
}
Remove deprecated bevy_dynamic_plugin
#
- PR #14534
- App
Dynamic plugins were deprecated in 0.14 for being unsound, and they have now been fully removed. Please consider using the alternatives listed in the bevy_dynamic_plugin
crate documentation, or worst-case scenario you may copy the code from 0.14.
Allow ordering variable timesteps around fixed timesteps #
- PR #14881
- App
run_fixed_main_schedule is no longer public. If you used to order against it, use the new dedicated RunFixedMainLoopSystem
system set instead. You can replace your usage of run_fixed_main_schedule
one for one by RunFixedMainLoopSystem::FixedMainLoop
, but it is now more idiomatic to place your systems in either RunFixedMainLoopSystem::BeforeFixedMainLoop
or RunFixedMainLoopSystem::AfterFixedMainLoop
Old:
app.add_systems(
RunFixedMainLoop,
some_system.before(run_fixed_main_schedule)
);
New:
app.add_systems(
RunFixedMainLoop,
some_system.in_set(RunFixedMainLoopSystem::BeforeFixedMainLoop)
);
Add features to switch NativeActivity
and GameActivity
usage #
- PR #12095
- App
GameActivity
is now the default activity for Android projects, replacing NativeActivity
. cargo-apk
has been replaced with cargo-ndk
since the former is not compatible with GameActivity
.
Before:
rustup target add aarch64-linux-android armv7-linux-androideabi
cargo install cargo-apk
After:
rustup target add aarch64-linux-android
cargo install cargo-ndk
Shared object files must be now built for the target architecture before launching package builds with the Gradle wrapper.
Before:
cargo apk build --package bevy_mobile_example
After:
cargo ndk -t arm64-v8a -o android_example/app/src/main/jniLibs build --package bevy_mobile_example
./android_example/gradlew build
(replace target and project name as required). Note that build output paths have changed. APK builds can be found under app/build/outputs/apk
).
Android Studio may also be used.
Bevy may require the libc++_shared.so
library to run on Android. This can be manually obtained from NDK source, or NDK describes a build.rs
approach. A suggested solution is also presented in the Bevy mobile example.
Applications that still require NativeActivity
should:
- disable default features in
Cargo.toml
- re-enable all default features except
android-game-activity
- enable the
android-native-activity
feature
Assets #
AssetServer LoadState API consistency #
- PR #15237
- Assets
Cleanup unneeded lifetimes in bevy_asset #
- PR #15546
- Assets
The traits AssetLoader
, AssetSaver
and Process
traits from bevy_asset
now use elided lifetimes. If you implement these then remove the named lifetime.
Replace AsyncSeek
trait by AsyncSeekForward
for Reader
to address #12880 #
- PR #14194
- Assets
Replace all instances of AsyncSeek
with AsyncSeekForward
in your asset reader implementations.
bevy_asset: Improve NestedLoader
API #
- PR #15509
- Assets
Code which uses bevy_asset
’s LoadContext::loader
/ NestedLoader
will see some naming changes:
untyped
is replaced bywith_unknown_type
with_asset_type
is replaced bywith_static_type
with_asset_type_id
is replaced bywith_dynamic_type
direct
is replaced byimmediate
(the opposite of “immediate” is “deferred”)
Remove incorrect equality comparisons for asset load error types #
- PR #15890
- Assets
The types bevy_asset::AssetLoadError
and bevy_asset::LoadState
no longer support equality comparisons. If you need to check for an asset’s load state, consider checking for a specific variant using LoadState::is_loaded
or the matches!
macro. Similarly, consider using the matches!
macro to check for specific variants of the AssetLoadError
type if you need to inspect the value of an asset load error in your code.
DependencyLoadState
and RecursiveDependencyLoadState
are not released yet, so no migration needed,
Faster MeshletMesh deserialization #
- PR #14193
- Assets
- Rendering
- Regenerate your
MeshletMesh
assets, as the disk format has changed, andMESHLET_MESH_ASSET_VERSION
has been bumped MeshletMesh
fields are now privateMeshletMeshSaverLoad
is now namedMeshletMeshSaverLoader
- The
Meshlet
,MeshletBoundingSpheres
, andMeshletBoundingSphere
types are now private MeshletMeshSaveOrLoadError::SerializationOrDeserialization
has been removed- Added
MeshletMeshSaveOrLoadError::WrongFileType
, match on this variant if you match onMeshletMeshSaveOrLoadError
Split TextureAtlasSources
out of TextureAtlasLayout
and make TextureAtlasLayout
serializable #
- PR #15344
- Assets
- Rendering
TextureAtlasBuilder
no longer stores a mapping back to the original images in TextureAtlasLayout
; that functionality has been added to a new struct, TextureAtlasSources
, instead. This also means that the signature for TextureAtlasBuilder::finish
has changed, meaning that calls of the form:
let (atlas_layout, image) = builder.build()?;
Will now change to the form:
let (atlas_layout, atlas_sources, image) = builder.build()?;
And instead of performing a reverse-lookup from the layout, like so:
let atlas_layout_handle = texture_atlases.add(atlas_layout.clone());
let index = atlas_layout.get_texture_index(&my_handle);
let handle = TextureAtlas {
layout: atlas_layout_handle,
index,
};
You can perform the lookup from the sources instead:
let atlas_layout = texture_atlases.add(atlas_layout);
let index = atlas_sources.get_texture_index(&my_handle);
let handle = TextureAtlas {
layout: atlas_layout,
index,
};
Additionally, TextureAtlasSources
also has a convenience method, handle
, which directly combines the index and an existing TextureAtlasLayout
handle into a new TextureAtlas
:
let atlas_layout = texture_atlases.add(atlas_layout);
let handle = atlas_sources.handle(atlas_layout, &my_handle);
Export glTF skins as a Gltf struct #
- PR #14343
- Assets
- Scenes
- Change
GltfAssetLabel::Skin(..)
toGltfAssetLabel::InverseBindMatrices(..)
.
Replace bevy_utils::CowArc
with atomicow
#
- PR #14977
- Assets
- Utils
bevy_utils::CowArc
has moved to a new crate called atomicow.
Audio #
Migrate audio to required components #
- PR #15573
- Audio
- ECS
Replace all insertions of AudioSourceBundle
, AudioBundle
, and PitchBundle
with the AudioPlayer
component. The other components required by it will now be inserted automatically.
In cases where the generics cannot be inferred, you may need to specify them explicitly. For example:
commands.spawn(AudioPlayer::<AudioSource>(asset_server.load("sounds/sick_beats.ogg")));
Color #
Update Grid Gizmo to use Color #
- PR #14886
- Color
- Gizmos
This shouldn’t be adding anything that isn’t already in a migration guide? I assume as it uses impl Into<...>
in the public interfaces that any users of these APIs shouldn’t have to make any code changes.
Core #
Rename bevy_core::name::DebugName
to bevy_core::name::NameOrEntity
#
- PR #14211
- Core
- Editor
- Rename usages of
bevy_core::name::DebugName
tobevy_core::name::NameOrEntity
Cross-Cutting #
Add core
and alloc
over std
Lints #
- PR #15281
- Cross-Cutting
The MSRV is now 1.81. Please update to this version or higher.
Remove the Component
trait implementation from Handle
#
- PR #15796
- Cross-Cutting
Handle
can no longer be used as a Component
. All existing Bevy types using this pattern have been wrapped in their own semantically meaningful type. You should do the same for any custom Handle
components your project needs.
The Handle<MeshletMesh>
component is now MeshletMesh3d
.
The WithMeshletMesh
type alias has been removed. Use With<MeshletMesh3d>
instead.
Fix floating point math #
- PR #15239
- Cross-Cutting
- Math
- Not a breaking change
- Projects should use bevy math where applicable
Add custom cursors #
- PR #14284
- Cross-Cutting
- UI
- Windowing
CursorIcon
is no longer a field inWindow
, but a separate component can be inserted to a window entity. It has been changed to an enum that can hold custom images in addition to system icons.Cursor
is renamed toCursorOptions
andcursor
field ofWindow
is renamed tocursor_options
CursorIcon
is renamed toSystemCursorIcon
Diagnostics #
Don't ignore draw errors #
- PR #13240
- Diagnostics
- Rendering
If you were using RenderCommandResult::Failure
to just ignore an error and retry later, use RenderCommandResult::Skip
instead.
This wasn’t intentional, but this PR should also help with https://github.com/bevyengine/bevy/issues/12660 since we can turn a few unwraps into error messages now.
ECS #
Created an EventMutator for when you want to mutate an event before reading #
- PR #13818
- ECS
Users currently using ManualEventReader
should use EventCursor
instead. ManualEventReader
will be removed in Bevy 0.16. Additionally, Events::get_reader
has been replaced by Events::get_cursor
.
Users currently directly accessing the Events
resource for mutation should move to EventMutator
if possible.
Update trigger_observers
to operate over slices of data #
- PR #14354
- ECS
- TBD
Simplify run conditions #
- PR #14441
- ECS
Some run conditions have been simplified.
// Before:
app.add_systems(Update, (
system_0.run_if(run_once()),
system_1.run_if(resource_changed_or_removed::<T>()),
system_2.run_if(resource_removed::<T>()),
system_3.run_if(on_event::<T>()),
system_4.run_if(any_component_removed::<T>()),
));
// After:
app.add_systems(Update, (
system_0.run_if(run_once),
system_1.run_if(resource_changed_or_removed::<T>),
system_2.run_if(resource_removed::<T>),
system_3.run_if(on_event::<T>),
system_4.run_if(any_component_removed::<T>),
));
Require &mut self
for World::increment_change_tick
#
- PR #14459
- ECS
The method World::increment_change_tick
now requires &mut self
instead of &self
. If you need to call this method but do not have mutable access to the world, consider using world.as_unsafe_world_cell_readonly().increment_change_tick()
, which does the same thing, but is less efficient than the method on World
due to requiring atomic synchronization.
fn my_system(world: &World) {
// Before
world.increment_change_tick();
// After
world.as_unsafe_world_cell_readonly().increment_change_tick();
}
Add FilteredAccess::empty
and simplify the implementation of update_component_access
for AnyOf
/Or
#
- PR #14352
- ECS
- The behaviour of
AnyOf<()>
andOr<()>
has been changed to match no archetypes rather than all archetypes to naturally match the corresponding logical operation. Consider replacing them with()
instead.
Track source location in change detection #
- PR #14034
- ECS
- Added
changed_by
field to many internal ECS functions used with change detection when thetrack_change_detection
feature flag is enabled. Use Location::caller() to provide the source of the function call.
Make QueryState::transmute
&co validate the world of the &Components
used #
- PR #14631
- ECS
QueryState::transmute
,QueryState::transmute_filtered
,QueryState::join
andQueryState::join_filtered
now take aimpl Into<UnsafeWorldCell>
instead of a&Components
Fix soudness issue with Conflicts involving read_all
and write_all
#
- PR #14579
- ECS
The get_conflicts
method of Access
now returns an AccessConflict
enum instead of simply a Vec
of ComponentId
s that are causing the access conflict. This can be useful in cases where there are no particular ComponentId
s conflicting, but instead all of them are; for example fn system(q1: Query<EntityMut>, q2: Query<EntityRef>)
Support more kinds of system params in buildable systems. #
- PR #14050
- ECS
The API for SystemBuilder
has changed. Instead of constructing a builder with a world and then adding params, you first create a tuple of param builders and then supply the world.
// Before
let system = SystemBuilder::<()>::new(&mut world)
.local::<u64>()
.builder::<Local<u64>>(|x| *x = 10)
.builder::<Query<&A>>(|builder| { builder.with::<B>(); })
.build(system);
// After
let system = (
ParamBuilder,
LocalBuilder(10),
QueryParamBuilder::new(|builder| { builder.with::<B>(); }),
)
.build_state(&mut world)
.build_system(system);
Add query reborrowing #
- PR #14690
- ECS
WorldQuery
now has an additionalshrink_fetch
method you have to implement if you were implementingWorldQuery
manually.
Rename Commands::register_one_shot_system
-> register_system
#
- PR #14910
- ECS
Commands::register_one_shot_system
has been renamed to register_system
.
Make QueryFilter an unsafe trait #
- PR #14790
- ECS
QueryFilter
is now an unsafe trait
. If you were manually implementing it, you will need to verify that the WorldQuery
implementation is read-only and then add the unsafe
keyword to the impl
.
EntityRef/Mut get_components (immutable variants only) #
- PR #15089
- ECS
- Renamed
FilteredEntityRef::components
toFilteredEntityRef::accessed_components
andFilteredEntityMut::components
toFilteredEntityMut::accessed_components
.
Removed Type Parameters from Observer
#
- PR #15151
- ECS
If you filtered for observers using Observer<A, B>
, instead filter for an Observer
.
Remove redundant information and optimize dynamic allocations in Table
#
- PR #12929
- ECS
Table
now uses ThinColumn
instead of Column
. That means that methods that previously returned Column
, will now return ThinColumn
instead.
ThinColumn
has a much more limited and low-level API, but you can still achieve the same things in ThinColumn
as you did in Column
. For example, instead of calling Column::get_added_tick
, you’d call ThinColumn::get_added_ticks_slice
and index it to get the specific added tick.
Rename push children to add children #
- PR #15196
- ECS
This section is optional. If there are no breaking changes, you can delete this section.
- If this PR is a breaking change (relative to the last release of Bevy), describe how a user might need to migrate their code to support these changes
rename any use of push_children()
to the updated add_children()
Rename Add to Queue for methods with deferred semantics #
- PR #15234
- ECS
Commands::add
andCommands::push
have been replaced withCommands::queue
.ChildBuilder::add_command
has been renamed toChildBuilder::queue_command
.
change return type of World::resource_ref
to Ref
#
- PR #15263
- ECS
Previously World::get_resource_ref::<T>
and World::resource_ref::<T>
would return a Res<T>
which was inconsistent with the rest of the World
API (notably resource_scope
). This has been fixed and the methods now return Ref<T>
.
This means it is no longer possible to get Res<T>
from World
. If you were relying on this, you should try using Ref<T>
instead since it has the same functionality.
Before
let my_resource: Res<MyResource> = world.resource_ref();
function_taking_resource(my_resource);
fn function_taking_resource(resource: Res<MyResource>) { /* ... */ }
After
let my_resource: Ref<MyResource> = world.resource_ref();
function_taking_resource(my_resource);
fn function_taking_resource(resource: Ref<MyResource>) { /* ... */ }
Support systems that take references as input #
- PR #15184
- ECS
All current explicit usages of the following types must be changed in the way specified:
SystemId<I, O>
toSystemId<In<I>, O>
System<In = T>
toSystem<In = In<T>>
IntoSystem<I, O, M>
toIntoSystem<In<I>, O, M>
Condition<M, T>
toCondition<M, In<T>>
In<Trigger<E, B>>
is no longer a valid input parameter type. UseTrigger<E, B>
directly, instead.
Follow up to cached run_system
#
- PR #15410
- ECS
IntoSystem::pipe
andIntoSystem::map
now returnIntoPipeSystem
andIntoAdapterSystem
instead ofPipeSystem
andAdapterSystem
. Most notably these types don’t implementSystem
but rather onlyIntoSystem
.
List components for QueryEntityError::QueryDoesNotMatch #
- PR #15435
- ECS
QueryEntityError
now has a lifetime. Convert it to a custom error if you need to store it.
Rename init_component & friends #
- PR #15454
- ECS
World::init_component
has been renamed toregister_component
.World::init_component_with_descriptor
has been renamed toregister_component_with_descriptor
.World::init_bundle
has been renamed toregister_bundle
.Components::init_component
has been renamed toregister_component
.Components::init_component_with_descriptor
has been renamed toregister_component_with_descriptor
.Components::init_resource
has been renamed toregister_resource
.Components::init_non_send
had been renamed toregister_non_send
.
System param validation for observers, system registry and run once #
- PR #15526
- ECS
RunSystemOnce::run_system_once
andRunSystemOnce::run_system_once_with
now return aResult<Out>
instead of justOut
15540 Make World::flush_commands private #
- PR #15553
- ECS
Enable EntityRef::get_by_id
and friends to take multiple ids and get multiple pointers back #
- PR #15593
- ECS
- The following functions now return an
Result<_, EntityComponentError>
instead of aOption<_>
:EntityRef::get_by_id
,EntityMut::get_by_id
,EntityMut::into_borrow_by_id
,EntityMut::get_mut_by_id
,EntityMut::into_mut_by_id
,EntityWorldMut::get_by_id
,EntityWorldMut::into_borrow_by_id
,EntityWorldMut::get_mut_by_id
,EntityWorldMut::into_mut_by_id
Rename observe to observe_entity on EntityWorldMut #
- PR #15616
- ECS
The observe()
method on entities has been renamed to observe_entity()
to prevent confusion about what is being observed in some cases.
Deprecate Events::oldest_id
#
- PR #15658
- ECS
- Change usages of
Events::oldest_id
toEvents::oldest_event_count
- If
Events::oldest_id
was used to get the actual oldestEventId::id
, note that the deprecated method never reliably did that in the first place as the buffers may contain no id currently.
Allow World::entity
family of functions to take multiple entities and get multiple references back #
- PR #15614
- ECS
World::get_entity
now returnsResult<_, Entity>
instead ofOption<_>
.- Use
world.get_entity(..).ok()
to return to the previous behavior.
- Use
World::get_entity_mut
andDeferredWorld::get_entity_mut
now returnResult<_, EntityFetchError>
instead ofOption<_>
.- Use
world.get_entity_mut(..).ok()
to return to the previous behavior.
- Use
Type inference for
World::entity
,World::entity_mut
,World::get_entity
,World::get_entity_mut
,DeferredWorld::entity_mut
, andDeferredWorld::get_entity_mut
has changed, and might now require the input argument’s type to be explicitly written when inside closures.The following functions have been deprecated, and should be replaced as such:
World::many_entities
->World::entity::<[Entity; N]>
World::many_entities_mut
->World::entity_mut::<[Entity; N]>
World::get_many_entities
->World::get_entity::<[Entity; N]>
World::get_many_entities_dynamic
->World::get_entity::<&[Entity]>
World::get_many_entities_mut
->World::get_entity_mut::<[Entity; N]>
- The equivalent return type has changed from
Result<_, QueryEntityError>
toResult<_, EntityFetchError>
- The equivalent return type has changed from
World::get_many_entities_dynamic_mut
->World::get_entity_mut::<&[Entity]>
- The equivalent return type has changed from
Result<_, QueryEntityError>
toResult<_, EntityFetchError>
- The equivalent return type has changed from
World::get_many_entities_from_set_mut
->World::get_entity_mut::<&EntityHashSet>
- The equivalent return type has changed from
Result<Vec<EntityMut>, QueryEntityError>
toResult<EntityHashMap<EntityMut>, EntityFetchError>
. If necessary, you can still convert theEntityHashMap
into aVec
.
- The equivalent return type has changed from
Deprecate get_or_spawn
#
- PR #15652
- ECS
If you are given an Entity
and you want to do something with it, use Commands.entity(...)
or World.entity(...)
. If instead you want to spawn something use Commands.spawn(...)
or World.spawn(...)
. If you are not sure if an entity exists, you can always use get_entity
and match on the Option<...>
that is returned.
bevy_ecs: Special-case Entity::PLACEHOLDER
formatting #
- PR #15839
- ECS
The Debug
and Display
impls for Entity
now return PLACEHOLDER
for the Entity::PLACEHOLDER
constant. If you had any code relying on these values, you may need to account for this change.
Minimal Bubbling Observers #
- PR #13991
- ECS
- Hierarchy
- Picking
- Manual implementations of
Event
should add associated typeTraverse = TraverseNone
and associated constantAUTO_PROPAGATE = false
; Trigger::new
has new fieldpropagation: &mut Propagation
which provides the bubbling state.ObserverRunner
now takes the same&mut Propagation
as a final parameter.
Change ReflectMapEntities to operate on components before insertion #
- PR #15422
- ECS
- Networking
- Scenes
- Consumers of
ReflectMapEntities
will need to callmap_entities
on values prior to inserting them into the world. - Implementors of
MapEntities
will need to remove themappings
method, which is no longer needed forReflectMapEntities
and has been removed from the trait.
Bubbling observers traversal should use query data #
- PR #15385
- ECS
- Picking
Update implementations of Traversal
.
Migrate bevy picking #
- PR #15690
- ECS
- Picking
This API hasn’t shipped yet, so I didn’t bother with a deprecation. However, for any crates tracking main the changes are as follows:
Previous api:
commands.insert(PointerBundle::new(PointerId::Mouse));
commands.insert(PointerBundle::new(PointerId::Mouse).with_location(location));
New api:
commands.insert(PointerId::Mouse);
commands.insert((PointerId::Mouse, PointerLocation::new(location)));
feat: Add World::get_reflect()
and World::get_reflect_mut()
#
- PR #14416
- ECS
- Reflection
No breaking changes, but users can use the new methods if they did it manually before.
Use crate: disqualified
#
- PR #15372
- ECS
- Reflection
- Utils
Replace references to bevy_utils::ShortName
with disqualified::ShortName
.
Migrate visibility to required components #
- PR #15474
- ECS
- Rendering
Replace all insertions of VisibilityBundle
with the Visibility
component. The other components required by it will now be inserted automatically.
Migrate fog volumes to required components #
- PR #15568
- ECS
- Rendering
Replace all insertions of FogVolumeBundle
with the Visibility
component. The other components required by it will now be inserted automatically.
Migrate meshes and materials to required components #
- PR #15524
- ECS
- Rendering
Asset handles for meshes and mesh materials must now be wrapped in the Mesh2d
and MeshMaterial2d
or Mesh3d
and MeshMaterial3d
components for 2D and 3D respectively. Raw handles as components no longer render meshes.
Additionally, MaterialMesh2dBundle
, MaterialMeshBundle
, and PbrBundle
have been deprecated. Instead, use the mesh and material components directly.
Previously:
commands.spawn(MaterialMesh2dBundle {
mesh: meshes.add(Circle::new(100.0)).into(),
material: materials.add(Color::srgb(7.5, 0.0, 7.5)),
transform: Transform::from_translation(Vec3::new(-200., 0., 0.)),
..default()
});
Now:
commands.spawn((
Mesh2d(meshes.add(Circle::new(100.0))),
MeshMaterial2d(materials.add(Color::srgb(7.5, 0.0, 7.5))),
Transform::from_translation(Vec3::new(-200., 0., 0.)),
));
If the mesh material is missing, a white default material is now used. Previously, nothing was rendered if the material was missing.
The WithMesh2d
and WithMesh3d
query filter type aliases have also been removed. Simply use With<Mesh2d>
or With<Mesh3d>
.
Migrate motion blur, TAA, SSAO, and SSR to required components #
- PR #15572
- ECS
- Rendering
MotionBlurBundle
, TemporalAntiAliasBundle
, ScreenSpaceAmbientOcclusionBundle
, and ScreenSpaceReflectionsBundle
have been deprecated in favor of the MotionBlur
, TemporalAntiAliasing
, ScreenSpaceAmbientOcclusion
, and ScreenSpaceReflections
components instead. Inserting them will now also insert the other components required by them automatically.
Migrate cameras to required components #
- PR #15641
- ECS
- Rendering
Camera2dBundle
and Camera3dBundle
have been deprecated in favor of Camera2d
and Camera3d
. Inserting them will now also insert the other components required by them automatically.
Synchronize removed components with the render world #
- PR #15582
- ECS
- Rendering
The retained render world notes should be updated to explain this edge case and SyncComponentPlugin
Migrate reflection probes to required components #
- PR #15737
- ECS
- Rendering
ReflectionProbeBundle
has been deprecated in favor of inserting the LightProbe
and EnvironmentMapLight
components directly. Inserting them will now automatically insert Transform
and Visibility
components.
Migrate bevy_transform
to required components #
- PR #14964
- ECS
- Transform
Replace all insertions of GlobalTransform
and/or TransformBundle
with Transform
alone.
Deprecate SpatialBundle #
- PR #15830
- ECS
- Transform
SpatialBundle
is now deprecated, insert Transform
and Visibility
instead which will automatically insert all other components that were in the bundle. If you do not specify these values and any other components in your spawn
/insert
call already requires either of these components you can leave that one out.
before:
commands.spawn(SpatialBundle::default());
after:
commands.spawn((Transform::default(), Visibility::default());
Gizmos #
Making bevy_render
an optional dependency for bevy_gizmos
#
- PR #14448
- Gizmos
No user-visible changes needed from the users.
Consistency between Wireframe2d
and Wireframe
#
- PR #14720
- Gizmos
Wireframe2dConfig
.default_color
type is nowColor
instead ofSrgba
. Use.into()
to convert between them.Wireframe2dColor
.color
type is nowColor
instead ofSrgba
. Use.into()
to convert between them.
Fix Gizmos warnings and doc errors when a subset of features are selected #
- PR #14887
- Gizmos
There shouldn’t be any reason to migrate, although if for some reason you use GizmoMeshConfig
and bevy_render
but not bevy_pbr
or bevy_sprite
(such that it does nothing), then you will get an error that it no longer exists.
Fix arc_2d
Gizmos #
- PR #14731
- Gizmos
- users have to adjust their usages of
arc_2d
:- before:
arc_2d(
pos,
angle,
arc_angle,
radius,
color
)
- after:
arc_2d(
// this `+ arc_angle * 0.5` quirk is only if you want to preserve the previous behavior
// with the new API.
// feel free to try to fix this though since your current calls to this function most likely
// involve some computations to counter-act that quirk in the first place
Isometry2d::new(pos, Rot2::radians(angle + arc_angle * 0.5),
arc_angle,
radius,
color
)
Use Isometry
in bevy_gizmos
wherever we can #
- PR #14676
- Gizmos
The gizmos methods function signature changes as follows:
2D
- if it took
position
&rotation_angle
before ->Isometry2d::new(position, Rot2::radians(rotation_angle))
- if it just took
position
before ->Isometry2d::from_translation(position)
- if it took
3D
- if it took
position
&rotation
before ->Isometry3d::new(position, rotation)
- if it just took
position
before ->Isometry3d::from_translation(position)
- if it took
Improve the gizmo for Plane3d
, reusing grid #
- PR #14650
- Gizmos
The optional builder methods on
gizmos.primitive_3d(&Plane3d { }, ...);
changed from
segment_length
segment_count
axis_count
to
cell_count
spacing
Switch rotation & translation in grid gizmos #
- PR #14656
- Gizmos
- Math
- Users might have to double check their already existing calls to all the
grid
methods. It should be more intuitive now though.
Make TrackedRenderPass::set_vertex_buffer aware of slice size #
- PR #14916
- Gizmos
- Rendering
TrackedRenderPass::set_vertex_buffer
function has been modified to update vertex buffers when the same buffer with the same offset is provided, but its size has changed. Some existing code may rely on the previous behavior, which did not update the vertex buffer in this scenario.
Hierarchy #
Optimize transform propagation #
- PR #14373
- Hierarchy
- Transform
This change does not introduce any breaking changes. Users of the Bevy engine will automatically benefit from this performance improvement without needing to modify their code.
Only propagate transforms entities with GlobalTransforms. #
- PR #14384
- Hierarchy
- Transform
- To avoid surprising performance pitfalls,
Transform
/GlobalTransform
propagation is no longer performed down through hierarchies where intermediate parent are missing aGlobalTransform
. To restore the previous behavior, addGlobalTransform::default
to intermediate entities.
Input #
Remove ReceivedCharacter
#
- PR #15126
- Input
ReceivedCharacter
was deprecated in 0.14 due to winit
reworking their keyboard system. It has now been fully removed. Switch to using KeyboardInput
instead.
// 0.14
fn listen_characters(events: EventReader<ReceivedCharacter>) {
for event in events.read() {
info!("{}", event.char);
}
}
// 0.15
fn listen_characters(events: EventReader<KeyboardInput>) {
for event in events.read() {
// Only check for characters when the key is pressed.
if !event.state.is_pressed() {
continue;
}
// Note that some keys such as `Space` and `Tab` won't be detected as a character.
// Instead, check for them as separate enum variants.
match &event.logical_key {
Key::Character(character) => {
info!("{} pressed.", character);
},
Key::Space => {
info!("Space pressed.");
},
_ => {},
}
}
}
Implement gamepads as entities #
- PR #12770
- Input
Gamepad input is no longer accessed using resources, instead they are entities and are accessible using the Gamepad component as long as the gamepad is connected.
Gamepads resource has been deleted, instead of using an internal id to identify gamepads you can use its Entity. Disconnected gamepads will NOT be despawned. Gamepad components that don’t need to preserve their state will be removed i.e. Gamepad component is removed, but GamepadSettings is kept. Reconnected gamepads will try to preserve their Entity id and necessary components will be re-inserted.
GamepadSettings is no longer a resource, instead it is a component attached to the Gamepad entity.
Axis For users switching from For users of The Similarly, any custom implementation of Finally, the fields of The However, if the old translation and rotation are 3d translation/rotations originating from a This discussion also applies to the The The reflection implementation for All active fields for reflected types (including lists, maps, tuples, etc.), must implement However, users implementing Additionally, custom dynamic types will need to implement the new hidden Help wanted! I’m not sure if this change is able to break code. From my understanding it shouldn’t since we just add functionality but I’m not sure yet if theres anything missing from my impl that would be normally provided by Certain type info structs now only return their item types as The following methods have been removed: Instead, access the For example: The fields on Additionally, the following types are no longer public: As well as the following traits: The reflection concept of “value type” has been replaced with a clearer “opaque type”. The following renames have been made to account for this: Additionally, declaring your own opaque types no longer uses Note that the order in which Old behavior will return The Old: New: now Changed Image format related entities are feature gated, if there are compilation errors about unknown names there are some of features in list ( The {% callout(type="info") %} At the time of writing, WGPU has not reimplemented tracing support, so WGPU tracing will not currently work. However, once WGPU has reimplemented tracing support, the steps below should be sufficient to continue generating WGPU traces. You can track the progress of WGPU tracing being reimplemented at gfx-rs/wgpu#5974. {% end %} To continue generating WGPU traces: The The following methods on Call Example: Replace all uses of with Many rendering components have been renamed for improved consistency and clarity. SSAO algorithm was changed from GTAO to VBAO (visibility bitmasks). A new field, if you were using Image formats that previously weren’t feature-gated are now feature-gated, meaning they will have to be enabled if you use them: Additionally, the Previously, these formats appeared in the enum by default, but weren’t actually enabled via the If you were individually configuring the Replace all uses of WARNING: use of With the advent of the retained render world, collections that contain references to Additionally, render phases now require specifying both the Renderers can now check Components that implement The The types of the fields border and border_radius of Before After Before After If you have a system which read It must be rewritten as an observer: Or, if you were expecting the event in relation to a specific entity or entities, as an entity observer: The following methods for Asset handles for scenes and dynamic scenes must now be wrapped in the Additionally, Previously: Now: TODO: very breaking Accessing text spans by index Text sections are now text sections on different entities in a hierarchy, Use the new Before: After: Iterating text spans Text spans are now entities in a hierarchy, so the new Doubles as #15591 migration guide. Text bundles ( Text sections were removed in favor of hierarchy-based approach. For root text entities with The APIs of This is not a breaking change for users migrating from 0.14, since When the Any code that previously relied on UI root nodes may now be children of ghost nodes, which means Let’s defer the migration guide to the required component port. I just want to yeet the Migration guide is on #15561 Style has a new field There are three associated constructor functions There is also a Move any fields set on Before: After: For any usage of the “computed node properties” that used to live on Before: After: The type parameter of If you were importing For Need a If you use the Using fn gamepad_system(
- gamepads: Res<Gamepads>,
- button_inputs: Res<ButtonInput<GamepadButton>>,
- button_axes: Res<Axis<GamepadButton>>,
- axes: Res<Axis<GamepadAxis>>,
+ gamepads: Query<&Gamepad>
) {
for gamepad in gamepads.iter() {
- if button_inputs.just_pressed(GamepadButton::new(gamepad, GamepadButtonType::South)) {
+ if gamepad.just_pressed(GamepadButton::South) {
println!("just pressed South");
}
- let right_trigger = button_axes
- .get(GamepadButton::new(
- gamepad,
- GamepadButtonType::RightTrigger2,
- ))
- .unwrap();
+ let right_trigger = gamepad.get(GamepadButton::RightTrigger2).unwrap();
if right_trigger.abs() > 0.01 {
info!("RightTrigger2 value is {}", right_trigger);
}
- let left_stick_x = axes
- .get(GamepadAxis::new(gamepad, GamepadAxisType::LeftStickX))
- .unwrap();
+ let left_stick_x = gamepad.get(GamepadAxis::LeftStickX).unwrap();
if left_stick_x.abs() > 0.01 {
info!("LeftStickX value is {}", left_stick_x);
}
}
}
Picking event ordering #
bevy_mod_picking
to bevy_picking
:On<T>
component, use .observe(|trigger: Trigger<T>|)
. You may now apply multiple handlers to the same entity using this command.bevy_picking::event::pointer_events
for current information. You may need to adjust your event handling logic accordingly.PointerCancel
has been replaced with Pointer<Canceled>
, which now has the semantics of an OS touch pointer cancel event.InputMove
and InputPress
have been merged into PointerInput
. The use remains exactly the same.EventReader
. This functionality may be re-implemented later.bevy_winit
:bevy_winit::WinitEvent
has moved to bevy_window::WindowEvent
. If this was the only thing you depended on bevy_winit
for, you should switch your dependency to bevy_window
.bevy_window
now depends on bevy_input
. The dependencies of bevy_input
are a subset of the existing dependencies for bevy_window
so this should be non-breaking.Math #
Added
new
method to Cone 3D primitive #new
method to the 3D primitive Cone struct.Disallow empty cubic and rational curves #
to_curve
method on Bevy’s cubic splines is now fallible (returning a Result
), meaning that any existing calls will need to be updated by handling the possibility of an error variant.CubicGenerator
or RationalGenerator
will need to be amended to include an Error
type and be made fallible itself.CubicCurve
and RationalCurve
are now private, so any direct constructions of these structs from segments will need to be replaced with the new CubicCurve::from_segments
and RationalCurve::from_segments
methods.Refactor Bounded2d/Bounded3d to use isometries #
Bounded2d
and Bounded3d
traits now take Isometry2d
and Isometry3d
parameters (respectively) instead of separate translation and rotation arguments. Existing calls to aabb_2d
, bounding_circle
, aabb_3d
, and bounding_sphere
will have to be changed to use isometries instead. A straightforward conversion is to refactor just by calling Isometry2d/3d::new
, as follows:// Old:
let aabb = my_shape.aabb_2d(my_translation, my_rotation);
// New:
let aabb = my_shape.aabb_2d(Isometry2d::new(my_translation, my_rotation));
Transform
or GlobalTransform
, then to_isometry
may be used instead. For example:// Old:
let bounding_sphere = my_shape.bounding_sphere(shape_transform.translation, shape_transform.rotation);
// New:
let bounding_sphere = my_shape.bounding_sphere(shape_transform.to_isometry());
from_point_cloud
construction method of Aabb2d
/BoundingCircle
/Aabb3d
/BoundingSphere
, which has similarly been altered to use isometries.Basic integration of cubic spline curves with the Curve API #
RationalCurve::domain
method has been renamed to RationalCurve::length
. Calling .domain()
on a RationalCurve
now returns its entire domain as an Interval
.Use
Dir2
/Dir3
instead of Vec2
/Vec3
for Ray2d::new
/Ray3d::new
#Ray2d::new
and Ray3d::new
now take a Dir2
and Dir3
instead of Vec2
and Vec3
respectively for the ray direction.bevy_reflect: Update
EulerRot
to match glam
0.29 #EulerRot
has been updated to align with glam
0.29. Please update any reflection-based usages accordingly.Picking #
rename Drop to bevy::picking::events::DragDrop to unclash std::ops:Drop #
Drop
to DragDrop
bevy::picking::events::Drop
is now bevy::picking::events::DragDrop
Reflection #
bevy_reflect: Nested
TypeInfo
getters #Typed
. For the majority of users this won’t have any visible impact.Reflect
manually may need to update their types to implement Typed
if they weren’t already.MaybeTyped
trait.Implement FromIterator/IntoIterator for dynamic types #
DynamicArray::from_vec
to DynamicArray::from_iter
Dedicated
Reflect
implementation for Set
-like things #Set
variants on the enums listed in the change section should probably be considered by people working with this level of the libimpl_reflect_value!
bevy_reflect: Add
Type
type #Type
instead of exposing direct methods on them.ArrayInfo::item_type_path_table
ArrayInfo::item_type_id
ArrayInfo::item_is
ListInfo::item_type_path_table
ListInfo::item_type_id
ListInfo::item_is
SetInfo::value_type_path_table
SetInfo::value_type_id
SetInfo::value_is
MapInfo::key_type_path_table
MapInfo::key_type_id
MapInfo::key_is
MapInfo::value_type_path_table
MapInfo::value_type_id
MapInfo::value_is
Type
directly using one of the new methods:ArrayInfo::item_ty
ListInfo::item_ty
SetInfo::value_ty
MapInfo::key_ty
MapInfo::value_ty
// BEFORE
let type_id = array_info.item_type_id();
// AFTER
let type_id = array_info.item_ty().id();
bevy_reflect: Refactor
serde
module #ReflectSerializer
and TypedReflectSerializer
are now private. To instantiate, the corresponding constructor must be used:// BEFORE
let serializer = ReflectSerializer {
value: &my_value,
registry: &type_registry,
};
// AFTER
let serializer = ReflectSerializer::new(&my_value, &type_registry);
ArraySerializer
EnumSerializer
ListSerializer
MapSerializer
ReflectValueSerializer
(fully removed)StructSerializer
TupleSerializer
TupleStructSerializer
DeserializeValue
(fully removed)bevy_reflect: Add
DynamicTyped
trait #Reflect
now has a supertrait of DynamicTyped
. If you were manually implementing Reflect
and did not implement Typed
, you will now need to do so.bevy_reflect: Replace "value" terminology with "opaque" #
ReflectKind::Value
→ ReflectKind::Opaque
ReflectRef::Value
→ ReflectRef::Opaque
ReflectMut::Value
→ ReflectMut::Opaque
ReflectOwned::Value
→ ReflectOwned::Opaque
TypeInfo::Value
→ TypeInfo::Opaque
ValueInfo
→ OpaqueInfo
impl_reflect_value!
→ impl_reflect_opaque!
impl_from_reflect_value!
→ impl_from_reflect_opaque!
#[reflect_value]
. This attribute has been replaced by #[reflect(opaque)]
:// BEFORE
#[derive(Reflect)]
#[reflect_value(Default)]
struct MyOpaqueType(u32);
// AFTER
#[derive(Reflect)]
#[reflect(opaque)]
#[reflect(Default)]
struct MyOpaqueType(u32);
#[reflect(opaque)]
appears does not matter.Remove
Return::Unit
variant #Return::Unit
variant; use Return::unit()
instead.Make
drain
take a mutable borrow instead of Box<Self>
for reflected Map
, List
, and Set
. #reflect::Map
, reflect::List
, and reflect::Set
all now take a &mut self
instead of a Box<Self>
. Callers of these traits should add &mut
before their boxes, and implementers of these traits should update to match.Serialize and deserialize tuple struct with one field as newtype struct #
#[derive(Reflect, Serialize)]
struct Test(usize);
let reflect = Test(3);
let serializer = TypedReflectSerializer::new(reflect.as_partial_reflect(), ®istry);
return serde_json::to_string(&serializer)
["3"]
. New behavior will return "3"
. If you were relying on old behavior you need to update your logic. Especially with serde_json
. ron
doesn’t affect from this.Use
FromReflect
when extracting entities in dynamic scenes #DynamicScene
format is changed to use custom serialize impls so old scene files will need updating:(
resources: {},
entities: {
4294967299: (
components: {
"bevy_render::camera::projection::OrthographicProjection": (
near: 0.0,
far: 1000.0,
viewport_origin: (
x: 0.5,
y: 0.5,
),
scaling_mode: WindowSize(1.0),
scale: 1.0,
area: (
min: (
x: -1.0,
y: -1.0,
),
max: (
x: 1.0,
y: 1.0,
),
),
),
},
),
},
)
(
resources: {},
entities: {
4294967299: (
components: {
"bevy_render::camera::projection::OrthographicProjection": (
near: 0.0,
far: 1000.0,
viewport_origin: (0.5, 0.5),
scaling_mode: WindowSize(1.0),
scale: 1.0,
area: (
min: (-1.0, -1.0),
max: (1.0, 1.0),
),
),
},
),
},
)
move ShortName to bevy_reflect #
bevy_utils::ShortName
should instead now be bevy_reflect::ShortName
.Rendering #
Lighting Should Only hold
Vec<Entity>
instead of TypeId<Vec<Entity>>
#SpotLightBundle
, CascadesVisibleEntities
and CubemapVisibleEntities
use VisibleMeshEntities instead of VisibleEntities
Add support for skybox transformation #
..Default::default()
or some rotation value in their initialization code.Allow volumetric fog to be localized to specific, optionally voxelized, regions. #
FogVolume
is now necessary in order to enable volumetric fog, in addition to VolumetricFogSettings
on the camera. Existing uses of volumetric fog can be migrated by placing a large FogVolume
surrounding the scene.Pack multiple vertex and index arrays together into growable buffers. #
GpuMesh
has been renamed to RenderMesh
, to reflect the fact that it no longer directly stores handles to GPU objects.GpuMesh
(now called RenderMesh
) to the MeshAllocator
resource. To access the vertex data for a mesh, use MeshAllocator::mesh_vertex_slice
. To access the index data for a mesh, use MeshAllocator::mesh_index_slice
.Add support for environment map transformation #
EnvironmentMapLight
struct, users will need to include ..default()
or some rotation value in their initialization code.Using Cas instead of CAS #14341 #
Move
Msaa
to component #Msaa
is no longer configured as a global resource, and should be specified on each spawned camera if a non-default setting is desired.Add 2d opaque phase with depth buffer #
ColorMaterial
now contains AlphaMode2d
. To keep previous behaviour, use AlphaMode::BLEND
. If you know your sprite is opaque, use AlphaMode::OPAQUE
Changed
Mesh::attributes*
functions to return MeshVertexAttribute
#Mesh::attributes
or Mesh::attributes_mut
the first value of the tuple is not the MeshVertexAttribute
instead of MeshVertexAttributeId
. To access the MeshVertexAttributeId
use the MeshVertexAttribute.id
field.Add
RenderSet::FinalCleanup
for World::clear_entities
#World::clear_entities
is now part of RenderSet::PostCleanup
rather than RenderSet::Cleanup
. Your cleanup systems should likely stay in RenderSet::Cleanup
.Add feature requirement info to image loading docs #
exr
, hdr
, basis-universal
, png
, dds
, tga
, jpeg
, bmp
, ktx2
, webp
and pnm
) should be added.Fix underflow panic in
InitTriInfo
#Rewrite screenshots. #
ScreenshotManager
has been removed. To take a screenshot, spawn a Screenshot
entity with the specified render target and provide an observer targeting the ScreenshotCaptured
event. See the window/screenshot
example to see an example.Replace the
wgpu_trace
feature with a field in bevy_render::settings::WgpuSettings
#bevy/wgpu_trace
and bevy_render/wgpu_trace
features have been removed, as WGPU tracing is now enabled during the creation of bevy_render::RenderPlugin
.bevy/wgpu_trace
or bevy_render/wgpu_trace
features you may have in any of your Cargo.toml
files.docs/debugging.md
, under the WGPU Tracing section.Refactor
AsBindGroup
to use a associated SystemParam
. #AsBindGroup
now allows the user to specify a SystemParam
to be used for creating bind groups.Meshlet software raster + start of cleanup #
Adds
ShaderStorageBuffer
asset #AsBindGroup
storage
attribute has been modified to reference the new Handle<Storage>
asset instead. Usages of Vec` should be converted into assets instead.Return
Result
s from Camera
's world/viewport conversion methods #Camera
now return a Result
instead of an Option
so that they can provide more information about failures:world_to_viewport
world_to_viewport_with_depth
viewport_to_world
viewport_to_world_2d
.ok()
on the Result
to turn it back into an Option
, or handle the Result
directly.Replaced implicit emissive weight with default. #
Split OrthographicProjection::default into 2d & 3d (Adopted) #
OrthographicProjection
, change ..default()
to ..OrthographicProjection::default_2d()
or ..OrthographicProjection::default_3d()
--- a/examples/3d/orthographic.rs
+++ b/examples/3d/orthographic.rs
@@ -20,7 +20,7 @@ fn setup(
projection: OrthographicProjection {
scale: 3.0,
scaling_mode: ScalingMode::FixedVertical(2.0),
- ..default()
+ ..OrthographicProjection::default_3d()
}
.into(),
transform: Transform::from_xyz(5.0, 5.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
Remove OrthographicProjection.scale (adopted) #
scale
with scaling_mode
, keeping in mind that scale
is (was) a multiplier. For example, replace scale: 2.0,
scaling_mode: ScalingMode::FixedHorizontal(4.0),
scaling_mode: ScalingMode::FixedHorizontal(8.0),
Rename rendering components for improved consistency and clarity #
AutoExposureSettings
→ AutoExposure
BloomSettings
→ Bloom
BloomPrefilterSettings
→ BloomPrefilter
ContrastAdaptiveSharpeningSettings
→ ContrastAdaptiveSharpening
DepthOfFieldSettings
→ DepthOfField
FogSettings
→ DistanceFog
SmaaSettings
→ Smaa
TemporalAntiAliasSettings
→ TemporalAntiAliasing
ScreenSpaceAmbientOcclusionSettings
→ ScreenSpaceAmbientOcclusion
ScreenSpaceReflectionsSettings
→ ScreenSpaceReflections
VolumetricFogSettings
→ VolumetricFog
Migrate lights to required components #
PointLightBundle
, SpotLightBundle
, and DirectionalLightBundle
have been deprecated. Use the PointLight
, SpotLight
, and DirectionalLight
components instead. Adding them will now insert the other components required by them automatically.Fix Mesh allocator bug and reduce Mesh data copies by two #
Mesh::get_vertex_buffer_data
has been renamed Mesh::create_packed_vertex_buffer_data
to reflect the fact that it copies data and allocates.Added visibility bitmask as an alternative SSAO method #
constant_object_thickness
, was added to ScreenSpaceAmbientOcclusion
. ScreenSpaceAmbientOcclusion
also lost its Eq
and Hash
implementations.Split out bevy_mesh from bevy_render #
bevy_render::mesh::morph::inherit_weights
is now bevy_render::mesh::inherit_weights
Mesh::compute_aabb
, you will need to use bevy_render::mesh::MeshAabb;
nowFeature-gate all image formats #
avif
ff
(Farbfeld)gif
ico
tiff
qoi
feature has been added to support loading QOI format images.image
crate, potentially resulting in weird bugs. Now, you should be able to add these features to your projects to support them properly.
bevy_render
crate, the feature flags for the general image formats were moved to bevy_image
instead. For example, bevy_render/png
no longer exists, and bevy_image/png
is the new location for this. The texture formats are still available on bevy_render
, e.g. bevy_render/ktx2
is needed to fully enable ktx2
support, and this will automatically enable bevy_image/ktx2
for loading the textures.Per-meshlet compressed vertex data #
Migrate bevy_sprite to required components #
SpriteBundle
with Sprite
. There are several new convenience constructors: Sprite::from_image
, Sprite::from_atlas_image
, Sprite::from_color
.Handle<Image>
and TextureAtlas
as components on sprite entities will NO LONGER WORK. Use the fields on Sprite
instead. I would have removed the Component
impls from TextureAtlas
and Handle<Image>
except it is still used within ui. We should fix this moving forward with the migration.Type safe retained render world #
Entity
that are extracted into the render world have been changed to contain MainEntity
in order to prevent errors where a render world entity id is used to look up an item by accident. Custom rendering code may need to be changed to query for &MainEntity
in order to look up the correct item from such a collection. Additionally, users who implement their own extraction logic for collections of main world entity should strongly consider extracting into a different collection that uses MainEntity
as a key.Entity
and MainEntity
for a given PhaseItem
. Custom render phases should ensure MainEntity
is available when queuing a phase item.RenderVisibleEntities
to avoid rendering items that are not visible from a view. RenderVisibleMeshEntities
, RenderCubemapVisibleEntities
, and RenderCascadeVisibleEntities
are also available for more fine-grained control.Move
ImageLoader
and CompressedImageSaver
to bevy_image
. #ImageLoader
can no longer be initialized directly through init_asset_loader
. Now you must use app.register_asset_loader(ImageLoader::new(supported_compressed_formats))
(check out the implementation of bevy_render::ImagePlugin
). This only affects you if you are initializing the loader manually and does not affect users of bevy_render::ImagePlugin
.Attempt to remove component from render world if not extracted. #
ExtractComponent
and return None
will cause the extracted component to be removed from the render world.Improve API for scaling orthographic cameras #
ScalingMode
has been refactored for clarity, especially on how to zoom orthographic cameras and their projections:ScalingMode::WindowSize
no longer stores a float, and acts as if its value was 1. Divide your camera’s scale by any previous value to achieve identical results.ScalingMode::FixedVertical
and FixedHorizontal
now use named fields.Fix UI texture atlas with offset #
let ui_node = ExtractedUiNode {
stack_index,
transform,
color,
rect,
image,
- atlas_size: Some(atlas_size * scale_factor),
+ atlas_scaling: Some(Vec2::splat(scale_factor)),
clip,
flip_x,
flip_y,
camera_entity,
border,
border_radius,
node_type,
},
let computed_slices = ComputedTextureSlices {
slices,
- image_size,
}
use precomputed border values #
logical_rect
and physical_rect
methods have been removed from Node
. Use Rect::from_center_size
with the translation and node size instead.ExtractedUiNode
have been changed to BorderRect
and ResolvedBorderRadius
respectively.Inverse bevy_render bevy_winit dependency and move cursor to bevy_winit #
CursorIcon
and CustomCursor
previously provided by bevy::render::view::cursor
is now available from bevy::winit
. A new feature custom_cursor
enables this functionality (default feature).Scenes #
Send
SceneInstanceReady
when spawning any kind of scene #SceneInstanceReady { parent: Entity }
is now SceneInstanceReady { id: InstanceId, parent: Option<Entity> }
.Align
Scene::write_to_world_with
to match DynamicScene::write_to_world_with
#Scene::write_to_world_with
no longer returns an InstanceInfo
.scene.write_to_world_with(world, ®istry)
let mut entity_map = EntityHashMap::default();
scene.write_to_world_with(world, &mut entity_map, ®istry)
Align
Scene::write_to_world_with
to match DynamicScene::write_to_world_with
#Scene::write_to_world_with
no longer returns an InstanceInfo
.scene.write_to_world_with(world, ®istry)
let mut entity_map = EntityHashMap::default();
scene.write_to_world_with(world, &mut entity_map, ®istry)
Change
SceneInstanceReady
to trigger an observer. #SceneInstanceReady
events:fn ready_system(ready_events: EventReader<'_, '_, SceneInstanceReady>) {
commands.observe(|trigger: Trigger<SceneInstanceReady>| {
commands.entity(entity).observe(|trigger: Trigger<SceneInstanceReady>| {
explicitly mention
component
in methods on DynamicSceneBuilder
#DynamicSceneBuilder::allow_all
and deny_all
now set resource accesses, not just components. To return to the previous behavior, use the new allow_all_components
or deny_all_components
methods.DynamicSceneBuilder
have been renamed:with_filter
-> with_component_filter
allow
-> allow_component
deny
-> deny_component
Migrate scenes to required components #
SceneRoot
and DynamicSceneRoot
components. Raw handles as components no longer spawn scenes.SceneBundle
and DynamicSceneBundle
have been deprecated. Instead, use the scene components directly.let model_scene = asset_server.load(GltfAssetLabel::Scene(0).from_asset("model.gltf"));
commands.spawn(SceneBundle {
scene: model_scene,
transform: Transform::from_xyz(-4.0, 0.0, -3.0),
..default()
});
let model_scene = asset_server.load(GltfAssetLabel::Scene(0).from_asset("model.gltf"));
commands.spawn((
SceneRoot(model_scene),
Transform::from_xyz(-4.0, 0.0, -3.0),
));
Text #
Text rework #
TextReader
and TextWriter
system parameters to access spans by index.fn refresh_text(mut query: Query<&mut Text, With<TimeText>>, time: Res<Time>) {
let text = query.single_mut();
text.sections[1].value = format_time(time.elapsed());
}
fn refresh_text(
query: Query<Entity, With<TimeText>>,
mut writer: UiTextWriter,
time: Res<Time>
) {
let entity = query.single();
*writer.text(entity, 1) = format_time(time.elapsed());
}
UiTextReader
and UiTextWriter
system parameters provide ways to iterate that hierarchy. The UiTextReader::iter
method will give you a normal iterator over spans, and UiTextWriter::for_each
lets you visit each of the spans.split up
TextStyle
#TextStyle
has been renamed to TextFont
and its color
field has been moved to a separate component named TextColor
which newtypes Color
.Text Rework cleanup #
TextBundle
and Text2dBundle
) were removed in favor of Text
and Text2d
. Shared configuration fields were replaced with TextLayout
, TextFont
and TextColor
components. Just TextBundle
’s additional field turned into TextNodeFlags
component, while Text2dBundle
’s additional fields turned into TextBounds
and Anchor
components.Text
or Text2d
components, child entities with TextSpan
will act as additional text sections. To still access text spans by index, use the new TextUiReader
, Text2dReader
and TextUiWriter
, Text2dWriter
system parameters.Add the ability to control font smoothing #
Text
now contains a font_smoothing: FontSmoothing
property, make sure to include it or add ..default()
when using the struct directly;FontSizeKey
has been renamed to FontAtlasKey
, and now also contains the FontSmoothing
setting;font_smoothing: FontSmoothing
argument: FontAtlas::new()
FontAtlasSet::add_glyph_to_atlas()
FontAtlasSet::get_glyph_atlas_info()
FontAtlasSet::get_outlined_glyph_texture()
Time #
aligning public apis of Time,Timer and Stopwatch #
Time
, Timer
and Stopwatch
have been cleaned up for consistency with each other and the standard library’s Duration
type. The following methods have been renamed:Stowatch::paused
-> Stopwatch::is_paused
Time::elapsed_seconds
-> Time::elapsed_secs
(including _f64
and _wrapped
variants)UI #
Clean up UiSystem system sets #
UiSystem
system set adjustments.UiSystem::Outline
system set is now strictly ordered after UiSystem::Layout
, rather than overlapping it.Fix error in
bevy_ui
when building without bevy_text
#MeasureArgs
did not exist then.bevy_text
feature is disabled for bevy_ui
, the type of the MeasureArgs::font_system
field is now a PhantomData
instead of being removed entirely. This is in order to keep the lifetime parameter, even though it is unused without text being enabled.Remove useless
Direction
field #Style
no longer has a direction
field, and Direction
has been deleted. They didn’t do anything, so you can delete any references to them as well.Rename BreakLineOn to LineBreak #
BreakLineOn
was renamed to LineBreak
, and parameters named linebreak_behavior
were renamed to linebreak
.Add UI
GhostNode
#Parent
/Children
to iterate UI children may now want to use bevy_ui::UiChildren
to ensure ghost nodes are skipped, and their first descendant Nodes included.Without<Parent>
might not query all root nodes. Use bevy_ui::UiRootNodes
where needed to iterate root nodes instead.Replace
Handle<M: UiMaterial>
component with UiMaterialHandle
wrapper #Component
impl on Handle
in the meantime :)Clip to the UI node's content box #
Overflow clip margin #
OverflowClipMargin
. It allows users to set the visible area for clipped content when using overflow-clip, -hidden, or -scroll and expand it with a margin.content_box
, padding_box
and border_box
:content_box
: elements painted outside of the content box area (the innermost part of the node excluding the padding and border) of the node are clipped. This is the new default behaviour.padding_box
: elements painted outside outside of the padding area of the node are clipped.border_box
: elements painted outside of the bounds of the node are clipped. This matches the behaviour from Bevy 0.14.with_margin
method that increases the size of the visible area by the given number in logical pixels, negative margin values are clamped to zero.OverflowClipMargin
is ignored unless overflow-clip, -hidden or -scroll is also set on at least one axis of the UI node.Migrate UI bundles to required components #
NodeBundle
with Node
. e.g. commands
- .spawn(NodeBundle {
- style: Style {
+ .spawn((
+ Node::default(),
+ Style {
width: Val::Percent(100.),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
- ..default()
- })
+ ))
ButtonBundle
with Button
. e.g. .spawn((
- ButtonBundle {
- style: Style {
- width: Val::Px(w),
- height: Val::Px(h),
- // horizontally center child text
- justify_content: JustifyContent::Center,
- // vertically center child text
- align_items: AlignItems::Center,
- margin: UiRect::all(Val::Px(20.0)),
- ..default()
- },
- image: image.clone().into(),
+ Button,
+ Style {
+ width: Val::Px(w),
+ height: Val::Px(h),
+ // horizontally center child text
+ justify_content: JustifyContent::Center,
+ // vertically center child text
+ align_items: AlignItems::Center,
+ margin: UiRect::all(Val::Px(20.0)),
..default()
},
+ UiImage::from(image.clone()),
ImageScaleMode::Sliced(slicer.clone()),
))
ImageBundle
with UiImage
. e.g.- commands.spawn(ImageBundle {
- image: UiImage {
+ commands.spawn((
+ UiImage {
texture: metering_mask,
..default()
},
- style: Style {
+ Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
..default()
},
- ..default()
- });
+ ));
Merge Style properties into Node. Use ComputedNode for computed properties. #
Style
into Node
and replace all Style
component usage with Node
.commands.spawn((
Node::default(),
Style {
width: Val::Px(100.),
..default()
},
));
commands.spawn(Node {
width: Val::Px(100.),
..default()
});
Node
, use ComputedNode
instead:fn system(nodes: Query<&Node>) {
for node in &nodes {
let computed_size = node.size();
}
}
fn system(computed_nodes: Query<&ComputedNode>) {
for computed_node in &computed_nodes {
let computed_size = computed_node.size();
}
}
Explicitly order
CameraUpdateSystem
before UiSystem::Prepare
#CameraUpdateSystem
is now explicitly ordered before UiSystem::Prepare
instead of being ambiguous with it.Utils #
Remove unused type parameter in
Parallel::drain()
#Parallel::drain()
was unused, so it is now removed. If you were manually specifying it, you can remove the bounds.// 0.14
// Create a `Parallel` and give it a value.
let mut parallel: Parallel<Vec<u8>> = Parallel::default();
*parallel.borrow_local_mut() = vec![1, 2, 3];
for v in parallel.drain::<u8>() {
// ...
}
// 0.15
let mut parallel: Parallel<Vec<u8>> = Parallel::default();
*parallel.borrow_local_mut() = vec![1, 2, 3];
// Remove the type parameter.
for v in parallel.drain() {
// ...
}
Remove remnant
EntityHash
and related types from bevy_utils
#bevy::utils::{EntityHash, EntityHasher, EntityHashMap, EntityHashSet}
now have to be imported from bevy::ecs::entity
.Allow
bevy_utils
in no_std
Contexts #bevy_utils
and setting default_features
to false
, but relying on elements which are now gated behind the std
or alloc
features, include the relevant feature in your Cargo.toml
.Remove allocation in
get_short_name
#format!
, dbg!
, panic!
, etc.// Before
panic!("{} is too short!", get_short_name(name));
// After
panic!("{} is too short!", ShortName(name));
String
Value// Before
let short: String = get_short_name(name);
// After
let short: String = ShortName(name).to_string();
Windowing #
Remove unused
default
feature from bevy_window
#bevy_window
had an empty default feature flag that did not do anything, so it was removed. You may have to remove any references to it if you specified it manually.# 0.14
[dependencies]
bevy_window = { version = "0.14", default-features = false, features = ["default"] }
# 0.15
[dependencies]
bevy_window = { version = "0.15", default-features = false }
Expose winit's
MonitorHandle
#WindowMode
variants now take a MonitorSelection
, which can be set to MonitorSelection::Primary
to mirror the old behavior.move ANDROID_APP to bevy_window #
android_activity
reexport from bevy::winit::android_activity
, it is now in bevy::window::android_activity
. Same for the ANDROID_APP
staticAdd
bevy_window::Window
options for MacOS #bevy_window::Window
now has extra fields for configuring MacOS window settings: pub movable_by_window_background: bool,
pub fullsize_content_view: bool,
pub has_shadow: bool,
pub titlebar_shown: bool,
pub titlebar_transparent: bool,
pub titlebar_show_title: bool,
pub titlebar_show_buttons: bool,
Window::default
keeps the same behaviour as before.