- 0.7 to 0.8
- Camera Driven Rendering
- Visibilty Inheritance, universal ComputedVisibility and RenderLayers support
- Use Affine3A for GlobalTransform to allow any affine transformation
- Add a SceneBundle to spawn a scene
- Make ScalingMode more flexible
- Allow closing windows at runtime
- Make RunOnce a non-manual System impl
- Move system_param fetch struct into anonymous scope to avoid name collisions
- Task doesn't impl Component
- Split time functionality into bevy_time
- Move float_ord from bevy_core to bevy_utils
- Move Rect to bevy_ui and rename it to UiRect
- Rename ElementState to ButtonState
- Improve docs and naming for RawWindowHandle functionality
- Migrate to encase from crevice
- Use ShaderType instead of AsStd140 and AsStd430
- Make paused timers update just_finished on tick
- Change default Image FilterMode to Linear
- Remove .system()
- Change gamepad.rs tuples to normal structs
- Remove EntityMut::get_unchecked
- Replace ReadOnlyFetch with ReadOnlyWorldQuery
- Fix unsoundness with Or/AnyOf/Option component access'
- Remove task_pool parameter from par_for_each(_mut)
- Fail to compile on 16-bit platforms
- Enforce type safe usage of Assets::get
- Allow higher order systems
- Added offset parameter to TextureAtlas::from_grid_with_padding
- Split mesh shader files
- Camera Driven Viewports
- Diagnostics: meaningful error when graph node has wrong number of inputs
- Make Reflect safe to implement
- Mark mutable APIs under ECS storage as pub(crate)
- Add global init and get accessors for all newtyped TaskPools
- Simplify design for *Labels
- Move get_short_name utility method from bevy_reflect into bevy_utils
- Remove dead SystemLabelMarker struct
- Add reflection for resources
- Make reflect_partial_eq return more accurate results
- Make RenderStage::Extract run on the render world
- Improve Gamepad DPad Button Detection
- Change window position types from tuple to vec
- Full documentation for bevy_asset
- Hierarchy commandization
- Remove blanket Serialize + Deserialize requirement for Reflect on generic types
- Lighter no default features
- Improve ergonomics and reduce boilerplate around creating text elements
- Add QueryState::get_single_unchecked_manual and its family
- tracing-tracy updated from 0.8.0 to 0.10.0
Migration Guide: 0.7 to 0.8
Before migrating make sure to run rustup update
Bevy relies heavily on improvements in the Rust language and compiler. As a result, the Minimum Supported Rust Version (MSRV) is "the latest stable release" of Rust.
Camera Driven Rendering #
This is a very complicated change and it is recommended to read the linked PRs for more details
// old 3d perspective camera
commands.spawn_bundle(PerspectiveCameraBundle::default())
// new 3d perspective camera
commands.spawn_bundle(Camera3dBundle::default())
// old 2d orthographic camera
commands.spawn_bundle(OrthographicCameraBundle::new_2d())
// new 2d orthographic camera
commands.spawn_bundle(Camera2dBundle::default())
// old 3d orthographic camera
commands.spawn_bundle(OrthographicCameraBundle::new_3d())
// new 3d orthographic camera
commands.spawn_bundle(Camera3dBundle {
projection: OrthographicProjection {
scale: 3.0,
scaling_mode: ScalingMode::FixedVertical(5.0),
..default()
}.into(),
..default()
})
UI no longer requires a dedicated camera. UiCameraBundle
has been removed. Camera2dBundle
and Camera3dBundle
now both default to rendering UI as part of their own render graphs. To disable UI rendering for a camera, disable it using the UiCameraConfig
component:
commands
.spawn_bundle(Camera3dBundle::default())
.insert(UiCameraConfig {
show_ui: false,
..default()
})
// 0.7
camera.world_to_screen(transform, world_position);
// 0.8
camera.world_to_viewport(transform, world_position);
Visibilty Inheritance, universal ComputedVisibility and RenderLayers support #
Visibility
is now propagated into children in a similar way to Transform
. Root elements of a hierarchy must now contain Visibility
and ComputedVisibility
for visibility propagation to work.
SpatialBundle
and VisibilityBundle
have been added for convenience. If you were using a TransformBundle
you should probably be using a SpatialBundle
now.
If you were previously reading Visibility::is_visible
as the "actual visibility" for sprites or lights, use ComputedVisibility::is_visible()
instead:
// 0.7
fn system(query: Query<&Visibility>) {
for visibility in query.iter() {
if visibility.is_visible {
info!("found visible entity");
}
}
}
// 0.8
fn system(query: Query<&ComputedVisibility>) {
for visibility in query.iter() {
if visibility.is_visible() {
info!("found visible entity");
}
}
}
Use Affine3A for GlobalTransform to allow any affine transformation #
GlobalTransform
fields have changed
- Replace
global_transform.translation
byglobal_transform.translation()
(For other fields, use thecompute_transform
method) GlobalTransform
do not support non-linear scales anymore, we'd like to hear from you if it is an inconvenience for you- If you need the
scale
,rotation
ortranslation
property you can now useglobal_transform.to_scale_rotation_translation()
// 0.7
let transform = Transform::from(*global_transform);
transform.scale
transform.rotation
transform.translation
// 0.8
let (scale, rotation, translation) = global_transform.to_scale_rotation_translation();
Add a SceneBundle to spawn a scene #
// 0.7
commands.spawn_scene(asset_server.load("models/FlightHelmet/FlightHelmet.gltf#Scene0"));
// 0.8
commands.spawn_bundle(SceneBundle {
scene: asset_server.load("models/FlightHelmet/FlightHelmet.gltf#Scene0"),
..Default::default()
});
The scene will be spawned as a child of the entity with the SceneBundle
Make ScalingMode more flexible #
Adds ability to specify scaling factor for WindowSize
, size of the fixed axis for FixedVertical
and FixedHorizontal
and a new ScalingMode
that is a mix of FixedVertical
and FixedHorizontal
Allow closing windows at runtime #
bevy::input::system::exit_on_esc_system
has been removed. Use bevy::window::close_on_esc
instead.
CloseWindow
has been removed. Use Window::close
instead. The Close variant has been added to WindowCommand
. Handle this by closing the relevant window.
Make RunOnce a non-manual System impl #
The run criterion RunOnce
, which would make the controlled systems run only once, has been replaced with a new run criterion function ShouldRun::once. Replace all instances of RunOnce with ShouldRun::once
.
Move system_param fetch struct into anonymous scope to avoid name collisions #
For code that was using a system param's fetch struct, such as EventReader's EventReaderState, the fetch struct can now be identified via the SystemParam trait associated type Fetch, e.g. for EventReader<T>
it can be identified as <EventReader<'static, 'static, T> as SystemParam>::Fetch
Task doesn't impl Component #
If you need a Task
to be a Component
you should use a wrapper type.
// 0.7
fn system(mut commands: Commands, thread_pool: Res<AsyncComputeTaskPool>) {
let task = thread_pool.spawn(async move {
// Complicated async work
Vec2::ZERO
});
commands.spawn().insert(task);
}
// 0.8
#[derive(Component)]
struct ComputeVec2(Task<Vec2>);
fn system(mut commands: Commands) {
let thread_pool = AsyncComputeTaskPool::get();
let task = thread_pool.spawn(async move {
// Complicated async work
Vec2::ZERO
});
commands.spawn().insert(ComputeVec2(task));
}
Split time functionality into bevy_time #
- Time related types (e.g.
Time
,Timer
,Stopwatch
,FixedTimestep
, etc.) should be imported frombevy::time::*
rather thanbevy::core::*
. - If you were adding
CorePlugin
manually, you'll also want to addTimePlugin
frombevy::time
. - The
bevy::core::CorePlugin::Time
system label is replaced withbevy::time::TimeSystem
.
Move float_ord from bevy_core to bevy_utils #
Replace imports of bevy::core::FloatOrd
with bevy::utils::FloatOrd
.
Move Rect to bevy_ui and rename it to UiRect #
The Rect
type has been renamed to UiRect
.
Rename ElementState to ButtonState #
The ElementState
type has been renamed to ButtonState
.
Improve docs and naming for RawWindowHandle functionality #
Renamed HasRawWindowHandleWrapper
to ThreadLockedRawWindowHandleWrapper
.
Migrate to encase from crevice #
Use ShaderType instead of AsStd140 and AsStd430 #
// old
#[derive(AsStd140)]
struct Foo {
a: Vec4,
b: Mat4,
}
// new
#[derive(ShaderType)]
struct Foo {
a: Vec4,
b: Mat4,
}
StorageBuffer #
- removed
set_body()
,values()
,values_mut()
,clear()
,push()
,append()
- added
set()
,get()
,get_mut()
UniformVec -> UniformBuffer #
- renamed
uniform_buffer()
tobuffer()
- removed
len()
,is_empty()
,capacity()
,push()
,reserve()
,clear()
,values()
- added
set()
,get()
DynamicUniformVec -> DynamicUniformBuffer #
- renamed
uniform_buffer()
tobuffer()
- removed
capacity()
,reserve()
Make paused timers update just_finished on tick #
Timer::times_finished
has been renamed to Timer::times_finished_this_tick
for clarity.
Change default Image FilterMode to Linear #
Default Image
filtering changed from Nearest
to Linear
.
// 0.7
// Nothing, nearest was the default
// 0.8
App::new()
.insert_resource(ImageSettings::default_nearest())
Image.sampler_descriptor
has been changed to use ImageSampler
instead of SamplerDescriptor
.
// 0.7
texture.sampler_descriptor = SamplerDescriptor {
address_mode_u: AddressMode::Repeat,
address_mode_v: AddressMode::Repeat,
..default()
};
// 0.8
texture.sampler_descriptor = ImageSampler::Descriptor(SamplerDescriptor {
address_mode_u: AddressMode::Repeat,
address_mode_v: AddressMode::Repeat,
..default()
});
Remove .system() #
You can no longer use .system()
. It was deprecated in 0.7.0. You can just remove the method call.
If you needed this for tests purposes, you can use bevy_ecs::system::assert_is_system
instead.
Change gamepad.rs tuples to normal structs #
The Gamepad
, GamepadButton
, GamepadAxis
, GamepadEvent
and GamepadEventRaw
types are now normal structs instead of tuple structs and have a new
function. To migrate change every instantiation to use the new()
function instead and use the appropriate field names instead of .0 and .1.
Remove EntityMut::get_unchecked #
Replace calls to EntityMut::get_unchecked
with calls to EntityMut::get
.
Replace ReadOnlyFetch with ReadOnlyWorldQuery #
The trait ReadOnlyFetch
has been replaced with ReadOnlyWorldQuery
along with the WorldQueryGats::ReadOnlyFetch
assoc type which has been replaced with <WorldQuery::ReadOnly as WorldQueryGats>::Fetch
The trait ReadOnlyFetch
has been replaced with ReadOnlyWorldQuery
along with the WorldQueryGats::ReadOnlyFetch
assoc type which has been replaced with <WorldQuery::ReadOnly as WorldQueryGats>::Fetch
- Any where clauses such as
QueryFetch<Q>: ReadOnlyFetch
should be replaced withQ: ReadOnlyWorldQuery
. - Any custom world query impls should implement
ReadOnlyWorldQuery
instead ofReadOnlyFetch
Functions update_component_access
and update_archetype_component_access
have been moved from the FetchState
trait to WorldQuery
- Any callers should now call
Q::update_component_access(state
instead ofstate.update_component_access
(andupdate_archetype_component_access
respectively) - Any custom world query impls should move the functions from the
FetchState
impl toWorldQuery
impl
WorldQuery
has been made an unsafe trait
, FetchState
has been made a safe trait
. (I think this is how it should have always been, but regardless this is definitely necessary now that the two functions have been moved to WorldQuery
)
- If you have a custom
FetchState
impl make it a normalimpl
instead ofunsafe impl
- If you have a custom
WorldQuery
impl make it anunsafe impl
, if your code was sound before it is going to still be sound
Fix unsoundness with Or/AnyOf/Option component access' #
Query conflicts from Or
/AnyOf
/Option
have been fixed, and made stricter to avoid undefined behaviour. If you have new query conflicts due to this you must refactor your systems; consider using ParamSet
.
Remove task_pool parameter from par_for_each(_mut) #
The task_pool
parameter for Query(State)::par_for_each(_mut)
has been removed. Remove these parameters from all calls to these functions.
// 0.7
fn parallel_system(
task_pool: Res<ComputeTaskPool>,
query: Query<&MyComponent>,
) {
query.par_for_each(&task_pool, 32, |comp| {
// ...
});
}
// 0.8
fn parallel_system(query: Query<&MyComponent>) {
query.par_for_each(32, |comp| {
// ...
});
}
If using Query
or QueryState
outside of a system run by the scheduler, you may need to manually configure and initialize a ComputeTaskPool
as a resource in the World
.
Fail to compile on 16-bit platforms #
bevy_ecs
will now explicitly fail to compile on 16-bit platforms, because it is unsound on those platforms due to various internal assumptions.
There is currently no alternative, but we're open to adding support. Please file an issue to help detail your use case.
Enforce type safe usage of Assets::get #
Assets::<T>::get
and Assets::<T>::get_mut
now require that the passed handles are Handle<T>
, improving the type safety of handles. If you were previously passing in:
- a
HandleId
, use&Handle::weak(id)
instead, to create a weak handle. You may have been able to store a type safeHandle
instead. - a
HandleUntyped
, use&handle_untyped.typed_weak()
to create a weak handle of the specified type. This is most likely to be the useful when using load_folder - a
&str
or anything not previously mentioned:assets.get(&assets.get_handle("asset/path.ron"))
- a
Handle<U>
of a different type, consider whether this is the correct handle type to store. If it is (i.e. the same handle id is used for multiple different Asset types) useHandle::weak(handle.id)
to cast to a different type.
Allow higher order systems #
SystemParamFunction
has changed. It was not previously part of the public API, so no migration instructions are provided. (It is now included in the public API, although you still should not implement this trait for your own types).
If possible, any custom System
implementations should be migrated to use higher order systems, which are significantly less error-prone.
Research is needed into allowing this to work for more cases.
Added offset parameter to TextureAtlas::from_grid_with_padding #
Calls to TextureAtlas::from_grid_with_padding
should be modified to include a new parameter, which can be set to Vec2::ZERO
to retain old behaviour.
// 0.7
from_grid_with_padding(texture, tile_size, columns, rows, padding)
// 0.8
from_grid_with_padding(texture, tile_size, columns, rows, padding, Vec2::ZERO)
Split mesh shader files #
In shaders for 3D meshes:
#import bevy_pbr::mesh_view_bind_group
->#import bevy_pbr::mesh_view_bindings
#import bevy_pbr::mesh_struct
->#import bevy_pbr::mesh_types
- NOTE: If you are using the mesh bind group at bind group index 2, you can remove those binding statements in your shader and just use
#import bevy_pbr::mesh_bindings
which itself imports the mesh types needed for the bindings.
- NOTE: If you are using the mesh bind group at bind group index 2, you can remove those binding statements in your shader and just use
In shaders for 2D meshes:
#import bevy_sprite::mesh2d_view_bind_group
->#import bevy_sprite::mesh2d_view_bindings
#import bevy_sprite::mesh2d_struct
->#import bevy_sprite::mesh2d_types
- NOTE: If you are using the mesh2d bind group at bind group index 2, you can remove those binding statements in your shader and just use
#import bevy_sprite::mesh2d_bindings
which itself imports the mesh2d types needed for the bindings.
- NOTE: If you are using the mesh2d bind group at bind group index 2, you can remove those binding statements in your shader and just use
Camera Driven Viewports #
Camera::projection_matrix
is no longer a public field. Use the new Camera::projection_matrix()
method instead:
// 0.7
let projection = camera.projection_matrix;
// 0.8
let projection = camera.projection_matrix();
Diagnostics: meaningful error when graph node has wrong number of inputs #
Exhaustive matches on RenderGraphRunnerError
will need to add a branch to handle the new MismatchedInputCount
variant.
Make Reflect safe to implement #
- Reflect derives should not have to change anything
- Manual reflect impls will need to remove the
unsafe
keyword, addany()
implementations, and rename the oldany
andany_mut
toas_any
andas_mut_any
. - Calls to
any
/any_mut
must be changed toas_any
/as_mut_any
Mark mutable APIs under ECS storage as pub(crate) #
If you experienced any problems caused by this change, please create an issue explaining in detail what you were doing with those apis.
Add global init and get accessors for all newtyped TaskPools #
Thread pools don't need to be stored in a resource anymore since they are now stored globally. You can now use get()
to access it.
// 0.7
fn spawn_tasks(thread_pool: Res<AsyncComputeTaskPool>) {
// Do something with thread_pool
}
// 0.8
fn spawn_tasks() {
let thread_pool = AsyncComputeTaskPool::get();
// Do something with thread_pool
}
Simplify design for *Labels #
- Any previous use of
Box<dyn SystemLabel>
should be replaced withSystemLabelId
. AsSystemLabel
trait has been modified.- No more output generics.
- Method
as_system_label
now returnsSystemLabelId
, removing an unnecessary level of indirection.
- If you need a label that is determined at runtime, you can use
Box::leak
. Not recommended.
Move get_short_name utility method from bevy_reflect into bevy_utils #
- added bevy_utils::get_short_name, which strips the path from a type name for convenient display.
- removed the TypeRegistry::get_short_name method. Use the function in bevy_utils instead.
Remove dead SystemLabelMarker struct #
This struct had no internal use, docs, or intuitable external use.
It has been removed.
Add reflection for resources #
Rename ReflectComponent::add_component
into ReflectComponent::insert_component
.
Make reflect_partial_eq return more accurate results #
Previously, all reflect_***_partial_eq
helper methods returned Some(false)
when the comparison could not be performed, which was misleading. They now return None
when the comparison cannot be performed.
Make RenderStage::Extract run on the render world #
The Extract
RenderStage
now runs on the render world (instead of the main world as before). You must use the Extract
SystemParam
to access the main world during the extract phase. Extract
takes a single type parameter, which is any system parameter (such as Res
, Query
etc.). It will extract this from the main world. Note that Commands
will not work correctly in Extract
- it will currently silently do nothing.
// 0.7
fn extract_clouds(mut commands: Commands, clouds: Query<Entity, With<Cloud>>) {
for cloud in clouds.iter() {
commands.get_or_spawn(cloud).insert(Cloud);
}
}
// 0.8
fn extract_clouds(mut commands: Commands, mut clouds: Extract<Query<Entity, With<Cloud>>>) {
for cloud in clouds.iter() {
commands.get_or_spawn(cloud).insert(Cloud);
}
}
You can now also access resources from the render world using the normal system parameters during Extract
:
fn extract_assets(mut render_assets: ResMut<MyAssets>, source_assets: Extract<Res<MyAssets>>) {
*render_assets = source_assets.clone();
}
Because extraction now runs in the render world, usage of Res<RenderWorld>
in the main world, should be replaced with usage of Res<MainWorld>
in the render world.
Please note that all existing extract systems need to be updated to match this new style; even if they currently compile they will not run as expected. A warning will be emitted on a best-effort basis if this is not met.
Improve Gamepad DPad Button Detection #
D-pad inputs can no longer be accessed as axes. Access them as gamepad buttons instead.
Change window position types from tuple to vec #
Changed the following fields
WindowCommand::SetWindowMode.resolution
from(u32, u32)
toUVec2
WindowCommand::SetResolution.logical_resolution
from(f32, f32)
toVec2
Full documentation for bevy_asset #
Rename FileAssetIo::get_root_path
to FileAssetIo::get_base_path
FileAssetIo::root_path()
is a getter for the root_path
field, while FileAssetIo::get_root_path
returned the parent directory of the asset root path, which was the executable's directory unless CARGO_MANIFEST_DIR
was set. This change solves the ambiguity between the two methods.
Hierarchy commandization #
The Parent
and Children
component fields are now private.
- Replace
parent.0
byparent.get()
- Replace
children.0
with*children
- You can't construct
Children
orParent
component anymore, you can use this as a stopgap measure, which may introduce a single frame delay
#[derive(Component)]
pub struct MakeChildOf(pub Entity);
fn add_parent(
mut commands: Commands,
orphans: Query<(Entity, &MakeChildOf)>,
) {
for (child, MakeChildOf(parent)) in &orphans {
commands.entity(*parent).add_child(child);
commands.entity(child).remove::<MakeChildOf>();
}
}
Remove blanket Serialize + Deserialize requirement for Reflect on generic types #
.register_type
for generic types like Option<T>
, Vec<T>
, HashMap<K, V>
will no longer insert ReflectSerialize
and ReflectDeserialize
type data. Instead you need to register it separately for concrete generic types like so:
.register_type::<Option<String>>()
.register_type_data::<Option<String>, ReflectSerialize>()
.register_type_data::<Option<String>, ReflectDeserialize>()
Lighter no default features #
bevy_asset
and bevy_scene
are no longer enabled when no-default-features
is used with the bevy
dependency.
- Crates that use Bevy with
no-default-features
will need to add these features manually if they rely on them.
bevy = { version = "0.8", default-features = false, features = [
"bevy_asset",
"bevy_scene",
] }
Improve ergonomics and reduce boilerplate around creating text elements #
Text::with_section
was renamed to Text::from_section
and no longer takes a TextAlignment
as argument. Use with_alignment
to set the alignment instead.
Add QueryState::get_single_unchecked_manual and its family #
Change system::QuerySingleError
to query::QuerySingleError
tracing-tracy updated from 0.8.0 to 0.10.0 #
The required tracy version when using the trace-tracy feature is now 0.8.1.