- 0.15 to 0.16
- Accessibility
- Animation
- App
- Assets
- Audio
- Cross-Cutting
- Dev-Tools
- Diagnostics
- ECS
- Improved Required Component Syntax
- Add EntityDoesNotExistError, replace cases of Entity as an error, do some easy Resultification
- Cache systems by S instead of S::System
- Change World::try_despawn and World::try_insert_batch to return Result
- Convert to fallible system in IntoSystemConfigs
- Create new NonSendMarker
- Define system param validation on a per-system parameter basis
- Deprecate insert_or_spawn function family
- Deprecated Query::many and many_mut
- Encapsulate cfg(feature = "track_location") in a type.
- Fallible systems
- Fix unsoundness in QueryIter::sort_by
- Flush commands after every mutation in WorldEntityMut
- Generic system config
- Implement SpawnableList for Vec<Bundle>
- Improved Command Errors
- Improved Spawn APIs and Bundle Effects
- Introduce methods on QueryState to obtain a Query
- Isolate component registration
- Make Query::single (and friends) return a Result
- Make system param validation rely on the unified ECS error handling via the GLOBAL_ERROR_HANDLER
- Move Item and fetch to QueryData from WorldQuery
- Move Resource trait to its own file
- Optimize Entities::entity_does_not_exist_error_details_message, remove UnsafeWorldCell from error
- Parent -> ChildOf
- Queued component registration
- Refactor hierarchy-related commands to remove structs
- Refactored ComponentHook Parameters into HookContext
- Relationships (non-fragmenting, one-to-many)
- Remove ChildOf::get and Deref impl
- Remove Event: Component trait bound using a wrapper type which impls Component
- Remove petgraph from bevy_ecs
- Remove deprecated ECS items
- Remove deprecated component_reads_and_writes
- Remove flush_and_reserve_invalid_assuming_no_entities
- Remove lifetime from QueryEntityError
- Remove unsound Clone impl for EntityMutExcept
- Remove unused generic in DeferredWorld::trigger
- Renamed EventWriter::send methods to write.
- Replace VisitEntities with MapEntities
- Run observers before hooks for on_replace and on_remove
- Shorten the 'world lifetime returned from QueryLens::query().
- Split Component::register_component_hooks into individual methods
- Support non-Vec data structures in relations
- Support using FilteredResources with ReflectResource.
- Turn apply_deferred into a ZST System
- Use register_dynamic for merging
- add Entity default to the entity set wrappers
- impl EntityBorrow for more types
- implement EntitySet and iter_many_unique methods
- make EntityHashMap and EntityHashSet proper types
- make various entity wrapper type modules public
- one shot system cleanup
- rename enqueue_command to queue_command for consistency
- Make ComponentTicks field public
- Add Immutable Component Support
- Faster entity cloning
- FilteredResource returns a Result instead of a simple Option
- ReflectBundle::remove improvement
- Input
- Math
- Fix atan2 docs
- Fix rounding in steps easing function
- Improve cubic segment bezier functionality
- Refactor non-core Curve methods into extension traits
- Rename Rot2::angle_between to Rot2::angle_to
- Reworked Segment types into their cartesian forms
- Use IntoIterator instead of Into<Vec<..>> in cubic splines interfaces
- [math] Add SmoothStep and SmootherStep easing functions
- Make bevy_reflect feature of bevy_math non-default
- Picking
- Add flags to SpritePlugin and UiPlugin to allow disabling their picking backend (without needing to disable features).
- Add optional transparency passthrough for sprite backend with bevy_picking
- Allow users to easily use bevy_sprite and bevy_ui without picking
- Fix bevy_picking plugin suffixes
- Flattened PointerAction::Pressed into Press and Release.
- If there is no movement, DragStart is not triggered.
- Make RayMap map public
- Make sprite picking opt-in
- Make sprite picking opt-in
- Rename "focus" in bevy_picking to "hover"
- Rename Pointer<Down/Up> -> Pointer<Pressed/Released> in bevy_picking.
- Rename PickingBehavior to Pickable
- Rename RayCastSettings to MeshRayCastSettings
- Unify picking backends
- Reflection
- Include ReflectFromReflect in all dynamic data types.
- Make bevy_remote feature enable serialize feature
- Rename ArgList::push methods to with and add new push methods which take &mut self
- bevy_reflect: Deprecate PartialReflect::clone_value
- bevy_reflect: Remove PartialReflect::serializable
- Remove unnecessary PartialReflect bound on DeserializeWithRegistry
- Rendering
- Add uv_transform to ColorMaterial
- Add a bindless mode to AsBindGroup.
- Add bevy_anti_aliasing
- Adding alpha_threshold to OrderIndependentTransparencySettings for user-level optimization
- Allowed creating uninitialized images (for use as storage textures)
- Bind only the written parts of storage buffers.
- Change GpuImage::size from UVec2 to Extent3d
- Cold Specialization
- Expose Pipeline Compilation Zero Initialize Workgroup Memory Option
- Fix sprite performance regression since retained render world
- Fix the texture_binding_array, specialized_mesh_pipeline, and custom_shader_instancing examples after the bindless change.
- Implement bindless lightmaps.
- Implement experimental GPU two-phase occlusion culling for the standard 3D mesh pipeline.
- Introduce support for mixed lighting by allowing lights to opt out of contributing diffuse light to lightmapped objects.
- Introduce two-level bins for multidrawable meshes.
- Key render phases off the main world view entity, not the render world view entity.
- Make indirect drawing opt-out instead of opt-in, enabling multidraw by default.
- Make the get function on InstanceInputUniformBuffer less error prone
- Make the default directional light shadow cascade settings similar to those of other engines.
- Mesh::merge to return a Result
- Move TextureAtlas and friends into bevy_image
- Move non-generic parts of the PrepassPipeline to internal field
- Native unclipped depth on supported platforms
- Newtype Anchor
- Only use the AABB center for mesh visibility range testing if specified.
- Reduce the clusterable object UBO size below 16384 for WebGL 2.
- Refactor and simplify custom projections
- Remove the type parameter from check_visibility, and only invoke it once.
- Support scale factor for image render targets
- Upgrade to wgpu v24
- Use multi_draw_indirect_count where available, in preparation for two-phase occlusion culling.
- Use unchecked shaders for better performance
- cleanup bevy_render/lib.rs
- doc: fix camera link
- ExtractedSprites slice buffer
- Improved UiImage and Sprite scaling and slicing APIs
- Rename DefaultCameraView
- Rename TargetCamera to UiTargetCamera
- BorderRect maintenance
- Scenes
- Tasks
- Text
- UI
- Fixing ValArithmeticError typo and unused variant
- Move TextureAtlas into UiImage and remove impl Component for TextureAtlas
- Multiple box shadow support
- Only use physical coords internally in bevy_ui
- Remove custom rounding
- Remove the min and max fields from LayoutContext.
- Rename UiBoxShadowSamples to BoxShadowSamples.
- UiImage -> ImageNode, UiImageSize -> ImageNodeSize
- Windowing
- Without area
- :pencil2: Fix typos across bevy
- Link iOS example with rustc, and avoid C trampoline
- Remove Image::from_buffer name argument (only present in debug "dds" builds)
- Remove bevy_core
- Rename trigger.entity() to trigger.target()
- Use 4-byte LightmapSlabIndex for batching instead of 16-byte AssetId<Image>
- Use target_abi = "sim" instead of ios_simulator feature
- Utils
Migration Guide: 0.15 to 0.16
Accessibility #
Replace bevy_a11y::Focus with InputFocus #
bevy_a11y::Focus
has been replaced with bevy_input_focus::Focus
.
Animation #
Incorporate all node weights in additive blending #
I will write a migration guide later if this change is not included in 0.15.
Add ways to configure EasingFunction::Steps
via new StepConfig
#
EasingFunction::Steps
now uses aStepConfig
instead of a rawusize
. You can replicate the previous behavior by replaceingEasingFunction::Steps(10)
withEasingFunction::Steps(StepConfig::new(10))
.
Fix EaseFunction::Exponential*
to exactly hit (0, 0) and (1, 1) #
This release of bevy slightly tweaked the definitions of EaseFunction::ExponentialIn
, EaseFunction::ExponentialOut
, and EaseFunction::ExponentialInOut
. The previous definitions had small discontinuities, while the new ones are slightly rescaled to be continuous. For the output values that changed, that change was less than 0.001, so visually you might not even notice the difference.
However, if you depended on them for determinism, you’ll need to define your own curves with the previous definitions.
App #
Headless by features #
HeadlessPlugins
has been removed, but the feature is still supported. bevy_window
, a new default feature enables windows, etc. To replicate HeadlessPlugins
, use DefaultPlugins
and disable the bevy_window
feature.
Assets #
Remove the meta
field from LoadedAsset
and ErasedLoadedAsset
. #
ErasedAssetLoader
now takes a borrow toAssetMetaDyn
instead of aBox
.LoadedAsset::new_with_dependencies
no longer requires ameta
argument.LoadContext::finish
no longer requires ameta
argument.
Weak handle migration #
Replace Handle::weak_from_u128
with weak_handle!
and a random UUID.
Add AssetChanged
query filter #
- The
asset_events
system is no longer public. Users should order their systems relative to theAssetEvents
system set.
Audio #
Add ability to mute audio sinks #
- The
AudioSinkPlayback
trait now has 4 new methods to allow you to mute audio sinks:is_muted
,mute
,unmute
andtoggle_mute
. You can use these methods onbevy_audio
’sAudioSink
andSpatialAudioSink
components to manage the sink’s mute state. AudioSinkPlayback
’sset_volume
method now takes a mutable reference instead of an immutable one. Update your code which callsset_volume
onAudioSink
andSpatialAudioSink
components to take a mutable reference. E.g.:
Before:
fn increase_volume(sink: Single<&AudioSink>) {
sink.set_volume(sink.volume() + 0.1);
}
After:
fn increase_volume(mut sink: Single<&mut AudioSink>) {
let current_volume = sink.volume();
sink.set_volume(current_volume + 0.1);
}
- The
PlaybackSettings
component now has amuted
field which you can use to spawn your audio in a muted state.PlaybackSettings
also now has a helper methodmuted
which you can use when building the component. E.g.:
commands.spawn((
// ...
AudioPlayer::new(asset_server.load("sounds/Windless Slopes.ogg")),
PlaybackSettings::LOOP.with_spatial(true).muted(),
));
Rename AudioSinkPlayback::toggle to toggle_playback #
AudioSinkPlayback
’stoggle
method has been renamed totoggle_playback
. This was done to create consistency with thetoggle_mute
method added in https://github.com/bevyengine/bevy/pull/16813. Change instances oftoggle
totoggle_playback
. E.g.:
Before:
fn pause(keyboard_input: Res<ButtonInput<KeyCode>>, sink: Single<&AudioSink>) {
if keyboard_input.just_pressed(KeyCode::Space) {
sink.toggle();
}
}
After:
fn pause(keyboard_input: Res<ButtonInput<KeyCode>>, sink: Single<&AudioSink>) {
if keyboard_input.just_pressed(KeyCode::Space) {
sink.toggle_playback();
}
}
Support decibels in bevy_audio::Volume #
Audio volume can now be configured using decibel values, as well as using linear scale values. To enable this, some types and functions in bevy_audio
have changed.
Volume
is now an enum withLinear
andDecibels
variants.
Before:
let v = Volume(1.0);
After:
let volume = Volume::Linear(1.0);
let volume = Volume::Decibels(0.0); // or now you can deal with decibels if you prefer
Volume::ZERO
has been renamed to the more semantically correctVolume::SILENT
becauseVolume
now supports decibels and “zero volume” in decibels actually means “normal volume”.- The
AudioSinkPlayback
trait’s volume-related methods now deal withVolume
types rather thanf32
s.AudioSinkPlayback::volume()
now returns aVolume
rather than anf32
.AudioSinkPlayback::set_volume
now receives aVolume
rather than anf32
. This affects theAudioSink
andSpatialAudioSink
implementations of the trait. The previousf32
values are equivalent to the volume converted to linear scale so theVolume:: Linear
variant should be used to migrate betweenf32
s andVolume
. - The
GlobalVolume::new
function now receives aVolume
instead of anf32
.
Cross-Cutting #
Add no_std
support to bevy
#
- If you were previously relying on
bevy
with default features disabled, you may need to enable thestd
andasync_executor
features. bevy_reflect
has had itsbevy
feature removed. If you were relying on this feature, simply enablesmallvec
andsmol_str
instead.
Support for non-browser wasm
#
When using Bevy crates which don’t automatically enable the web
feature, please enable it when building for the browser.
Upgrade to Rust Edition 2024 #
The lifetimes of functions using return-position impl-trait (RPIT) are likely more conservative than they had been previously. If you encounter lifetime issues with such a function, please create an issue to investigate the addition of + use<...>
.
Don't reëxport bevy_image
from bevy_render
#
Use bevy_image
instead of bevy_render::texture
items.
Dev-Tools #
BRP strict field in query #
BrpQueryParams
now hasstrict
boolean field. It serfs as a flag to fail when encountering an invalid component rather than skipping it. Defaults to false.
Rename track_change_detection
flag to track_location
#
The track_change_detection
feature flag has been renamed to track_location
to better reflect its extended capabilities.
Draw the UI debug overlay using the UI renderer #
The ui_debug_overlay
module has been removed from bevy_dev_tools
. There is a new debug overlay implemented using the bevy_ui
renderer. To use it, enable the bevy_ui_debug
feature and set the enable
field of the UiDebugOptions
resource to true
.
Diagnostics #
Allow users to customize history length in FrameTimeDiagnosticsPlugin
#
FrameTimeDiagnosticsPlugin
now contains two fields. Use FrameTimeDiagnosticsPlugin::default()
to match Bevy’s previous behavior or, for example, FrameTimeDiagnosticsPlugin::new(60)
to configure it.
Event source location tracking #
- If you manually construct a
SendEvent
, useSendEvent::new()
ECS #
Improved Required Component Syntax #
Custom-constructor requires should use the new expression-style syntax:
// before
#[derive(Component)]
#[require(A(returns_a))]
struct Foo;
// after
#[derive(Component)]
#[require(A = returns_a())]
struct Foo;
Inline-closure-constructor requires should use the inline value syntax where possible:
// before
#[derive(Component)]
#[require(A(|| A(10))]
struct Foo;
// after
#[derive(Component)]
#[require(A(10)]
struct Foo;
In cases where that is not possible, use the expression-style syntax:
// before
#[derive(Component)]
#[require(A(|| A(10))]
struct Foo;
// after
#[derive(Component)]
#[require(A = A(10)]
struct Foo;
Add EntityDoesNotExistError
, replace cases of Entity
as an error, do some easy Resultification #
World::inspect_entity
now returnsResult<impl Iterator<Item = &ComponentInfo>, EntityDoesNotExistError>
instead ofimpl Iterator<Item = &ComponentInfo>
.World::get_entity
now returnsEntityDoesNotExistError
as an error instead ofEntity
. You can still access the entity’s ID through the error’sentity
field.UnsafeWorldCell::get_entity
now returnsResult<UnsafeEntityCell, EntityDoesNotExistError>
instead ofOption<UnsafeEntityCell>
.
Cache systems by S
instead of S::System
#
The CachedSystemId
resource has been changed:
// Before:
let cached_id = CachedSystemId::<S::System>(id);
assert!(id == cached_id.0);
// After:
let cached_id = CachedSystemId::<S>::new(id);
assert!(id == SystemId::from_entity(cached_id.entity));
Change World::try_despawn
and World::try_insert_batch
to return Result
#
World::try_despawn
now returns aResult
rather than abool
.World::try_insert_batch
andWorld::try_insert_batch_if_new
now return aResult
where they previously returned nothing.
Convert to fallible system in IntoSystemConfigs #
IntoSystemConfigs
has been removed forBoxedSystem<(), ()>
. Either useInfallibleSystemWrapper
before boxing or make your system returnbevy::ecs::prelude::Result
.
Create new NonSendMarker
#
If NonSendMarker
is being used from bevy_app::prelude::*
, replace it with bevy_ecs::system::NonSendMarker
or use it from bevy_ecs::prelude::*
. In addition to that, NonSendMarker
does not need to be wrapped like so:
fn my_system(_non_send_marker: Option<NonSend<NonSendMarker>>) {
...
}
Instead, it can be used without any wrappers:
fn my_system(_non_send_marker: NonSendMarker) {
...
}
Define system param validation on a per-system parameter basis #
Various system and system parameter validation methods (SystemParam::validate_param
, System::validate_param
and System::validate_param_unsafe
) now return and accept a ValidationOutcome
enum, rather than a bool
. The previous true
values map to ValidationOutcome::Valid
, while false
maps to ValidationOutcome::Invalid
.
However, if you wrote a custom schedule executor, you should now respect the new ValidationOutcome::Skipped
parameter, skipping any systems whose validation was skipped. By contrast, ValidationOutcome::Invalid
systems should also be skipped, but you should call the default_error_handler
on them first, which by default will result in a panic.
If you are implementing a custom SystemParam
, you should consider whether failing system param validation is an error or an expected state, and choose between Invalid
and Skipped
accordingly. In Bevy itself, Single
and Populated
now once again skip the system when their conditions are not met. This is the 0.15.0 behavior, but stands in contrast to the 0.15.1 behavior, where they would panic.
Deprecate insert_or_spawn
function family #
The following functions have been deprecated:
Commands::insert_or_spawn_batch
World::insert_or_spawn_batch
World::insert_or_spawn_batch_with_caller
These functions, when used incorrectly, can cause major performance problems and are generally viewed as anti-patterns and foot guns. These are planned to be removed altogether in 0.17.
Instead of these functions consider doing one of the following:
Option A) Instead of despawing entities and re-spawning them at a particular id, insert the new Disabled
component without despawning the entity, and use try_insert_batch
or insert_batch
and remove Disabled
instead of re-spawning it.
Option B) Instead of giving special meaning to an entity id, simply use spawn_batch
and ensure entity references are valid when despawning.
Deprecated Query::many and many_mut #
Query::many
and Query::many_mut
have been deprecated to reduce panics and API duplication. Use Query::get_many
and Query::get_many_mut
instead, and handle the Result
.
Encapsulate cfg(feature = "track_location")
in a type. #
Methods like Ref::changed_by()
that return a &'static Location<'static>
will now be available even when the track_location
feature is disabled, but they will return a new MaybeLocation
type. MaybeLocation
wraps a &'static Location<'static>
when the feature is enabled, and is a ZST when the feature is disabled.
Existing code that needs a &Location
can call into_option().unwrap()
to recover it. Many trait impls are forwarded, so if you only need Display
then no changes will be necessary.
If that code was conditionally compiled, you may instead want to use the methods on MaybeLocation
to remove the need for conditional compilation.
Code that constructs a Ref
, Mut
, Res
, or ResMut
will now need to provide location information unconditionally. If you are creating them from existing Bevy types, you can obtain a MaybeLocation
from methods like Table::get_changed_by_slice_for()
or ComponentSparseSet::get_with_ticks
. Otherwise, you will need to store a MaybeLocation
next to your data and use methods like as_ref()
or as_mut()
to obtain wrapped references.
Fallible systems #
This change should be pretty much non-breaking, except for users who have implemented their own custom executors. Those users should use ScheduleSystem
in place of BoxedSystem<(), ()>
and import the System
trait where needed. They can choose to do whatever they wish with the result.
Fix unsoundness in QueryIter::sort_by
#
The sort
family of methods on QueryIter
unsoundly gave access L::Item<'w>
with the full 'w
lifetime. It has been shortened to L::Item<'w>
so that items cannot escape the comparer. If you get lifetime errors using these methods, you will need to make the comparer generic in the new lifetime. Often this can be done by replacing named 'w
with '_
, or by replacing the use of a function item with a closure.
// Before: Now fails with "error: implementation of `FnMut` is not general enough"
query.iter().sort_by::<&C>(Ord::cmp);
// After: Wrap in a closure
query.iter().sort_by::<&C>(|l, r| Ord::cmp(l, r));
query.iter().sort_by::<&C>(comparer);
// Before: Uses specific `'w` lifetime from some outer scope
// now fails with "error: implementation of `FnMut` is not general enough"
fn comparer(left: &&'w C, right: &&'w C) -> Ordering { /* ... */ }
// After: Accepts any lifetime using inferred lifetime parameter
fn comparer(left: &&C, right: &&C) -> Ordering { /* ... */ }
Flush commands after every mutation in WorldEntityMut
#
Previously EntityWorldMut
triggered command queue flushes in unpredictable places, which could interfere with hooks and observers. Now the command queue is flushed always immediately after any call in EntityWorldMut
that spawns or despawns an entity, or adds, removes or replaces a component. This means hooks and observers will run their commands in the correct order.
As a side effect, there is a possibility that a hook or observer could despawn the entity that is being referred to by EntityWorldMut
. This could already currently happen if an observer was added while keeping an EntityWorldMut
reference and would cause unsound behaviour. If the entity has been despawned, calling any methods which require the entity location will panic. This matches the behaviour that Commands
will panic if called on an already despawned entity. In the extremely rare case where taking a new EntityWorldMut
reference or otherwise restructuring the code so that this case does not happen is not possible, there’s a new is_despawned
method that can be used to check if the referred entity has been despawned.
Generic system config #
SystemSetConfigs -> ScheduleConfigs Existing spawn patterns will continue to work as expected. Manual Bundle implementations now require a The old The The errors Component registration can now be queued with only The following functions have moved from Accordingly, functions in If you were queuing the structs of hierarchy-related commands or Update the function signatures for your component hooks to only take 2 arguments, Likewise, if you were discarding certain parameters, you can use The The The following methods (some removed in previous PRs) are now replaced by As Additionally, you’ll need to To ease migration, please consider the below extension trait which you can include in your project: Please take note of the use of If you were previously implementing The order of hooks and observers for Users of If you are manually creating a Old: New: This can prevent unnecessary cloning. Switch type parameter order for the relevant wrapper types/aliases. Any custom type used as a Users of Any mention or import of types in the affected modules have to add the respective module name to the import path. F.e.: All instances of the Users will need to handle the different return type on FilteredResource::get, FilteredResource::get_id, FilteredResource::get_mut as it is now a Result not an Option. If you don’t need the returned value from The I’m not sure if this counts as a breaking change, since the implementation clearly meant to use Replace The segment type constructors changed so if someone previously created a Segment2d with a direction and length they would now need to use the The cubic splines API now uses This version of bevy marks Sprite picking now ignores transparent regions (with an alpha value less than or equal to 0.1). To configure this, modify the Fix the missing part of Drag https://github.com/bevyengine/bevy/pull/16950 The The sprite picking backend is now strictly opt-in using the Various terms related to “focus” in These changes are also relevant when working with Clicking and pressing Events in events.rs categories change from [Down], [Up], [Click] to [Pressed], [Released], [Click]. Change all instances of The hasher in reflected The Uses of the Similarly, the following methods have been deprecated and should be replaced with these alternatives: Add When using anti aliasing features, you now need to import them from If you previously explicitly initialized OrderIndependentTransparencySettings with your own Code that directly access TODO The following types have been moved from If you are using the If you are using the If you are using the If you were using a field of the The anchor component has been changed from an enum to a struct newtyping a The other enum variants have been replaced with corresponding constants: This section is optional. If there are no breaking changes, you can delete this section. The In most cases, this means code that spawns an entity with should be converted to: The If you previously relied on scene entities no longer in the hierarchy being despawned when the scene root is despawned , use The Before: After: Before: After: Bevy UI now supports multiple shadows per node. A new struct The Before: After: The The The Before: After: This section is optional. If there are no breaking changes, you can delete this section. (kept in case I include the If you have been building your application for iOS: Previously, the You have two options for dealing with this: If you’ve added further C code and Xcode customizations, or it makes sense for your use-case to continue link with Xcode, you can revert to the old behaviour by adding The other, preferred option is to remove your “compile” and “link” build phases, and instead replace it with a “run script” phase that invokes Structs Functions Removed If you’re using a project that builds upon the mobile example, remove the In 0.16 Note that certain items have been completely removed, see below for further details. Re-Exports Structs Traits Macros Functions Type Aliases Removed Items
Implement SpawnableList for
Vec<Bundle>
#Vec
s of Bundle
instead of using the SpawnIter
approach.
Improved Command Errors #
Improved Spawn APIs and Bundle Effects #
BundleEffect
associated type. Existing bundles would have no bundle effect, so use ()
. Additionally Bundle::from_components
has been moved to the new BundleFromComponents
trait.// Before
unsafe impl Bundle for X {
unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self {
}
/* remaining bundle impl here */
}
// After
unsafe impl Bundle for X {
type Effect = ();
/* remaining bundle impl here */
}
unsafe impl BundleFromComponents for X {
unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self {
}
}
Introduce methods on QueryState to obtain a Query #
Query::to_readonly
has been renamed to Query::as_readonly
.
Isolate component registration #
Make Query::single (and friends) return a Result #
Query::single
, Query::single_mut
and their QueryState
equivalents now return a Result
. Generally, you’ll want to:Result
using the ?
operator.let else Ok(data)
block to early return if it’s an expected failure.unwrap()
or Ok
destructuring inside of tests.Query::get_single
(etc) methods which did this have been deprecated.
Make system param validation rely on the unified ECS error handling via the GLOBAL_ERROR_HANDLER #
ParamWarnPolicy
and the WithParamWarnPolicy
have been removed completely. Failures during system param validation are now handled via the GLOBAL_ERROR_HANDLER
: please see the bevy_ecs::error
module docs for more information.
Move
Item
and fetch
to QueryData
from WorldQuery
#WorldQuery::Item
type and WorldQuery::fetch
method have been moved to QueryData
, as they were not useful for QueryFilter
types.
Move
Resource
trait to its own file #bevy_ecs::system::Resource
has been moved to bevy_ecs::resource::Resource
.
Optimize
Entities::entity_does_not_exist_error_details_message
, remove UnsafeWorldCell
from error #EntityFetchError::NoSuchEntity
and QueryEntityError::NoSuchEntity
now contain an EntityDoesNotExistDetails
struct instead of an UnsafeWorldCell
. If you were just printing these, they should work identically.
Parent -> ChildOf #
Parent
component has been renamed to ChildOf
.
Queued component registration #
&World
. To facilitate this, a few APIs needed to be moved around.Components
to ComponentsRegistrator
:register_component
register_component_with_descriptor
register_resource_with_descriptor
register_non_send
register_resource
register_required_components_manual
Bundle
and Component
now take ComponentsRegistrator
instead of Components
. You can obtain ComponentsRegistrator
from the new World::components_registrator
. You can obtain ComponentsQueuedRegistrator
from the new World::components_queue
, and use it to stage component registration if desired.
Refactor hierarchy-related commands to remove structs #
SendEvent
directly, you will need to change them to the methods implemented on EntityCommands
(or Commands
for SendEvent
): StructMethodcommands.queue(AddChild { child, parent });``commands.entity(parent).add_child(child);
OR commands.entity(child).set_parent(parent);``commands.queue(AddChildren { children, parent });``commands.entity(parent).add_children(children);``commands.queue(InsertChildren { children, parent });``commands.entity(parent).insert_children(children);``commands.queue(RemoveChildren { children, parent });``commands.entity(parent).remove_children(children);``commands.queue(ReplaceChildren { children, parent });``commands.entity(parent).replace_children(children);``commands.queue(ClearChildren { parent });``commands.entity(parent).clear_children();``commands.queue(RemoveParent { child });``commands.entity(child).remove_parent()``commands.queue(DespawnRecursive { entity, warn: true });``commands.entity(entity).despawn_recursive();``commands.queue(DespawnRecursive { entity, warn: false });``commands.entity(entity).try_despawn_recursive();``commands.queue(DespawnChildrenRecursive { entity, warn: true });``commands.entity(entity).despawn_descendants();``commands.queue(DespawnChildrenRecursive { entity, warn: false});``commands.entity(entity).try_despawn_descendants();``commands.queue(SendEvent { event });``commands.send_event(event);
Refactored
ComponentHook
Parameters into HookContext
#world
and context
. Note that because HookContext
is plain data with all members public, you can use de-structuring to simplify migration.// Before
fn my_hook(
mut world: DeferredWorld,
entity: Entity,
component_id: ComponentId,
) { ... }
// After
fn my_hook(
mut world: DeferredWorld,
HookContext { entity, component_id, caller }: HookContext,
) { ... }
..
in the de-structuring:// Before
fn my_hook(
mut world: DeferredWorld,
entity: Entity,
_: ComponentId,
) { ... }
// After
fn my_hook(
mut world: DeferredWorld,
HookContext { entity, .. }: HookContext,
) { ... }
Relationships (non-fragmenting, one-to-many) #
ChildBuilder
with ChildSpawnerCommands
..set_parent(parent_id)
with .insert(Parent(parent_id))
..replace_children()
with .remove::<Children>()
followed by .add_children()
. Note that you’ll need to manually despawn any children that are not carried over..despawn_recursive()
with .despawn()
..despawn_descendants()
with .despawn_related::<Children>()
..despawn()
which depend on the children being preserved, you’ll need to remove the Children
component first.
Remove ChildOf::get and Deref impl #
// Before
**child_of
// After
child_of.parent
// Before
child_of.get()
// After
child_of.parent
// Before
entity.get::<ChildOf>().map(ChildOf::get)
// After
entity.get::<ChildOf>().map(|c| c.parent)
Remove Event: Component trait bound using a wrapper type which impls Component #
Event
trait no longer requires the Component
trait. If you were relying on this behavior, change your trait bounds from Event
to Event + Component
. If you also want your Event
type to implement Component
, add a derive.
Remove
petgraph
from bevy_ecs
#Dag::graph
method no longer returns a petgraph
DiGraph
and instead returns the new DiGraph
type within bevy_ecs
. Edge and node iteration methods are provided so conversion to the petgraph
type should be trivial if required.
Remove deprecated ECS items #
Events::get_reader
, Events::get_reader_current
, ManualEventReader
, Condition::and_then
, Condition::or_else
, World::,many_entities
, World::many_entities_mut
, World::get_many_entities
, World::get_many_entities_dynamic
, World::get_many_entities_mut
, World::get_many_entities_dynamic_mut
, World::get_many_entities_from_set_mut
Remove deprecated
component_reads_and_writes
#Access::try_iter_component_access
:Access::component_reads_and_writes
Access::component_reads
Access::component_writes
try_iter_component_access
returns a Result
, you’ll now need to handle the failing case (e.g., unwrap()
). There is currently a single failure mode, UnboundedAccess
, which occurs when the Access
is for all Components
except certain exclusions. Since this list is infinite, there is no meaningful way for Access
to provide an iterator. Instead, get a list of components (e.g., from the Components
structure) and iterate over that instead, filtering using Access::has_component_read
, Access::has_component_write
, etc.filter_map
the accesses based on which method you’re attempting to replace:Access::component_reads_and_writes
-> Exclusive(_) | Shared(_)
Access::component_reads
-> Shared(_)
Access::component_writes
-> Exclusive(_)
pub trait AccessCompatibilityExt {
/// Returns the indices of the components this has access to.
fn component_reads_and_writes(&self) -> impl Iterator<Item = T> + '_;
/// Returns the indices of the components this has non-exclusive access to.
fn component_reads(&self) -> impl Iterator<Item = T> + '_;
/// Returns the indices of the components this has exclusive access to.
fn component_writes(&self) -> impl Iterator<Item = T> + '_;
}
impl<T: SparseSetIndex> AccessCompatibilityExt for Access<T> {
fn component_reads_and_writes(&self) -> impl Iterator<Item = T> + '_ {
self
.try_iter_component_access()
.expect("Access is unbounded. Please refactor the usage of this method to directly use try_iter_component_access")
.filter_map(|component_access| {
let index = component_access.index().sparse_set_index();
match component_access {
ComponentAccessKind::Archetypal(_) => None,
ComponentAccessKind::Shared(_) => Some(index),
ComponentAccessKind::Exclusive(_) => Some(index),
}
})
}
fn component_reads(&self) -> impl Iterator<Item = T> + '_ {
self
.try_iter_component_access()
.expect("Access is unbounded. Please refactor the usage of this method to directly use try_iter_component_access")
.filter_map(|component_access| {
let index = component_access.index().sparse_set_index();
match component_access {
ComponentAccessKind::Archetypal(_) => None,
ComponentAccessKind::Shared(_) => Some(index),
ComponentAccessKind::Exclusive(_) => None,
}
})
}
fn component_writes(&self) -> impl Iterator<Item = T> + '_ {
self
.try_iter_component_access()
.expect("Access is unbounded. Please refactor the usage of this method to directly use try_iter_component_access")
.filter_map(|component_access| {
let index = component_access.index().sparse_set_index();
match component_access {
ComponentAccessKind::Archetypal(_) => None,
ComponentAccessKind::Shared(_) => None,
ComponentAccessKind::Exclusive(_) => Some(index),
}
})
}
}
expect(...)
in these methods. You should consider using these as a starting point for a more appropriate migration based on your specific needs.
Remove flush_and_reserve_invalid_assuming_no_entities #
Entities::flush_and_reserve_invalid_assuming_no_entities
for reserve
and flush_as_invalid
and notify us if that’s insufficient
Remove lifetime from
QueryEntityError
#QueryEntityError::QueryDoesNotMatch.1
is of type ArchetypeId
instead of UnsafeWorldCell
. It is up to the caller to obtain an UnsafeWorldCell
now.QueryEntityError
no longer has a lifetime parameter, remove it from type signatures where required.
Remove unsound
Clone
impl for EntityMutExcept
#EntityMutExcept
can no-longer be cloned, as this violates Rust’s memory safety rules.
Remove unused generic in
DeferredWorld::trigger
#DeferredWorld::trigger
no longer takes a generic argument. They type is inferred via impl Event
instead of T: Event
. If rust can not infer the type for you, consider specifying the type on the variable passed into the function rather than on the function itself.
Renamed
EventWriter::send
methods to write
. #EventWriter::send
has been renamed to EventWriter::write
.EventWriter::send_batch
has been renamed to EventWriter::write_batch
.EventWriter::send_default
has been renamed to EventWriter::write_default
.
Replace VisitEntities with MapEntities #
VisitEntities
or VisitEntitiesMut
(likely via a derive), instead use MapEntities
. Those were almost certainly used in the context of Bevy Scenes or reflection via ReflectMapEntities
. If you have a case that uses VisitEntities
or VisitEntitiesMut
directly, where MapEntities
is not a viable replacement, please let us know!// before
#[derive(VisitEntities, VisitEntitiesMut)]
struct Inventory {
items: Vec<Entity>,
#[visit_entities(ignore)]
label: String,
}
// after
#[derive(MapEntities)]
struct Inventory {
#[entities]
items: Vec<Entity>,
label: String,
}
Run observers before hooks for
on_replace
and on_remove
#on_replace
and on_remove
has been swapped. Observers are now run before hooks. This is a more natural ordering where the removal ordering is inverted compared to the insertion ordering.
Shorten the 'world lifetime returned from
QueryLens::query()
. #QueryLens::query()
who were calling get_inner()
or iter_inner()
will need to replace the call with QueryLens::query_inner()
.
Split
Component::register_component_hooks
into individual methods #Component::register_component_hooks
is now deprecated and will be removed in a future release. When implementing Component
manually, also implement the respective hook methods on Component
.// Before
impl Component for Foo {
// snip
fn register_component_hooks(hooks: &mut ComponentHooks) {
hooks.on_add(foo_on_add);
}
}
// After
impl Component for Foo {
// snip
fn on_add() -> Option<ComponentHook> {
Some(foo_on_add)
}
}
Support non-Vec data structures in relations #
EntityHashSet
and EntityHashMap
are no longer re-exported in bevy_ecs::entity
directly. If you were not using bevy_ecs
/ bevy
’s prelude
, you can access them through their now-public modules, hash_set
and hash_map
instead.
Support using FilteredResources with ReflectResource. #
ReflectComponentFns
struct, the reflect
function now takes FilteredResources
instead &World
, and there is a new reflect_mut
function that takes FilteredResourcesMut
.
Turn
apply_deferred
into a ZST System #apply_deferred
system via apply_deferred(world)
, don’t.
Use register_dynamic for merging #
RequiredComponents::register_dynamic
has been changed to RequiredComponents::register_dynamic_with
.required_components.register_dynamic(
component_id,
component_constructor.clone(),
requirement_inheritance_depth,
);
required_components.register_dynamic_with(
component_id,
requirement_inheritance_depth,
|| component_constructor.clone(),
);
add Entity default to the entity set wrappers #
impl EntityBorrow for more types #
NormalizedWindowRef::entity
has been replaced with an EntityBorrow::entity
impl.
implement EntitySet and iter_many_unique methods #
Borrow<Entity>
entity list item for an iter_many
method now has to implement EntityBorrow
instead. Any type that implements Borrow<Entity>
can trivially implement EntityBorrow
.
make EntityHashMap and EntityHashSet proper types #
with_hasher
and with_capacity_and_hasher
on EntityHashMap
/Set
must now use new
and with_capacity
respectively. If the non-newtyped versions are required, they can be obtained via Deref
, DerefMut
or into_inner
calls.
make various entity wrapper type modules public #
bevy::ecs::entity::EntityIndexSet
-> bevy::ecs::entity::index_set::EntityIndexSet
one shot system cleanup #
World::run_system_with_input
to World::run_system_with
.World::run_system_once_with
such that the system comes before the input.
rename enqueue_command to queue_command for consistency #
enqueue_command
method have been renamed to queue_command
.
Make
ComponentTicks
field public #ComponentTicks::last_changed_tick
and ComponentTicks::added_tick
methods, access fields directly.
Add Immutable
Component
Support #Component
manually, you must now provide a type for Mutability
. The type Mutable
provides equivalent behaviour to earlier versions of Component
:impl Component for Foo {
type Mutability = Mutable;
// ...
}
Component<Mutability = Mutable>
rather than Component
if you require mutable access to said component.Mut<T>
will now typically return an OccupiedEntry<T>
instead, requiring you to add an into_mut()
to get the Mut<T>
item again.
Faster entity cloning #
&EntityCloner
in component clone handlers is changed to &mut ComponentCloneCtx
to better separate data.EntityCloneHandler
from enum to struct and added convenience functions to add default clone and reflect handler more easily.
FilteredResource returns a Result instead of a simple Option #
ReflectBundle::remove
improvement #remove
, discard it.Input #
Gamepad improvements #
Gamepad
fields are now public.Gamepad
delegates like Gamepad::just_pressed
, call these methods directly on the fields.
Scale input to account for deadzones #
GamepadButtonChangedEvent.value
is now linearly rescaled to be from 0.0..=1.0
(instead of low..=high
) and GamepadAxisChangedEvent.value
is now linearly rescaled to be from -1.0..=0.0
/0.0..=1.0
(accounting for the deadzone).
Use
Name
component for gamepad #GamepadInfo
no longer exists: Name
component.Gamepad
component directly.GamepadConnection::Connected
now stores all info fields directly.
Expose
text
field from winit in KeyboardInput
#KeyboardInput
event now has a new text
field.Math #
Fix atan2 docs #
f32::atan2
directly, so it was really just the parameter names that were wrong.
Fix rounding in steps easing function #
EaseFunction::Steps
now behaves like css’s default, “jump-end.” If you were relying on the old behavior, we plan on providing it. See https://github.com/bevyengine/bevy/issues/17744.
Improve cubic segment bezier functionality #
CubicCurve::new_bezier
with CubicCurve::new_bezier_easing
.
Refactor non-core Curve methods into extension traits #
Curve
has been refactored so that much of its functionality is now in extension traits. Adaptors such as map
, reparametrize
, reverse
, and so on now require importing CurveExt
, while the resampling methods resample_*
require importing CurveResampleExt
. Both of these new traits are exported through bevy::math::curve
and through bevy::math::prelude
.
Rename
Rot2::angle_between
to Rot2::angle_to
#Rot2::angle_between
has been deprecated, use Rot2::angle_to
instead, the semantics of Rot2::angle_between
will change in the future.
Reworked Segment types into their cartesian forms #
from_direction
constructor
Use
IntoIterator
instead of Into<Vec<..>>
in cubic splines interfaces #IntoIterator
in places where it used Into<Vec<..>>
. For most users, this will have little to no effect (it is largely more permissive). However, in case you were using some unusual input type that implements Into<Vec<..>>
without implementing IntoIterator
, you can migrate by converting the input to a Vec<..>
before passing it into the interface.
[math] Add
SmoothStep
and SmootherStep
easing functions #EaseFunction
as #[non_exhaustive]
to that future changes to add more easing functions will be non-breaking. If you were exhaustively matching that enum – which you probably weren’t – you’ll need to add a catch-all (_ =>
) arm to cover unknown easing functions.
Make
bevy_reflect
feature of bevy_math
non-default #bevy_reflect
has been made a non-default feature of bevy_math
. (It is still enabled when bevy_math
is used through bevy
.) You may need to enable this feature if you are using bevy_math
on its own and desire for the types it exports to implement Reflect
and other reflection traits.Picking #
Add flags to
SpritePlugin
and UiPlugin
to allow disabling their picking backend (without needing to disable features). #UiPlugin
now contains an extra add_picking
field if bevy_ui_picking_backend
is enabled.SpritePlugin
is no longer a unit struct, and has one field if bevy_sprite_picking_backend
is enabled (otherwise no fields).
Add optional transparency passthrough for sprite backend with bevy_picking #
SpriteBackendSettings
resource.
Allow users to easily use
bevy_sprite
and bevy_ui
without picking #bevy_sprite_picking_backend
is no longer included by default when using the bevy_sprite
feature. If you are using Bevy without default features and relied on sprite picking, add this feature to your Cargo.toml
.bevy_ui_picking_backend
is no longer included by default when using the bevy_ui
feature. If you are using Bevy without default features and relied on sprite picking, add this feature to your Cargo.toml
.
Fix
bevy_picking
plugin suffixes #MeshPickingBackend
is now named MeshPickingPlugin
.MeshPickingBackendSettings
is now named MeshPickingSettings
.SpritePickingBackend
is now named SpritePickingPlugin
.UiPickingBackendPlugin
is now named UiPickingPlugin
.DefaultPickingPlugins
is now a a PluginGroup
instead of a Plugin
.
Flattened
PointerAction::Pressed
into Press
and Release
. #PointerAction::Pressed
has been separated into two variants, PointerAction::Press
and PointerAction::Release
.PointerAction::Moved
has been renamed to PointerAction::Move
.PointerAction::Canceled
has been renamed to PointerAction::Cancel
.
If there is no movement, DragStart is not triggered. #
Make RayMap map public #
bevy_picking::backend::ray::RayMap::map
method is removed as redundant, In systems using Res<RayMap>
replace ray_map.map()
with &ray_map.map
Make sprite picking opt-in #
SpritePickingCamera
and Pickable
components. You should add the Pickable
component any entities that you want sprite picking to be enabled for, and mark their respective cameras with SpritePickingCamera
.
Make sprite picking opt-in #
Pickable
component when using sprite picking.-commands.spawn(Sprite { .. } );
+commands.spawn((Sprite { .. }, Pickable::default());
Rename "focus" in
bevy_picking
to "hover" #bevy_picking
have been renamed to refer to “hover” to avoid confusion with bevy_input_focus
. In particular:update_focus
system has been renamed to generate_hovermap
PickSet::Focus
and PostFocus
have been renamed to Hover
and PostHover
bevy_picking::focus
module has been renamed to bevy_picking::hover
is_focus_enabled
field on PickingPlugin
has been renamed to is_hover_enabled
focus_should_run
run condition has been renamed to hover_should_run
Rename Pointer<Down/Up> -> Pointer<Pressed/Released> in bevy_picking. #
bevy_picking/src/pointer.rs
:enum PressDirection
:
PressDirection::Down
changes to PressDirection::Pressed
.
PressDirection::Up
changes to PressDirection::Released
.enum PointerAction
bevy_picking/src/events.rs
:struct Down
changes to struct Pressed
- fires when a pointer button is pressed over the ‘target’ entity.struct Up
changes to struct Released
- fires when a pointer button is released over the ‘target’ entity.struct Click
now fires when a pointer sends a Pressed event followed by a Released event on the same ‘target’.struct DragStart
now fires when the ‘target’ entity receives a pointer Pressed event followed by a pointer Move event.struct DragEnd
now fires when the ‘target’ entity is being dragged and receives a pointer Released event.PickingEventWriters<'w>::down_events: EventWriter<'w, Pointer<Down>>
changes to PickingEventWriters<'w>::pressed_events: EventWriter<'w, Pointer<Pressed>>
.PickingEventWriters<'w>::up_events changes to PickingEventWriters<'w>::released_events
.
Rename
PickingBehavior
to Pickable
#PickingBehavior
to Pickable
.
Rename
RayCastSettings
to MeshRayCastSettings
#RayCastSettings
has been renamed to MeshRayCastSettings
to avoid naming conflicts with other ray casting backends and types.
Unify picking backends #
UiPickingPlugin
and SpritePickingPlugin
are no longer included in DefaultPlugins
. They must be explicitly added.RayCastPickable
has been replaced in favor of the MeshPickingCamera
and Pickable
components. You should add them to cameras and entities, respectively, if you have MeshPickingSettings::require_markers
set to true
.Reflection #
Include ReflectFromReflect in all dynamic data types. #
HashMap
s and HashSet
s now have to implement Default
. This is the case for the ones provided by Bevy already, and is generally a sensible thing to do.
Make
bevy_remote
feature enable serialize
feature #bevy_remote
feature of bevy
now enables the serialize
feature automatically. If you wish to use bevy_remote
without enabling the serialize
feature for Bevy subcrates, you must import bevy_remote
on its own.
Rename
ArgList::push
methods to with
and add new push
methods which take &mut self
#ArgList::push
methods should be replaced with the with
counterpart.
bevy_reflect: Deprecate
PartialReflect::clone_value
#PartialReflect::clone_value
is being deprecated. Instead, use PartialReflect::to_dynamic
if wanting to create a new dynamic instance of the reflected value. Alternatively, use PartialReflect::reflect_clone
to attempt to create a true clone of the underlying value.Array::clone_dynamic
→ Array::to_dynamic_array
Enum::clone_dynamic
→ Enum::to_dynamic_enum
List::clone_dynamic
→ List::to_dynamic_list
Map::clone_dynamic
→ Map::to_dynamic_map
Set::clone_dynamic
→ Set::to_dynamic_set
Struct::clone_dynamic
→ Struct::to_dynamic_struct
Tuple::clone_dynamic
→ Tuple::to_dynamic_tuple
TupleStruct::clone_dynamic
→ TupleStruct::to_dynamic_tuple_struct
bevy_reflect: Remove
PartialReflect::serializable
#PartialReflect::serializable
has been removed. If you were using this to pass on serialization information, use ReflectSerialize
instead or create custom type data to generate the Serializable
.
Remove unnecessary
PartialReflect
bound on DeserializeWithRegistry
#DeserializeWithRegistry
types are no longer guaranteed to be PartialReflect
as well. If you were relying on this type bound, you should add it to your own bounds manually.- impl<T: DeserializeWithRegistry> Foo for T { .. }
+ impl<T: DeserializeWithRegistry + PartialReflect> Foo for T { .. }
Rendering #
Add
uv_transform
to ColorMaterial
#uv_transform
field to constructors of ColorMaterial
Add a bindless mode to
AsBindGroup
. #RenderAssets::prepare_asset
now takes an AssetId
parameter.wgpu
material bind group IDs, as part of the bindless change. Use the new MaterialBindGroupAllocator
to map from bind group index to bind group ID.
Add bevy_anti_aliasing #
bevy::anti_aliasing
instead of bevy::core_pipeline
Adding alpha_threshold to OrderIndependentTransparencySettings for user-level optimization #
layer_count
, you will now have to add either a ..default()
statement or an explicit alpha_threshold
value:fn setup(mut commands: Commands) {
commands.spawn((
Camera3d::default(),
OrderIndependentTransparencySettings {
layer_count: 16,
..default()
},
));
}
Allowed creating uninitialized images (for use as storage textures) #
Image
data will now need to use unwrap or handle the case where no data is provided. Behaviour of new_fill slightly changed, but not in a way that is likely to affect anything. It no longer panics and will fill the whole texture instead of leaving black pixels if the data provided is not a nice factor of the size of the image.
Bind only the written parts of storage buffers. #
Change
GpuImage::size
from UVec2
to Extent3d
#GpuImage::size
is now an Extent3d
. To easily get 2D size, use size_2d()
.
Cold Specialization #
AssetEvents
has been moved into the PostUpdate
schedule.
Expose Pipeline Compilation Zero Initialize Workgroup Memory Option #
zero_initialize_workgroup_memory: false,
to ComputePipelineDescriptor
or RenderPipelineDescriptor
structs to preserve 0.14 functionality, add zero_initialize_workgroup_memory: true,
to restore bevy 0.13 functionality.
Fix sprite performance regression since retained render world #
ExtractedSprites
is now using MainEntityHashMap
for storage, which is keyed on MainEntity
.ExtractedSprite
is now stored in the render_entity
member of it.
Fix the
texture_binding_array
, specialized_mesh_pipeline
, and custom_shader_instancing
examples after the bindless change. #AsBindGroup::unprepared_bind_group
for your materials, so you must no longer panic in that function. Instead, return the new AsBindGroupError::CreateBindGroupDirectly
error, and Bevy will fall back to calling AsBindGroup::as_bind_group
as before.
Implement bindless lightmaps. #
Opaque3dBinKey::lightmap_image
field is now Opaque3dBinKey::lightmap_slab
, which is a lightweight identifier for an entire binding array of lightmaps.
Implement experimental GPU two-phase occlusion culling for the standard 3D mesh pipeline. #
bevy::render::batching::gpu_preprocessing::get_or_create_work_item_buffer
, not PreprocessWorkItemBuffers::new
. See the specialized_mesh_pipeline
example.
Introduce support for mixed lighting by allowing lights to opt out of contributing diffuse light to lightmapped objects. #
AmbientLight
resource, the IrradianceVolume
component, and the EnvironmentMapLight
component now have affects_lightmapped_meshes
fields. If you don’t need to use that field (for example, if you aren’t using lightmaps), you can safely set the field to true.DirectionalLight
, PointLight
, and SpotLight
now have affects_lightmapped_mesh_diffuse
fields. If you don’t need to use that field (for example, if you aren’t using lightmaps), you can safely set the field to true.
Introduce two-level bins for multidrawable meshes. #
BinnedPhaseItem
. The batch set key is used to collect multidrawable meshes together. If you aren’t using the multidraw feature, you can safely set the batch set key to ()
.
Key render phases off the main world view entity, not the render world view entity. #
Make indirect drawing opt-out instead of opt-in, enabling multidraw by default. #
GpuCulling
component is no longer available. To disable indirect mode, which may be useful with custom render nodes, add the new NoIndirectDrawing
component to your camera.
Make the
get
function on InstanceInputUniformBuffer
less error prone #InstanceInputUniformBuffer::get
now returns Option<BDI>
instead of BDI
to reduce panics. If you require the old functionality of InstanceInputUniformBuffer::get
consider using InstanceInputUniformBuffer::get_unchecked
.
Make the default directional light shadow cascade settings similar to those of other engines. #
Mesh::merge to return a Result #
Mesh::merge
now returns a Result<(), MeshMergeError>
.
Move
TextureAtlas
and friends into bevy_image
#bevy_sprite
to bevy_image
: TextureAtlas
, TextureAtlasBuilder
, TextureAtlasSources
, TextureAtlasLayout
and DynamicTextureAtlasBuilder
.bevy
crate, and were importing these types directly (e.g. before use bevy::sprite::TextureAtlas
), be sure to update your import paths (e.g. after use bevy::image::TextureAtlas
)bevy
prelude to import these types (e.g. use bevy::prelude::*
), you don’t need to change anything.bevy_sprite
subcrate, be sure to add bevy_image
as a dependency if you do not already have it, and be sure to update your import paths.
Move non-generic parts of the PrepassPipeline to internal field #
PrepassPipeline
, most of them have now been move to PrepassPipeline::internal
.
Native unclipped depth on supported platforms #
MeshPipelineKey::DEPTH_CLAMP_ORTHO
is now MeshPipelineKey::UNCLIPPED_DEPTH_ORTHO
DEPTH_CLAMP_ORTHO
shaderdef has been renamed to UNCLIPPED_DEPTH_ORTHO_EMULATION
clip_position_unclamped: vec4<f32>
is now unclipped_depth: f32
Newtype
Anchor
#Vec2
. The Custom
variant has been removed, instead to construct a custom Anchor
use its tuple constructor:Sprite {
anchor: Anchor(Vec2::new(0.25, 0.4)),
..default()
}
Anchor::BottomLeft
to Anchor::BOTTOM_LEFT
Anchor::Center
to Anchor::CENTER
Anchor::TopRight
to Anchor::TOP_RIGHT
Only use the AABB center for mesh visibility range testing if specified. #
VisibilityRange
component now has an extra field, use_aabb
. Generally, you can safely set it to false.
Reduce the clusterable object UBO size below 16384 for WebGL 2. #
MAX_UNIFORM_BUFFER_CLUSTERABLE_OBJECTS
has been reduced from 256
to 204
.
Refactor and simplify custom projections #
PerspectiveProjection
and OrthographicProjection
are no longer components. Use Projection
instead.Projection
with Projection::custom()
.
Remove the type parameter from
check_visibility
, and only invoke it once. #check_visibility
no longer takes a QueryFilter
, and there’s no need to add it manually to your app schedule anymore for custom rendering items. Instead, entities with custom renderable components should add the appropriate type IDs to VisibilityClass
. See custom_phase_item
for an example.
Support scale factor for image render targets #
RenderTarget::Image
now takes an ImageRenderTarget
instead of a Handle<Image>
. You can call handle.into()
to construct an ImageRenderTarget
using the same settings as before.
Upgrade to wgpu v24 #
WGPU_DX12_COMPILER
environment variable is set at runtime, it is usedstatically-linked-dxc
feature is enabled, a custom version of DXC will be statically linked into your app at compile time.dxcompiler.dll
and dxil.dll
at runtime.
Use
multi_draw_indirect_count
where available, in preparation for two-phase occlusion culling. #specialized_mesh_pipeline
example for an example of how this is done.
Use unchecked shaders for better performance #
cleanup bevy_render/lib.rs #
RenderCreation::Manual
variant fields are now wrapped in a struct called RenderResources
doc: fix camera link #
ExtractedSprites
slice buffer #ExtractedSprite
has a new kind: ExtractedSpriteKind
field with variants Single
and Slices
.Single
represents a single sprite. ExtractedSprite
’s anchor
, rect
, scaling_mode
and custom_size
fields have been moved into Single
.Slices
contains a range that indexes into a new resource ExtractedSlices
. Slices are used to draw elements composed from multiple sprites such as text or nine-patched borders.ComputedTextureSlices::extract_sprites
has been renamed to extract_slices
. Its transform
and original_entity
parameters have been removed.
Improved
UiImage
and Sprite
scaling and slicing APIs #ImageScaleMode
component has been removed. Instead, SpriteImageMode
and NodeImageMode
have been created for a new field image_mode
on both Sprite
and UiImage
(
UiImage::new(image.clone()),
ImageScaleMode::Sliced(slicer.clone()),
)
(
UiImage::new(image.clone())
.with_mode(NodeImageMode::Sliced(slicer.clone())),
)
Rename
DefaultCameraView
#DefaultCameraView
has been renamed to UiCameraView
Rename
TargetCamera
to UiTargetCamera
#TargetCamera
has been renamed to UiTargetCamera
.
BorderRect
maintenance #square
and rectangle
functions belonging to BorderRect
have been renamed to all
and axes
.Scenes #
Only despawn scene entities still in the hierarchy #
SceneSpawner::despawn_instance()
instead.Tasks #
Support
on_thread_spawn
and on_thread_destroy
for TaskPoolPlugin
#TaskPooolThreadAssignmentPolicy
now has two additional fields: on_thread_spawn
and on_thread_destroy
. Please consider defaulting them to None
.Text #
Add byte information to
PositionedGlyph
#PositionedGlyph::new()
has been removed as there is no longer an unused field. Create new PositionedGlyph
s directly.
Remove the
atlas_scaling
field from ExtractedUiItem::Gylphs
. #atlas_scaling
field from ExtractedUiItem::Gylphs
has been removed. This shouldn’t affect any existing code as it wasn’t used for anything.
add line height to
TextFont
#TextFont
now has a line_height
field. Any instantiation of TextFont
that doesn’t have ..default()
will need to add this field.UI #
Fixing
ValArithmeticError
typo and unused variant #ValArithmeticError::NonEvaluateable
has been renamed to NonEvaluateable::NonEvaluable
ValArithmeticError::NonIdenticalVariants
has been removed
Move TextureAtlas into UiImage and remove impl Component for TextureAtlas #
commands.spawn((
UiImage::new(image),
TextureAtlas { index, layout },
));
commands.spawn(UiImage::from_atlas_image(image, TextureAtlas { index, layout }));
commands.spawn(UiImage {
texture: some_image,
..default()
})
commands.spawn(UiImage {
image: some_image,
..default()
})
Multiple box shadow support #
ShadowStyle
is used to set the style for each shadow. And the BoxShadow
component is changed to a tuple struct wrapping a vector containing a list of ShadowStyle
s. To spawn a node with a single shadow you can use the new
constructor function:commands.spawn((
Node::default(),
BoxShadow::new(
Color::BLACK.with_alpha(0.8),
Val::Percent(offset.x),
Val::Percent(offset.y),
Val::Percent(spread),
Val::Px(blur),
)
));
Only use physical coords internally in
bevy_ui
#ComputedNode
’s fields and methods now use physical coordinates. ComputedNode
has a new field inverse_scale_factor
. Multiplying the physical coordinates by the inverse_scale_factor
will give the logical values.
Remove custom rounding #
UiSurface::get_layout
now also returns the final sizes before rounding. Call .0
on the Ok
result to get the previously returned taffy::Layout
value.
Remove the
min
and max
fields from LayoutContext
. #min
and max
fields have been removed from LayoutContext
. To retrieve these values call min_element
and max_element
on LayoutContent::physical_size
instead.
Rename
UiBoxShadowSamples
to BoxShadowSamples
. #UiBoxShadowSamples
has been renamed to BoxShadowSamples
UiImage -> ImageNode, UiImageSize -> ImageNodeSize #
commands.spawn(UiImage::new(image));
commands.spawn(ImageNode::new(image));
Windowing #
Make CustomCursor variants CustomCursorImage/CustomCursorUrl structs #
CustomCursor
enum’s variants now hold instances of CustomCursorImage
or CustomCursorUrl
. Update your uses of CustomCursor
accordingly.
Make
RawHandleWrapper
fields private to save users from themselves #window_handle
and display_handle
fields on RawHandleWrapper
are no longer public. Use the newly added getters and setters to manipulate them instead.
Rework WindowMode::Fullscreen API #
WindowMode::SizedFullscreen(MonitorSelection)
and WindowMode::Fullscreen(MonitorSelection)
has become WindowMode::Fullscreen(MonitorSelection, VideoModeSelection)
. Previously, the VideoMode was selected based on the closest resolution to the current window size for SizedFullscreen and the largest resolution for Fullscreen. It is possible to replicate that behaviour by searching Monitor::video_modes
and selecting it with VideoModeSelection::Specific(VideoMode)
but it is recommended to use VideoModeSelection::Current
as the default video mode when entering fullscreen.
Support texture atlases in CustomCursor::Image #
CustomCursor::Image
enum variant has some new fields. Update your code to set them.CustomCursor::Image {
handle: asset_server.load("branding/icon.png"),
hotspot: (128, 128),
}
CustomCursor::Image {
handle: asset_server.load("branding/icon.png"),
texture_atlas: None,
flip_x: false,
flip_y: false,
rect: None,
hotspot: (128, 128),
}
Without area #
:pencil2: Fix typos across bevy #
reparameterize
change here)
Link iOS example with
rustc
, and avoid C trampoline ##[bevy_main]
attribute created a main_rs
entry point that most Xcode templates were using to run your Rust code from C. This was found to be unnecessary, as you can simply let Rust build your application as a binary, and run that directly.#[no_mangle] extern "C" main_rs() { main() }
to your main.rs
. Note that the old approach of linking a static library prevents the Rust standard library from doing runtime initialization, so certain functionality provided by std
might be unavailable (stack overflow handlers, stdout/stderr flushing and other such functionality provided by the initialization routines).cargo build --bin ...
, and moves the built binary to the Xcode path $TARGET_BUILD_DIR/$EXECUTABLE_PATH
. An example of how to do this can be viewed at [INSERT LINK TO UPDATED EXAMPLE PROJECT]. To make the debugging experience in Xcode nicer after this, you might also want to consider either enabling panic = "abort"
or to set a breakpoint on the rust_panic
symbol.
Remove Image::from_buffer
name
argument (only present in debug "dds" builds) #Image::from_buffer()
no longer has a name
argument that’s only present in debug builds when the "dds"
feature is enabled. If you happen to pass a name, remove it.
Remove
bevy_core
#bevy_core
has been removed and its items moved into more appropriate locations. Below are some tables showing where items have been moved toItem 0.15 Path 0.16 Path FrameCount
bevy_core
bevy_diagnostic
FrameCountPlugin
bevy_core
bevy_diagnostic
Name
bevy_core
bevy_ecs::name
NameOrEntity
bevy_core
bevy_ecs::name
NameOrEntityItem
bevy_core
bevy_ecs::name
NonSendMarker
bevy_core
bevy_app
TaskPoolOptions
bevy_core
bevy_app
TaskPoolPlugin
bevy_core
bevy_app
TaskPoolThreadAssignmentPolicy
bevy_core
bevy_app
TypeRegistrationPlugin
bevy_core
Removed Item 0.15 Path 0.16 Path update_frame_count
bevy_core
bevy_diagnostic
TypeRegistrationPlugin
no longer exists. If you can’t use a default App
but still need Name
registered, do so manually.// Before
app.add_plugins(TypeRegistrationPlugin);
// After
app.register_type::<Name>();
```.
Rename
trigger.entity()
to trigger.target()
#Trigger::entity()
to Trigger::target()
.ObserverTrigger::entity
to ObserverTrigger::target
Use 4-byte LightmapSlabIndex for batching instead of 16-byte
AssetId<Image>
#RenderLightmap::new()
no longer takes an AssetId<Image>
argument for the asset id of the lightmap image.
Use
target_abi = "sim"
instead of ios_simulator
feature #ios_simulator
feature from your Cargo.toml
(Bevy now handles this internally).Utils #
bevy_utils
Refactor #bevy_utils
(and by extension bevy::utils
) was significantly reduced with many of its items either being removed, spun-out into their own crates, or just moved into more appropriate existing crates. Below is a series of tables for all items that were in bevy_utils
0.15 that have since been moved or removed in 0.16.Item 0.15 Path 0.16 Path hashbrown
bevy_utils
Removed tracing
bevy_utils
bevy_log
Item 0.15 Path 0.16 Path AHasher
bevy_utils
ahash
Duration
bevy_utils
core::time
FixedState
bevy_utils
bevy_platform_support::hash
Hashed
bevy_utils
bevy_platform_support::hash
Instant
bevy_utils
bevy_platform_support::time
NoOpHash
bevy_utils
bevy_platform_support::time
PassHash
bevy_utils
bevy_platform_support::time
PassHasher
bevy_utils
bevy_platform_support::time
RandomState
bevy_utils
bevy_platform_support::time
SystemTime
bevy_utils
std::time
SystemTimeError
bevy_utils
std::time
TryFromFloatSecsError
bevy_utils
core::time
Item 0.15 Path 0.16 Path ConditionalSend
bevy_utils
bevy_tasks
ConditionalSendFuture
bevy_utils
bevy_tasks
Item 0.15 Path 0.16 Path all_tuples
bevy_utils
variadics_please
all_tuples_with_size
bevy_utils
variadics_please
debug_once
bevy_utils
bevy_log
detailed_trace
bevy_utils
Removed error_once
bevy_utils
bevy_log
info_once
bevy_utils
bevy_log
trace_once
bevy_utils
bevy_log
warn_once
bevy_utils
bevy_log
Item 0.15 Path 0.16 Path assert_object_safe
bevy_utils
Removed dbg
bevy_utils
Removed error
bevy_utils
Removed check_ready
bevy_utils::futures
bevy_tasks::futures
now_or_never
bevy_utils::futures
bevy_tasks::futures
info
bevy_utils
Removed warn
bevy_utils
Removed Item 0.15 Path 0.16 Path BoxedFuture
bevy_utils
bevy_tasks
Entry
bevy_utils
bevy_platform_support::collections::hash_map
HashMap
bevy_utils
bevy_platform_support::collections
HashSet
bevy_utils
bevy_platform_support::collections
StableHashMap
bevy_utils
Removed StableHashSet
bevy_utils
Removed assert_object_safe
was removed in part because the term is now outdated (replaced with dyn compatibility) and otherwise because it is trivial to inline.// Before
const _: () = assert_object_safe::<dyn MyTrait>();
// After
const _: Option<Box<dyn MyTrait>> = None;
hashbrown
was removed from bevy_utils
as a re-export due to its significant API change from hashbrown
0.14 to 0.15. Instead of exposing a large public API out of our direct control, we've taken a more explicit subset and moved it into bevy_platform_support::collections
, mimicking the layout of the standard library. If you need access to hashbrown
, take a direct dependency instead.detailed_trace
was removed due to its minimal use within the engine. If you still wish to use it, make sure you have taken a direct dependency on tracing
and have a feature name detailed_trace
defined in your Cargo.toml
. You can use the below as a replacement:macro_rules! detailed_trace {
($($tts:tt)*) => {
if cfg!(feature = "detailed_trace") {
::tracing::trace!($($tts)*);
}
}
}
dbg
, info
, warn
, and error
were all removed due to minimal use within the engine. If you still wish to use them, make sure you have taken a direct dependency on tracing
. You can use the below as a replacement:/// Calls the [`tracing::info!`] macro on a value.
pub fn info<T: core::fmt::Debug>(data: T) {
::tracing::info!("{:?}", data);
}
/// Calls the [`tracing::debug!`] macro on a value.
pub fn dbg<T: core::fmt::Debug>(data: T) {
::tracing::debug!("{:?}", data);
}
/// Processes a [`Result`] by calling the [`tracing::warn!`] macro in case of an [`Err`] value.
pub fn warn<E: core::fmt::Debug>(result: Result<(), E>) {
if let Err(warn) = result {
::tracing::warn!("{:?}", warn);
}
}
/// Processes a [`Result`] by calling the [`tracing::error!`] macro in case of an [`Err`] value.
pub fn error<E: core::fmt::Debug>(result: Result<(), E>) {
if let Err(error) = result {
::tracing::error!("{:?}", error);
}
}
StableHashMap
and StableHashSet
were removed due to minimal use within the engine. You can use the below as a replacement:/// A stable hash-map.
pub type StableHashMap<K, V> = bevy::platform_support::collections::HashMap<K, V, bevy::platform_support::hash::FixedState>;
/// A stable hash-set.
pub type StableHashSet<K> = bevy::platform_support::collections::HashSet<K, bevy::platform_support::hash::FixedState>;