- 0.9 to 0.10
- Migrate engine to Schedule v3 (stageless)
- Windows as Entities
- Make the SystemParam derive macro more flexible
- Basic adaptive batching for parallel query iteration
- Enum Visibility component
- bevy_reflect: Pre-parsed paths
- Remove App::add_sub_app
- Make HandleUntyped::id private
- Break CorePlugin into TaskPoolPlugin, TypeRegistrationPlugin, FrameCountPlugin.
- Immutable sparse sets for metadata storage
- Split Component Ticks
- Document and lock down types in bevy_ecs::archetype
- Lock down access to Entities
- Borrow instead of consuming in EventReader::clear
- Newtype ArchetypeRow and TableRow
- Round out the untyped APIs
- Extend EntityLocation with TableId and TableRow
- Remove ExclusiveSystemParam::apply
- Remove the SystemParamState trait and remove types like ResState
- Panic on dropping NonSend in non-origin thread.
- Document alignment requirements of Ptr, PtrMut and OwningPtr
- Added resource_id and changed init_resource and init_non_send_resource to return ComponentId
- Replace RemovedComponents<T> backing with Events<Entity>
- Remove broken DoubleEndedIterator impls on event iterators
- Rename Tick::is_older_than to Tick::is_newer_than
- Cleanup system sets called labels
- Simplify generics for the SystemParamFunction trait
- Deprecate ChangeTrackers<T> in favor of Ref<T>
- EntityMut: rename remove_intersection to remove and remove to take
- bevy_ecs: ReflectComponentFns without World
- Allow iterating over with EntityRef over the entire World
- Remove BuildWorldChildren impl from WorldChildBuilder
- Rename dynamic feature
- bevy_reflect: add insert and remove methods to List
- bevy_reflect: Decouple List and Array traits
- bevy_reflect: Remove ReflectSerialize and ReflectDeserialize registrations from most glam types
- Add AutoMax next to ScalingMode::AutoMin
- Change From<Icosphere> to TryFrom<Icosphere>
- Add try_* to add_slot_edge, add_node_edge
- Shader defs can now have a value
- Get pixel size from wgpu
- Run clear trackers on render world
- Rename camera "priority" to "order"
- Reduce branching in TrackedRenderPass
- Make PipelineCache internally mutable.
- Changed Msaa to Enum
- Support recording multiple CommandBuffers in RenderContext
- Improve OrthographicCamera consistency and usability
- Changed &mut PipelineCache to &PipelineCache
- Introduce detailed_trace macro, use in TrackedRenderPass
- Added subdivisions to shape::Plane
- Change standard material defaults and update docs
- Remove dead code after #7784
- Directly extract joints into SkinnedMeshJoints
- Intepret glTF colors as linear instead of sRGB
- Send emissive color to uniform as linear instead of sRGB
- The update_frame_count system should be placed in CorePlugin
- Pipelined Rendering
- Remove ImageMode
- Rename the background_color of 'ExtractedUiNodetocolor`
- Remove the GlobalTransform::translation_mut method
- Flip UI image
- Remove TextError::ExceedMaxTextAtlases(usize) variant
- Change default FocusPolicy to Pass
- Remove VerticalAlign from TextAlignment
- Remove QueuedText
- Change the default width and height of Size to Val::Auto
- Fix the Size helper functions using the wrong default value and improve the UI examples
- The size field of CalculatedSize should not be a Size
- Update winit to 0.28
Migration Guide: 0.9 to 0.10
Bevy relies heavily on improvements in the Rust language and compiler. As a result, the Minimum Supported Rust Version (MSRV) is "the latest stable release" of Rust.
Migrate engine to Schedule v3 (stageless) #
Calls to
.label(MyLabel)
should be replaced with.in_set(MySet)
SystemLabel
derives should be replaced withSystemSet
. You will also need to add theDebug
,PartialEq
,Eq
, andHash
traits to satisfy the new trait bounds.Stages have been removed. Replace these with system sets, and then add command flushes using the
apply_system_buffers
exclusive system where needed.The
CoreStage
,StartupStage
,RenderStage
, andAssetStage
enums have been replaced withCoreSet
,StartupSet
,RenderSet
andAssetSet
. The same scheduling guarantees have been preserved.with_run_criteria
has been renamed torun_if
. Run criteria have been renamed to run conditions for clarity, and should now simply return abool
instead ofschedule::ShouldRun
.Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow.
App::add_state
now takes 0 arguments: the starting state is set based on theDefault
impl.Instead of creating
SystemSet
containers for systems that run in stages, usemy_system.in_schedule(OnEnter(State::Variant))
or itsOnExit
sibling.For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the
CoreSchedule::Outer
label.Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The
run_fixed_timestep
system runs this schedule betweenCoreSet::First
andCoreSet::PreUpdate
by default.Command flush points introduced by
AssetStage
have been removed. If you were relying on these, add them back manually.The
calculate_bounds
system, with theCalculateBounds
label, is now inCoreSet::Update
, rather than inCoreSet::PostUpdate
before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior.The
RenderLabel
AppLabel
was renamed toRenderApp
for clarityWhen testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using
Schedule::new()
andWorld::run_schedule
rather than constructing stagesStates have been dramatically simplified: there is no longer a “state stack”. To queue a transition to the next state, call
NextState::set
Strings can no longer be used as a
SystemLabel
orSystemSet
. Use a type, or use the system function instead.
Stages #
Stages had two key elements: they ran one after another, and they applied commands at their end.
The former can be replaced by system sets (unless you need branching or looping scheduling logic, in which case you should use a schedule), and the latter can be controlled manually via apply_system_buffers
.
To migrate from Bevy's built-in stages, we've provided the CoreSet
, StartupSet
and RenderSet
system sets. Command flushes have already been added to these, but if you have added custom stages you may need to add your own if you were relying on that behavior.
Before:
app
.add_system_to_stage(CoreStage::PostUpdate, my_system)
.add_startup_system_to_stage(StartupStage::PostStartup, my_startup_system);
After:
app
.add_system(my_system.in_base_set(CoreSet::PostUpdate))
.add_startup_system(my_startup_system.in_base_set(StartupSet::PostStartup));
If you had your own stage:
// Bevy 0.9
#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)]
pub struct AfterUpdate;
app.add_stage_after(CoreStage::Update, AfterUpdate, SystemStage::parallel());
// Bevy 0.10, no command flush
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
#[system_set(base)]
pub struct AfterUpdate;
app.configure_set(
AfterUpdate
.after(CoreSet::UpdateFlush)
.before(CoreSet::PostUpdate),
);
// Bevy 0.10, with a command flush
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
#[system_set(base)]
pub enum AfterUpdate {
Parallel,
CommandFlush
}
app.configure_sets(
(
CoreSet::UpdateFlush,
AfterUpdate::Parallel,
AfterUpdate::CommandFlush,
CoreSet::PostUpdate,
).chain()
).add_system(apply_system_buffers.in_base_set(AfterUpdate::CommandFlush));
Label types #
System labels have been renamed to systems sets and unified with stage labels. The StageLabel
trait should be replaced by a system set, using the SystemSet
trait as discussed immediately below.
Before:
#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)]
enum MyStage {
BeforeRound,
AfterRound,
}
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemLabel)]
enum MySystem {
ComputeForces,
FindCollisions,
}
After:
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
enum MySet {
BeforeRound,
AfterRound,
}
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
enum MySystem {
ComputeForces,
FindCollisions,
}
System sets (Bevy 0.9) #
In Bevy 0.9, you could use the SystemSet
type and various methods to configure many systems at once. Additionally, this was the only way to interact with various scheduling APIs like run criteria.
Before:
app.add_system_set(SystemSet::new().with_system(a).with_system(b).with_run_criteria(my_run_criteria));
After:
app.add_systems((a, b).run_if(my_run_condition));
Ambiguity detection #
The ReportExecutionOrderAmbiguities
resource has been removed. Instead, this is configured on a per-schedule basis.
app.edit_schedule(CoreSchedule::Main, |schedule| {
schedule.set_build_settings(ScheduleBuildSettings {
ambiguity_detection: LogLevel::Warn,
..default()
});
})
Fixed timesteps #
The FixedTimestep
run criteria has been removed, and is now handled by either a schedule or the on_timer
/ on_fixed_timer
run conditions.
Before:
app.add_stage_after(
CoreStage::Update,
FixedUpdateStage,
SystemStage::parallel()
.with_run_criteria(
FixedTimestep::step(0.5)
)
.with_system(fixed_update),
);
After:
// This will affect the update frequency of fixed time for your entire app
app.insert_resource(FixedTime::new_from_secs(0.5))
// This schedule is automatically added with DefaultPlugins
.add_system(fixed_update.in_schedule(CoreSchedule::FixedUpdate));
Apps may now only have one unified fixed timestep. CoreSchedule::FixedTimestep
is intended to be used for determinism and stability during networks, physics and game mechanics. Unlike timers, it will run repeatedly if more than a single period of time has elapsed since it was last run.
It is not intended to serve as a looping timer to regularly perform work or poll. If you were relying on multiple FixedTimestep
run criteria with distinct periods, you should swap to using timers, via the on_timer(MY_PERIOD)
or on_fixed_timer(MY_PERIOD)
run conditions.
Before:
app.add_system_set(
SystemSet::new()
.with_run_criteria(FixedTimestep::step(0.5))
.with_system(update_pathfinding),
)
.add_system_set(
SystemSet::new()
.with_run_criteria(FixedTimestep::step(0.1))
.with_system(apply_damage_over_time),
);
After:
app
.add_system(update_pathfinding.run_if(on_timer(Duration::from_secs_f32(0.5))))
.add_system(apply_damage_over_time.run_if(on_timer(Duration::from_secs_f32(0.1))));
States #
States have been significantly simplied and no longer have a state stack. Each state type (usually an enum), requires the States
trait, typically implemented via the derive macro.
For example:
#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States)]
enum AppState {
#[default]
Menu,
InGame,
}
App::add_state
no longer takes an argument: the starting state is now controlled via the Default
impl for your state type.
To access the current state of the States
type above, use Res<State<AppState>
, and access the tuple field via .0
. To queue up a state transition, use ResMut<NextState<AppState>>
and call .set(AppState::Menu)
.
State transitions are now applied via the apply_state_transitions
exclusive system, a copy of which is added CoreSet::StateTransitions
when you call App::add_state
. You can add more copies as needed, specific to the state being applied.
OnEnter
and OnExit
systems now live in schedules, run on the World
via the apply_state_transitions
system. By contrast, OnUpdate
is now a system set which is nested within CoreSet::Update
.
Before:
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
enum AppState {
Menu,
InGame,
}
app.add_state(AppState::Menu)
.add_system_set(SystemSet::on_enter(AppState::Menu).with_system(setup_menu))
.add_system_set(SystemSet::on_update(AppState::Menu).with_system(menu))
.add_system_set(SystemSet::on_exit(AppState::Menu).with_system(cleanup_menu))
After:
#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States)]
enum AppState {
#[default]
Menu,
InGame,
}
app.add_state::<AppState>()
.add_system(setup_menu.in_schedule(OnEnter(AppState::Menu)))
.add_system(menu.in_set(OnUpdate(AppState::Menu)))
.add_system(cleanup_menu.in_schedule(OnExit(AppState::Menu)));
When you need to run your state-specific systems outside of CoreSet::Update
, you can use the built-in in_state
run condition.
Windows as Entities #
Replace WindowDescriptor
with Window
.
Change width
and height
fields into a WindowResolution
, either by doing
WindowResolution::new(width, height) // Explicitly
// or using From<_> for tuples for convenience
(1920., 1080.).into()
Replace any WindowCommand
code to just modify the Window
’s fields directly and creating/closing windows is now by spawning/despawning an entity with a Window
component like so:
let window = commands.spawn(Window { ... }).id(); // open window
commands.entity(window).despawn(); // close window
To get a window, you now need to use a Query
instead of a Res
// 0.9
fn count_pixels(windows: Res<Windows>) {
let Some(primary) = windows.get_primary() else {
return;
};
println!("{}", primary.width() * primary.height());
}
// 0.10
fn count_pixels(primary_query: Query<&Window, With<PrimaryWindow>>) {
let Ok(primary) = primary_query.get_single() else {
return;
};
println!("{}", primary.width() * primary.height());
}
Make the SystemParam
derive macro more flexible #
The lifetime 's
has been removed from EventWriter
. Any code that explicitly specified the lifetimes for this type will need to be updated.
// 0.9
#[derive(SystemParam)]
struct MessageWriter<'w, 's> {
events: EventWriter<'w, 's, Message>,
}
// 0.10
#[derive(SystemParam)]
struct MessageWriter<'w> {
events: EventWriter<'w, Message>,
}
Basic adaptive batching for parallel query iteration #
The batch_size
parameter for Query(State)::par_for_each(_mut)
has been removed. These calls will automatically compute a batch size for you. Remove these parameters from all calls to these functions.
// 0.9
fn parallel_system(query: Query<&MyComponent>) {
query.par_for_each(32, |comp| {
...
});
}
// 0.10
fn parallel_system(query: Query<&MyComponent>) {
query.par_iter().for_each(|comp| {
...
});
}
Enum Visibility
component #
- Evaluation of the
visibility.is_visible
field should now check forvisibility == Visibility::Inherited
. - Setting the
visibility.is_visible
field should now directly set the value:*visibility = Visibility::Inherited
. - Usage of
Visibility::VISIBLE
orVisibility::INVISIBLE
should now useVisibility::Inherited
orVisibility::Hidden
respectively. ComputedVisibility::INVISIBLE
andSpatialBundle::VISIBLE_IDENTITY
have been renamed toComputedVisibility::HIDDEN
andSpatialBundle::INHERITED_IDENTITY
respectively.
bevy_reflect: Pre-parsed paths #
GetPath
methods have been renamed according to the following:
path
->reflect_path
path_mut
->reflect_path_mut
get_path
->path
get_path_mut
->path_mut
Remove App::add_sub_app #
App::add_sub_app
has been removed in favor of App::insert_sub_app
. Use SubApp::new
and insert it via App::insert_sub_app
// 0.9
let mut sub_app = App::new()
// Build subapp here
app.add_sub_app(MySubAppLabel, sub_app, extract_fn);
// 0.10
let mut sub_app = App::new()
// Build subapp here
app.insert_sub_app(MySubAppLabel, SubApp::new(sub_app, extract_fn));
Make HandleUntyped::id private #
Instead of directly accessing the ID of a HandleUntyped
as handle.id
, use the new getter handle.id()
.
Break CorePlugin
into TaskPoolPlugin
, TypeRegistrationPlugin
, FrameCountPlugin
. #
CorePlugin
was broken into separate plugins. If not using DefaultPlugins
or MinimalPlugins
PluginGroup
s, the replacement for CorePlugin
is now to add TaskPoolPlugin
, TypeRegistrationPlugin
, and FrameCountPlugin
to the app.
Immutable sparse sets for metadata storage #
Table::component_capacity()
has been removed as Tables do not support adding/removing columns after construction.
Split Component Ticks #
Various low level APIs interacting with the change detection ticks no longer return &UnsafeCell<ComponentTicks>
, instead returning TickCells
which contains two separate &UnsafeCell<Tick>
s instead.
// 0.9
column.get_ticks(row).deref().changed
// 0.10
column.get_ticks(row).changed.deref()
Document and lock down types in bevy_ecs::archetype #
ArchetypeId
, ArchetypeGeneration
, and ArchetypeComponentId
are all now opaque IDs and cannot be turned into a numeric value. Please file an issue if this does not work for your use case or check bevy_ecs is excessively public for more info.
Archetype
and Archetypes
are not constructible outside of bevy_ecs
now. Use World::archetypes
to get a read-only reference to either of these types.
Lock down access to Entities #
Entities
’s Default
implementation has been removed. You can fetch a reference to a World
’s Entities
via World::entities
and World::entities_mut
.
Entities::alloc_at_without_replacement
and AllocAtWithoutReplacement
has been made private due to difficulty in using it properly outside of bevy_ecs
. If you still need use of this API, please file an issue or check bevy_ecs is excessively public for more info.
Borrow instead of consuming in EventReader::clear
#
EventReader::clear
now takes a mutable reference instead of consuming the event reader. This means that clear
now needs explicit mutable access to the reader variable, which previously could have been omitted in some cases:
// Old (0.9)
fn clear_events(reader: EventReader<SomeEvent>) {
reader.clear();
}
// New (0.10)
fn clear_events(mut reader: EventReader<SomeEvent>) {
reader.clear();
}
Newtype ArchetypeRow and TableRow #
Archetype
indices and Table
rows have been newtyped as ArchetypeRow
and TableRow
.
Round out the untyped APIs #
MutUntyped::into_inner
now marks things as changed.
Extend EntityLocation with TableId and TableRow #
A World
can only hold a maximum of 232 - 1 archetypes and tables now. If your use case requires more than this, please file an issue explaining your use case.
Remove ExclusiveSystemParam::apply
#
The trait method ExclusiveSystemParamState::apply
has been removed. If you have an exclusive system with buffers that must be applied, you should apply them within the body of the exclusive system.
Remove the SystemParamState
trait and remove types like ResState
#
The traits SystemParamState
and SystemParamFetch
have been removed, and their functionality has been transferred to SystemParam
.
The trait ReadOnlySystemParamFetch
has been replaced with ReadOnlySystemParam
.
// 0.9
impl SystemParam for MyParam<'_, '_> {
type State = MyParamState;
}
unsafe impl SystemParamState for MyParamState {
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... }
}
unsafe impl<'w, 's> SystemParamFetch<'w, 's> for MyParamState {
type Item = MyParam<'w, 's>;
fn get_param(&mut self, ...) -> Self::Item;
}
unsafe impl ReadOnlySystemParamFetch for MyParamState { }
// 0.10
unsafe impl SystemParam for MyParam<'_, '_> {
type State = MyParamState;
type Item<'w, 's> = MyParam<'w, 's>;
fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { ... }
fn get_param<'w, 's>(state: &mut Self::State, ...) -> Self::Item<'w, 's>;
}
unsafe impl ReadOnlySystemParam for MyParam<'_, '_> { }
Panic on dropping NonSend in non-origin thread. #
Normal resources and NonSend
resources no longer share the same backing storage. If R: Resource
, then NonSend<R>
and Res<R>
will return different instances from each other. If you are using both Res<T>
and NonSend<T>
(or their mutable variants), to fetch the same resources, it’s strongly advised to use Res<T>
.
Document alignment requirements of Ptr
, PtrMut
and OwningPtr
#
Safety invariants on bevy_ptr
types’ new
byte_add
and byte_offset
methods have been changed. All callers should re-audit for soundness.
Added resource_id
and changed init_resource
and init_non_send_resource
to return ComponentId
#
- Added
Components::resource_id
. - Changed
World::init_resource
to return the generatedComponentId
. - Changed
World::init_non_send_resource
to return the generatedComponentId
.
Replace RemovedComponents<T>
backing with Events<Entity>
#
- Add a
mut
forremoved: RemovedComponents<T>
since we are now modifying an event reader internally. - Iterating over removed components now requires
&mut removed_components
orremoved_components.iter()
instead of&removed_components
.
Remove broken DoubleEndedIterator
impls on event iterators #
ManualEventIterator
and ManualEventIteratorWithId
are no longer DoubleEndedIterator
s since the impls didn't work correctly, and any code using this was likely broken.
Rename Tick::is_older_than
to Tick::is_newer_than
#
Replace usages of Tick::is_older_than
with Tick::is_newer_than
.
Cleanup system sets called labels #
PrepareAssetLabel
is now called PrepareAssetSet
Simplify generics for the SystemParamFunction
trait #
For the SystemParamFunction
trait, the type parameters In
, Out
, and Param
have been turned into associated types.
// 0.9
fn my_generic_system<T, In, Out, Param, Marker>(system_function: T)
where
T: SystemParamFunction<In, Out, Param, Marker>,
Param: SystemParam,
{ ... }
// 0.10
fn my_generic_system<T, Marker>(system_function: T)
where
T: SystemParamFunction<Marker>,
{ ... }
For the ExclusiveSystemParamFunction
trait, the type parameter Param
has been turned into an associated type. Also, In
and Out
associated types have been added, since exclusive systems now support system piping.
// 0.9
fn my_exclusive_system<T, Param, Marker>(system_function: T)
where
T: ExclusiveSystemParamFunction<Param, Marker>,
T: Param: ExclusiveSystemParam,
{ ... }
// 0.10
fn my_exclusive_system<T, Marker>(system_function: T)
where
T: ExclusiveSystemParamFunction<Marker>,
{ ... }
Deprecate ChangeTrackers<T>
in favor of Ref<T>
#
ChangeTrackers<T>
has been deprecated, and will be removed in the next release. Any usage should be replaced with Ref<T>
.
// 0.9
fn my_system(q: Query<(&MyComponent, ChangeTrackers<MyComponent>)>) {
for (value, trackers) in &q {
if trackers.is_changed() {
// Do something with `value`.
}
}
}
// 0.10
fn my_system(q: Query<Ref<MyComponent>>) {
for value in &q {
if value.is_changed() {
// Do something with `value`.
}
}
}
EntityMut
: rename remove_intersection
to remove
and remove
to take
#
// 0.9
fn clear_children(parent: Entity, world: &mut World) {
if let Some(children) = world.entity_mut(parent).remove::<Children>() {
for &child in &children.0 {
world.entity_mut(child).remove_intersection::<Parent>();
}
}
}
// 0.10
fn clear_children(parent: Entity, world: &mut World) {
if let Some(children) = world.entity_mut(parent).take::<Children>() {
for &child in &children.0 {
world.entity_mut(child).remove::<Parent>();
}
}
}
bevy_ecs: ReflectComponentFns without World #
Call World::entity
before calling into the changed ReflectComponent
methods, most likely user already has a EntityRef
or EntityMut
which was being queried redundantly.
Allow iterating over with EntityRef over the entire World #
World::iter_entities
now returns an iterator of EntityRef
instead of Entity
. To get the actual ID, use EntityRef::id
from the returned EntityRef
s.
Remove BuildWorldChildren
impl from WorldChildBuilder
#
Hierarchy editing methods such as with_children
and push_children
have been removed from WorldChildBuilder
. You can edit the hierarchy via EntityMut
instead.
Rename dynamic feature #
dynamic
feature was renamed to dynamic_linking
bevy_reflect: add insert
and remove
methods to List
#
Manual implementors of List
need to implement the new methods insert
and remove
and consider whether to use the new default implementation of push
and pop
.
bevy_reflect: Decouple List
and Array
traits #
The List
trait is no longer dependent on Array
. Implementors of List
can remove the Array
impl and move its methods into the List
impl (with only a couple tweaks).
// 0.9
impl Array for Foo {
fn get(&self, index: usize) -> Option<&dyn Reflect> {/* ... */}
fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {/* ... */}
fn len(&self) -> usize {/* ... */}
fn is_empty(&self) -> bool {/* ... */}
fn iter(&self) -> ArrayIter {/* ... */}
fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>> {/* ... */}
fn clone_dynamic(&self) -> DynamicArray {/* ... */}
}
impl List for Foo {
fn insert(&mut self, index: usize, element: Box<dyn Reflect>) {/* ... */}
fn remove(&mut self, index: usize) -> Box<dyn Reflect> {/* ... */}
fn push(&mut self, value: Box<dyn Reflect>) {/* ... */}
fn pop(&mut self) -> Option<Box<dyn Reflect>> {/* ... */}
fn clone_dynamic(&self) -> DynamicList {/* ... */}
}
// 0.10
impl List for Foo {
fn get(&self, index: usize) -> Option<&dyn Reflect> {/* ... */}
fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {/* ... */}
fn insert(&mut self, index: usize, element: Box<dyn Reflect>) {/* ... */}
fn remove(&mut self, index: usize) -> Box<dyn Reflect> {/* ... */}
fn push(&mut self, value: Box<dyn Reflect>) {/* ... */}
fn pop(&mut self) -> Option<Box<dyn Reflect>> {/* ... */}
fn len(&self) -> usize {/* ... */}
fn is_empty(&self) -> bool {/* ... */}
fn iter(&self) -> ListIter {/* ... */}
fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>> {/* ... */}
fn clone_dynamic(&self) -> DynamicList {/* ... */}
}
Some other small tweaks that will need to be made include:
- Use
ListIter
forList::iter
instead ofArrayIter
(the return type fromArray::iter
) - Replace
array_hash
withlist_hash
inReflect::reflect_hash
for implementors ofList
bevy_reflect: Remove ReflectSerialize
and ReflectDeserialize
registrations from most glam types #
This PR removes ReflectSerialize
and ReflectDeserialize
registrations from most glam types. This means any code relying on either of those type data existing for those glam types will need to not do that.
This also means that some serialized glam types will need to be updated. For example, here is Affine3A
:
// 0.9
(
"glam::f32::affine3a::Affine3A": (1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0),
// 0.10
"glam::f32::affine3a::Affine3A": (
matrix3: (
x_axis: (
x: 1.0,
y: 0.0,
z: 0.0,
),
y_axis: (
x: 0.0,
y: 1.0,
z: 0.0,
),
z_axis: (
x: 0.0,
y: 0.0,
z: 1.0,
),
),
translation: (
x: 0.0,
y: 0.0,
z: 0.0,
),
)
)
Add AutoMax next to ScalingMode::AutoMin #
Rename ScalingMode::Auto
to ScalingMode::AutoMin
.
Change From<Icosphere>
to TryFrom<Icosphere>
#
// 0.9
shape::Icosphere {
radius: 0.5,
subdivisions: 5,
}
.into()
// 0.10
shape::Icosphere {
radius: 0.5,
subdivisions: 5,
}
.try_into()
.unwrap()
Add try_* to add_slot_edge, add_node_edge #
Remove .unwrap()
from add_node_edge
and add_slot_edge
. For cases where the error was handled, use try_add_node_edge
and try_add_slot_edge
instead.
Remove .unwrap()
from input_node
. For cases where the option was handled, use get_input_node
instead.
Shader defs can now have a value #
- Replace
shader_defs.push(String::from("NAME"));
byshader_defs.push("NAME".into());
- If you used shader def
NO_STORAGE_BUFFERS_SUPPORT
, check howAVAILABLE_STORAGE_BUFFER_BINDINGS
is now used in Bevy default shaders
Get pixel size from wgpu #
PixelInfo
has been removed. PixelInfo::components
is equivalent to texture_format.describe().components
. PixelInfo::type_size
can be gotten from texture_format.describe().block_size/ texture_format.describe().components
. But note this can yield incorrect results for some texture types like Rg11b10Float.
Run clear trackers on render world #
The call to clear_trackers
in App
has been moved from the schedule to App::update
for the main world and calls to clear_trackers
have been added for sub_apps
in the same function. This was due to needing stronger guarantees. If clear_trackers
isn’t called on a world it can lead to memory leaks in RemovedComponents
. If you were ordering systems with clear_trackers
this is no longer possible.
Rename camera "priority" to "order" #
Rename priority
to order
in usage of Camera
.
Reduce branching in TrackedRenderPass #
TrackedRenderPass
now requires a RenderDevice
to construct. To make this easier, use RenderContext.begin_tracked_render_pass
instead.
// 0.9
TrackedRenderPass::new(render_context.command_encoder.begin_render_pass(
&RenderPassDescriptor {
...
},
));
// 0.10
render_context.begin_tracked_render_pass(RenderPassDescriptor {
...
});
Make PipelineCache internally mutable. #
Most usages of resource_mut::<PipelineCache>
and ResMut<PipelineCache>
can be changed to resource::<PipelineCache>
and Res<PipelineCache>
as long as they don’t use any methods requiring mutability - the only public method requiring it is process_queue
.
Changed Msaa to Enum #
// 0.9
let multi = Msaa { samples: 4 }
// 0.10
let multi = Msaa::Sample4
// 0.9
multi.samples
// 0.10
multi.samples()
Support recording multiple CommandBuffers in RenderContext #
RenderContext
’s fields are now private. Use the accessors on RenderContext
instead, and construct it with RenderContext::new
.
Improve OrthographicCamera
consistency and usability #
Change
window_origin
toviewport_origin
; replaceWindowOrigin::Center
withVec2::new(0.5, 0.5)
andWindowOrigin::BottomLeft
withVec2::new(0.0, 0.0)
For shadow projections and such, replace
left
,right
,bottom
, andtop
witharea: Rect::new(left, bottom, right, top)
For camera projections, remove l/r/b/t values from
OrthographicProjection
instantiations, as they no longer have any effect in anyScalingMode
Change
ScalingMode::None
toScalingMode::Fixed
- Replace manual changes of l/r/b/t with:
- Arguments in
ScalingMode::Fixed
to specify size viewport_origin
to specify offset
- Arguments in
- Replace manual changes of l/r/b/t with:
Change
ScalingMode::WindowSize
toScalingMode::WindowSize(1.0)
Changed &mut PipelineCache
to &PipelineCache
#
SpecializedComputePipelines::specialize
now takes a &PipelineCache
instead of a &mut PipelineCache
Introduce detailed_trace macro, use in TrackedRenderPass #
Some detailed bevy trace events now require the use of the cargo feature detailed_trace
in addition to enabling TRACE
level logging to view. Should you wish to see these logs, please compile your code with the bevy feature detailed_trace
. Currently, the only logs that are affected are the renderer logs pertaining to TrackedRenderPass
functions
Added subdivisions to shape::Plane #
shape::Plane
now takes an additional subdivisions
parameter so users should provide it or use the new shape::Plane::from_size()
.
Change standard material defaults and update docs #
StandardMaterial
’s default have now changed to be a fully dielectric material with medium roughness. If you want to use the old defaults, you can set perceptual_roughness = 0.089
and metallic = 0.01
(though metallic should generally only be set to 0.0 or 1.0).
Remove dead code after #7784 #
Removed SetShadowViewBindGroup
, queue_shadow_view_bind_group()
, and LightMeta::shadow_view_bind_group
in favor of reusing the prepass view bind group.
Directly extract joints into SkinnedMeshJoints #
ExtractedJoints
has been removed. Read the bound bones from SkinnedMeshJoints
instead.
Intepret glTF colors as linear instead of sRGB #
No API changes are required, but it's possible that your gltf meshes look different
Send emissive color to uniform as linear instead of sRGB #
- If you have previously manually specified emissive values with
Color::rgb()
and would like to retain the old visual results, you must now useColor::rgb_linear()
instead; - If you have previously manually specified emissive values with
Color::rgb_linear()
and would like to retain the old visual results, you'll need to apply a one-time gamma calculation to your channels manually to get the actual linear RGB value:- For channel values greater than
0.0031308
, use(1.055 * value.powf(1.0 / 2.4)) - 0.055
; - For channel values lower than or equal to
0.0031308
, usevalue * 12.92
;
- For channel values greater than
- Otherwise, the results should now be more consistent with other tools/engines.
The update_frame_count
system should be placed in CorePlugin #
The FrameCount
resource was previously only updated when using the bevy_render
feature. If you are not using this feature but still want the FrameCount
it will now be updated correctly.
Pipelined Rendering #
App runner
and SubApp extract
functions are now required to be Send
This was changed to enable pipelined rendering. If this breaks your use case please report it as these new bounds might be able to be relaxed.
Remove ImageMode #
ImageMode
never worked, if you were using it please create an issue.
Rename the background_color
of 'ExtractedUiNodeto
color` #
The background_color
field of ExtractedUiNode
is now named color
.
Remove the GlobalTransform::translation_mut
method #
GlobalTransform::translation_mut
has been removed without alternative, if you were relying on this, update the Transform
instead. If the given entity had children or parent, you may need to remove its parent to make its transform independent (in which case the new Commands::set_parent_in_place
and Commands::remove_parent_in_place
may be of interest)
Bevy may add in the future a way to toggle transform propagation on an entity basis.
Flip UI image #
UiImage
is a struct now, so useUiImage::new(handler)
instead ofUiImage(handler)
UiImage
no longer implementsDeref
andDerefMut
, so use&image.texture
or&mut image.texture
instead
Remove TextError::ExceedMaxTextAtlases(usize)
variant #
TextError::ExceedMaxTextAtlases(usize)
was never thrown so if you were matching on this variant you can simply remove it.
Change default FocusPolicy to Pass #
FocusPolicy
default has changed from FocusPolicy::Block
to FocusPolicy::Pass
Remove VerticalAlign from TextAlignment #
The alignment
field of Text
now only affects the text’s internal alignment.
Change TextAlignment
to TextAlignment` which is now an enum. Replace:
TextAlignment::TOP_LEFT
,TextAlignment::CENTER_LEFT
,TextAlignment::BOTTOM_LEFT
withTextAlignment::Left
TextAlignment::TOP_CENTER
,TextAlignment::CENTER_LEFT
,TextAlignment::BOTTOM_CENTER
withTextAlignment::Center
TextAlignment::TOP_RIGHT
,TextAlignment::CENTER_RIGHT
,TextAlignment::BOTTOM_RIGHT
withTextAlignment::Right
Changes for Text2dBundle
Text2dBundle
has a new field text_anchor
that takes an Anchor
component that controls its position relative to its transform.
Text2dSize
was removed. Use TextLayoutInfo
instead.
Remove QueuedText
#
QueuedText
was never meant to be user facing. If you relied on it, please make an issue.
Change the default width
and height
of Size
to Val::Auto
#
The default values for Size
width
and height
have been changed from Val::Undefined
to Val::Auto
. It’s unlikely to cause any issues with existing code.
Fix the Size
helper functions using the wrong default value and improve the UI examples #
The Size::width
constructor function now sets the height
to Val::Auto
instead of Val::Undefined
. The Size::height
constructor function now sets the width
to Val::Auto
instead of Val::Undefined
.
The size
field of CalculatedSize
should not be a Size
#
The size field of CalculatedSize
has been changed to a Vec2
.
Update winit to 0.28 #
// 0.9
app.new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
always_on_top: true,
..default()
}),
..default()
}));
// 0.10
app.new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
window_level: bevy::window::WindowLevel::AlwaysOnTop,
..default()
}),
..default()
}));