Bevy 0.8
Posted on July 30, 2022 by Carter Anderson ( @cart @cart_cart cartdev )
Thanks to 130 contributors, 461 pull requests, community reviewers, and our generous sponsors, I'm happy to announce the Bevy 0.8 release on crates.io!
For those who don't know, Bevy is a refreshingly simple data-driven game engine built in Rust. You can check out our Quick Start Guide to try it today. It's free and open source forever! You can grab the full source code on GitHub. Check out Bevy Assets for a collection of community-developed plugins, games, and learning resources.
To update an existing Bevy App or Plugin to Bevy 0.8, check out our 0.7 to 0.8 Migration Guide.
Since our last release a few months ago we've added a ton of new features, bug fixes, and quality of life tweaks, but here are some of the highlights:
- New Material System: Custom shaders are now much easier to define, thanks to the new Material trait and AsBindGroup derive.
- Camera-driven Rendering: Each Camera now configures what it renders and how it renders it. Easily layer camera renders on top of each other, do split screen, or render to a texture in just a few lines of code.
- Built-in Shader Modularization: Many built-in shader types and functions are now importable. Notably, custom shaders can now import the PBR shader logic
- Spot Lights: A new light type that emits light in a cone shape from a fixed point.
- Visibility Inheritance: Hiding an entity now also hides all of its descendants in the hierarchy.
- Upgraded to wgpu 0.13: Uses a new, more ergonomic WGSL shader syntax.
- Automatic Mesh Tangent Generation: If tangents are missing for a mesh, generate them with mikktspace.
- Renderer Optimizations: Parallel frustum culling and unstable sorts for unbatched render phases yielded some big wins!
- Scene Bundle: Easily spawn scenes using a normal Bevy bundle and extend them with new components and children.
- Scripting and Modding Progress: Untyped ECS APIs: A step toward 3rd party scripting language support! Interact with Bevy ECS internals directly via pointers.
- ECS Query Ergonomics and Usability: Queries now implement
IntoIter
and mutable queries can be converted to immutable queries. - ECS Internals Refactors: Sweeping changes to Bevy ECS internals that make it simpler, safer, and easier to maintain.
- Reflection Improvements: Support for reflecting more types, ECS resource reflection, untyped reflection, improved internals.
- Hierarchy Commands: Hierarchy updates now use "transactional commands" to ensure hierarchy consistency at all times.
- Bevy UI Now Uses Taffy: We've swapped to (and help maintain) a collaborative fork of the now abandoned Stretch UI layout library. Exponential blow-up bug begone!
New Material System #
Bevy has a brand new Material
system that makes defining custom shaders a breeze. Bevy's previous material system required hundreds of lines of "mid-level" boilerplate. This was never the long term plan, just an intermediate step. In Bevy 0.8, custom shader materials are as simple as this:
#[derive(AsBindGroup, TypeUuid, Clone)]
#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
pub struct CoolMaterial {
#[uniform(0)]
color: Color,
#[texture(1)]
#[sampler(2)]
color_texture: Handle<Image>,
}
// The Material trait has many optional functions for configuration.
// In this case, all we need to set is a fragment shader. Ergonomics!
impl Material for CoolMaterial {
fn fragment_shader() -> ShaderRef {
"cool_material.wgsl".into()
}
}
And the cool_material.wgsl
shader:
struct CoolMaterial {
color: vec4<f32>,
};
@group(1) @binding(0)
var<uniform> material: CoolMaterial;
@group(1) @binding(1)
var color_texture: texture_2d<f32>;
@group(1) @binding(2)
var color_sampler: sampler;
@fragment
fn fragment(
#import bevy_pbr::mesh_vertex_output
) -> @location(0) vec4<f32> {
return material.color * textureSample(color_texture, color_sampler, uv);
}
And just like that, we have a configurable shader material!
This can be used to create whatever effects you want! For example: @DGriffin91
made this cool "glowing orb" effect:
They also made a nice video tutorial outlining how to create this material.
This is thanks to the new AsBindGroup
trait / derive, which does all of the hard work of converting the material to GPU-compatible datatypes, writing them to the GPU, and creating the final BindGroup
. The AsBindGroup
trait is powerful: it supports combining multiple fields into the same uniform binding, configuring texture binding types (2D, 3D, filtering, etc), and more. For details, check out the AsBindGroup
docs.
All built-in materials, such as the PBR StandardMaterial
have been ported to use this new system. We strive to make Bevy "internals" the same as user code, and this is no exception! Material
also works seamlessly with our more advanced shader features, such as shader pipeline specialization.
There is also an equivalent Material2d
trait, which enables custom materials in 2D.
Camera-Driven Rendering #
In previous versions of Bevy, Cameras
were selected and run as a part of one "global" RenderGraph
. There could only be one "active" camera of a given type, and that camera could only render to one target. The only way to render from multiple perspectives at the same time was to manually extend the render graph with duplicate logic. This was full of complicated low-level renderer boilerplate that wasn't approachable for the average Bevy user.
In Bevy 0.8, each Camera
now configures what it renders, how it renders, and what it renders to. An enabled camera will start a new run of a RenderGraph
to a specified RenderTarget
. The render graph defines modular render logic for the given camera and the render target defines the window or texture the graph will render to.
This makes scenarios that were previously hundreds (or thousands) of lines of code as simple as setting a few fields on the Camera
entity:
Render to Textures #
Rendering a Camera
to a texture is now a single line of code:
camera.target = RenderTarget::Image(image_handle);
This enables too many scenarios to count: portals, rendering UI to a texture and rendering it in 3d space, in-game security cameras, real-time player portraits rendered in UI widgets ... the sky is the limit!
Here is an example of a "portal effect":
This is accomplished by rendering a second camera to a texture, synchronizing its orientation with the main player's camera, and using that texture in the main camera's scene.
Split Screen #
Each Camera
now has an optional Viewport
, which if set will draw to a section of a RenderTarget
instead of the whole. If you spawn two active cameras and set each camera's Viewport
to draw to half of the window, you have simple, painless split screen!
Layered Rendering #
Cameras can now be layered on top of each other using the new "camera priority" field:
// This camera defaults to priority 0 and is rendered "first" / "at the back"
commands.spawn_bundle(Camera3dBundle::default());
commands.spawn_bundle(Camera3dBundle {
camera_3d: Camera3d {
// don't clear the color while rendering this camera
clear_color: ClearColorConfig::None,
..default()
},
camera: Camera {
// renders after / on top of the main camera
priority: 1,
..default()
},
..default()
});
"Priority" determines the order cameras are drawn in. The "portal" effect in the render to textures example above uses priority to render the "portal" camera first, ensuring it is ready to be used by the main camera.
Here is a simple example of two cameras rendering to the same window:
This can be used for things like "custom UI passes", "minimaps", etc.
Ergonomic Target Size Access #
Cameras now store their RenderTarget
size locally, which makes retrieving the size much simpler:
// Much nicer than needing to look up the size on the target Window or Image manually,
// like you had to in previous Bevy versions!
let target_size = camera.logical_target_size();
let viewport_size = camera.logical_viewport_size();
This also means that converting world to screen coordinates for a camera is much easier than it used to be:
// Bevy 0.7 (old)
camera.world_to_screen(windows, images, camera_transform, world_position);
// Bevy 0.8 (new)
camera.world_to_viewport(camera_transform, world_position);
New Camera Bundles #
The old OrthographicCameraBundle
and PerspectiveCameraBundle
have been replaced with Camera3dBundle
and Camera2dBundle
. In most cases migration should be as simple as replacing the old names with the new ones. 3D cameras default to "perspective" projections, but they can still be switched to orthographic using the new Projection
component in the bundle.
No More CameraUiBundle! #
Bevy UI now no longer needs a separate camera entity to work. UI "just works" for all camera types and can be enabled or disabled per-camera using the UiCameraConfig
component.
commands
.spawn_bundle(Camera3dBundle::default())
.insert(UiCameraConfig {
show_ui: false,
});
Custom Render Graphs #
The default 2D and 3D RenderGraphs
for each Camera
can be overridden by setting the CameraRenderGraph
component:
commands.spawn_bundle(Camera3dBundle {
camera_render_graph: CameraRenderGraph::new(some_custom_graph),
..default()
})
This enables you to draw the camera with whatever custom render logic you need! For example, you could replace the built in clustered-forward-rendering with deferred rendering. Note that this generally won't be required: most custom rendering scenarios will be covered by high-level Materials or extending the built-in render graphs. And using the default render graph will ensure maximum compatibility with other plugins.
Enabling / Disabling Cameras #
If a camera is "active", it will render to its RenderTarget
. To activate or deactivate a camera, set the new is_active
field:
camera.is_active = true;
RenderLayers #
Bevy's existing RenderLayers
system can be used to tell a Camera
to only render entities on specific layers. Camera-Driven Rendering pairs nicely with this feature. This enables rendering one set of entities to one camera and another set of entities to another camera. We've ported the RenderLayers
system to all entities with Visibility
, so this will all Just Work™.
Spotlights #
Bevy now has a SpotLight
entity type, which emits light in a cone shape from a point in space.
Visibility Inheritance #
Visibility in entity hierarchies (using the Visibility
component) now propagates down the hierarchy. This is hugely useful, as entities in a game often have many entities nested beneath them. A "player entity" is often made up of many pieces: the player sprite or mesh, what the player is wearing / holding, visual effects, etc.
Visibility inheritance means that you only need to hide the top level "player" entity in your code and everything beneath it will be hidden for you.
This "flight helmet" scene consists of many "pieces" nested under the main helmet entity. Hiding all of these "sub entities" is as now as easy as hiding the top level helmet entity.
fn hide_helmets(mut helmet_visibilities: Query<&mut Visibility, With<Helmet>>) {
let mut helmet_visibility = helmet_visibilities.single_mut();
helmet_visibility.is_visible = false;
}
In past versions of Bevy, you had to hide each piece manually!
The "inherited visibility" is computed in the PostUpdate
stage and stored on the ComputedVisibility
component. ComputedVisibility
now has the following functions:
is_visible_in_hierarchy()
: Whether or not the entity is visible according to "visibility inheritance".is_visible_in_view()
: Whether or not the entity is visible in any view. This is used for culling entities in cases like "frustum culling".is_visible()
: The canonical place to determine whether or not an entity will be drawn. Combines "view visibility" and "hierarchy visibility".
SpatialBundle and VisibilityBundle #
With the addition of Visibility Inheritance comes the constraint that visibility propagation requires all elements in the hierarchy to have the appropriate visibility components. When constructing scenes, developers often want to group entities under parent "organizational" entities, which exist solely to group entities together, reposition them, and hide them as a unit. These "organizational" entities still require visibility components to propagate the Transform
and Visibility
to GlobalTransform
and ComputedVisibility
(respectively).
To make this easy, we've added a new SpatialBundle
, which adds the components mentioned above. This allows the entity to configure and propagate visibility and transform data without incurring the cost of actually rendering it.
commands
// This entity controls the position and visibility of the entities beneath it.
.spawn_bundle(SpatialBundle {
transform: Transform::from_xyz(10.0, 20.0, 30.0),
visibility: Visibility {
is_visible: true,
},
..default()
}).with_children(|parent| {
parent
.spawn_bundle(TableBundle::default())
.spawn_bundle(ShopKeeperBundle::default())
.spawn_bundle(PotionBundle::default());
});
To ensure visibility and transforms are propagated, make sure the whole hierarchy (root -> leaf) has these components:
commands
.spawn_bundle(SpatialBundle::default())
.with_children(|parent| {
parent
.spawn_bundle(SpatialBundle::default())
.with_children(|parent| {
parent.spawn_bundle(SpatialBundle::default());
});
});
If you know you don't need Transform
propagation (or your entity already has those components), you can instead use the new VisibilityBundle
, which only adds the components required for visibility propagation.
Built-in Shader Modularization #
In Bevy 0.8, we've started modularizing our built-in shaders. Notably, this means you can now import and run the built-in PBR shader / lighting logic:
#import bevy_pbr::utils
#import bevy_pbr::clustered_forward
#import bevy_pbr::lighting
#import bevy_pbr::shadows
#import bevy_pbr::pbr_types
#import bevy_pbr::pbr_functions
@fragment
fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
var pbr_input: PbrInput = pbr_input_new();
// set the base color to red
pbr_input.material.base_color = vec4<f32>(1.0, 0.0, 0.0, 1.0);
/* set other PbrInput fields here */
return tone_mapping(pbr(pbr_input))
}
We've also modularized our mesh and view binding shader logic. When paired with the New Material System, users can now reasonably write custom PBR materials without re-defining all of the PBR logic in their shaders. The new Array Texture Example illustrates how to define a custom PBR shader material using these new APIs:
We also plan on evolving the user experience here. Now that we've broken everything up and modularized it, we'll work on reducing the amount of boilerplate required to extend this logic (cutting down on imports, removing the need to set all PbrInput fields, etc).
wgpu 0.13: New WGSL Shader Syntax #
We've updated to the latest and greatest wgpu version. wgpu 0.13 brings plenty of fixes and improvements, but the most visible change is the new more ergonomic WGSL "attribute" syntax:
Bindings now look like this:
// wgpu 0.12 (old)
[[group(1), binding(0)]]
var<uniform> material: Material;
// wgpu 0.13 (new)
@group(1) @binding(0)
var<uniform> material: Material;
Shader stage entry points and inputs now look like this:
// wgpu 0.12 (old)
[[stage(vertex)]]
fn vertex([[location(0)]] position: vec3<f32>, [[location(1)]] normal: vec3<f32>) -> VertexOutput {
}
// wgpu 0.13 (new)
@vertex
fn vertex(@location(0) position: vec3<f32>, @location(1) normal: vec3<f32>) -> VertexOutput {
}
Much easier on the eyes! (and the fingers!)
Scene Bundle #
In previous versions of Bevy scenes were spawned like this:
commands.spawn_scene(asset_server.load("some.gltf#Scene0"));
This worked, but it made it difficult to actually use the scene in practice. Repositioning the scene required either manually grabbing the scene's entity id and then repositioning it when it spawns, or creating a parent entity with the relevant transform components and "spawning the scene as a child". Additionally, it was challenging to extend scenes with new components.
In Bevy 0.8, we've added a SceneBundle
, which brings scene spawning in line with our other entity construction APIs:
commands.spawn_bundle(SceneBundle {
scene: asset_server.load("some.gltf#Scene0"),
..default()
})
When the scene loads, it will automatically spawn underneath the entity created by the spawn_bundle
command. This makes it much easier to transform the scene and add new components at the "root":
commands
.spawn_bundle(SceneBundle {
scene: asset_server.load("player.gltf#Scene0"),
transform: Transform::from_xyz(10.0, 20.0, 30.0),
..default()
})
.insert(Player::default());
Parallel Frustum Culling #
Bevy uses "frustum culling" to skip drawing entities that are outside of the camera's view. In Bevy 0.8, frustum culling is now done in parallel. When culling thousands of entities, this yields significant performance improvements:
frustum culling system time vs number of entities culled (lower is better) #
Note that "parallel b" stand for "parallel batch size" (number of entities in each batch). We selected 1024 as our batch size in Bevy 0.8, as that performs better.
Automatic Mesh Tangent Generation #
Vertex tangents are used in tandem with normal maps to give meshes more detailed normals when rendering them. Some imported meshes have normal maps, but don't have vertex tangents calculated. Bevy can now automatically generate vertex tangents for Meshes
that are missing them using the defacto industry-standard MikkTSpace library / algorithm (Godot, Unity, Unreal, and Blender all use this).
We have started maintaining our own fork of the gltf-rs/mikktspace crate so we can:
- update dependencies at the speed required for Bevy;
- start reining in the unsafe code, as it currently uses unsafe Rust code auto-generated from the original
mikktspace.h
written in C.
Default to Linear Texture Filtering #
Images in Bevy now use linear texture filtering by default, which is more in line with the rest of the gamedev ecosystem (Unity and Godot both default to filtered textures).
This means that textures that require unfiltered pixels (such as "pixel art" sprites) must override this default, either per-image:
image.sampler_descriptor = ImageSampler::nearest();
or globally using the new ImageSettings
resource:
app.insert_resource(ImageSettings::default_nearest())
With that, we get crisp pixel art:
New GlobalTransform Matrix Representation #
The internal representation of the GlobalTransform
component (representing the "world space" transform for an entity) has been changed from a "similarity" (translation Vec3
/ rotation Quat
/ scale Vec3
) to an "affine 3D transform" (Mat3A
and a Vec3
translation).
Notably, this allows for shear to be represented. Shear is a controversial topic. Engine and physics programmers tend to hate it. Artists tend to love it. Given that most artist tools and game engines support shear in their equivalent types, we believe it is important to provide this as an option.
ShaderType derive #
Bevy 0.8 now uses the ShaderType
trait / derive (provided by the encase crate) to easily convert Rust data types to GPU-compatible shader data types.
// ShaderType requires each field to implement ShaderType,
// which Bevy's math types and Color type implement.
#[derive(ShaderType)]
struct SpriteData {
position: Vec2,
color: Color,
}
And on the WGSL shader side it looks like this:
struct SpriteData {
position: vec2<f32>,
color: vec4<f32>,
};
@group(1) @binding(0)
var<uniform> sprite_data: SpriteData;
This trait can be used in the new Material system if you need to define custom shader uniform or buffer bindings.
ShaderType
replaces the AsStd140
and AsStd430
traits / derives (provided by the crevice crate) used in previous Bevy versions. This simplifies (and clarifies) the "how to transfer data to the GPU" story in Bevy, while also adding new features, such as support for unbounded Rust vecs (for storage buffers) and configurable dynamic offsets for uniform and storage buffers.
For example, Bevy's built-in lighting pipeline was adjusted to take advantage of this:
#[derive(ShaderType)]
pub struct GpuPointLightsStorage {
#[size(runtime)]
data: Vec<GpuPointLight>,
}
Render Phase Sorting Optimization #
Bevy uses "render phases" to collect per-entity render logic for a render pass. These phases can be sorted to control draw order for a variety of reasons: back-to-front depth sorting for transparency correctness and front-to-back sorting for early fragment discarding during opaque rendering.
When possible, Bevy 0.8 now uses "unstable sorts" (currently "radix sort"), which yields a significant performance improvement:
many_cubes stress test "opaque phase" sort times (in milliseconds, less is better) #
Vertex Colors #
Bevy's 2D and 3D pipelines and Materials
now support vertex colors, if a given Mesh
provides them. The PBR StandardMaterial
and the 2D ColorMaterial
build on this and will use the vertex colors if they are set:
Regular Polygon and Circle Mesh Primitives #
Bevy now has Circle
and RegularPolygon
Mesh
shapes:
let pentagon = RegularPolygon::new(10., 5);
let handle = meshes.add(Mesh::from(pentagon));
commands.spawn_bundle(ColorMesh2dBundle {
mesh: handle.into(),
..default()
});
Scripting and Modding Progress: Untyped ECS APIs #
Bevy officially only supports Rust as the "one true way to define app logic". We have very good reasons for this and that philosophy likely won't change any time soon. But we do want to provide the tools needed for the community to build 3rd party scripting / modding plugins for their languages of choice.
When we released Bevy ECS V2, we intentionally built our internal ECS storage with these cases in mind. But we didn't expose public APIs that made it possible to interact with ECS data without normal Rust types.
Bevy 0.8 adds public "untyped" ECS APIs that enable retrieving lifetimed pointers to component and resource data using ComponentId
instead of actual Rust types.
let health_ptr: Ptr = world.entity(player).get_by_id(heath_component_id).unwrap();
These, when combined with our reflection APIs, provide the tools needed to start building scripting support!
@jakobhellermann
has started building their own JavaScript / TypeScript plugin for Bevy. Note that:
- This plugin is still very much a work in progress and is not ready to be used in projects.
- This is an unofficial community effort. Bevy will not be adding official JavaScript/TypeScript support.
Here is a TypeScript snippet from their repository that queries Bevy ECS data from the script:
const ballQuery = world.query({
components: [ballId, transformId, velocityId],
});
for (const item of ballQuery) {
let [ball, transform, velocity] = item.components;
velocity = velocity[0];
info(velocity.toString());
}
Query IntoIter #
Bevy ECS Queries
now implement the IntoIterator
trait, which provides access to Rust's nicer iteration syntax:
// In previous Bevy versions, iter/iter_mut had to be called manually:
fn system(mut players: Query<&mut Player>) {
for player in players.iter() {
}
for mut player in players.iter_mut() {
}
}
// In Bevy 0.8, you have the option to use this syntax:
fn system(mut players: Query<&mut Player>) {
for player in &players {
}
for mut player in &mut players {
}
}
Query::iter_many #
It is now possible to pass a list of entities to a Query
to iterate over using Query::iter_many
, which is significantly more ergonomic than calling get(entity)
on each individual entity:
#[derive(Component)]
struct BlueTeam {
members: Vec<Entity>,
}
fn system(blue_team: Res<BlueTeam>, players: Query<&Player>) {
info!("Blue Team Assemble!");
for player in players.iter_many(&blue_team.members) {
info!("{}", player.name);
}
}
There is also a Query::iter_many_mut
, which provides similar functionality for mutable queries. But to ensure aliased mutability is not allowed, it does not implement iterator. Instead, use this pattern:
let mut iter = players.iter_many_mut(&blue_team.members);
while let Some(mut player) = iter.fetch_next() {
player.score += 1;
}
Convert Mutable Queries to Read-only #
Mutable Queries
can now be converted to their read-only versions, which makes it easier to build and use abstractions over queries:
fn system(mut players: Query<&mut Player>) {
for mut player in &mut players {
// mutate players here
}
log_players(players.to_readonly());
}
fn log_players(players: Query<&Players>) {
for player in &players {
info!("{player:?}");
}
}
ECS "lifetimed pointers" #
Bevy ECS has been refactored to use lifetimed, type-erased pointers instead of "raw pointers", which significantly improved the safety and legibility of our internals without compromising performance or flexibility.
From a high level, this enables us to "retain" the lifetime of World borrows throughout our internals while still using type-erased APIs to support scenarios like 3rd party scripting languages.
By retaining this lifetime, we can rely more on Rust's borrow checker to yell at us when we are doing something unsound. And, as it happens, this caught a number of soundness bugs!
ECS Query Internals Refactors #
@BoxyUwU
has been hard at work refactoring our Query
internals to be simpler and easier to read:
ReadOnlyFetch
was replaced withReadOnlyWorldQuery
, moving this trait constraint "up a level", making it easier to express in the type system.- "QF Fetch generics" were removed from
Query
andQueryState
methods and types in favor ofWorldQuery
usage, making filters and normal fetches consistent in the type system and simpler to express.
We have more changes in this vein planned for the next release. Bevy ECS internals are becoming considerably easier to understand!
ECS Optimizations #
Bevy ECS had a number of optimizations this time around:
@james7132
sped up entity moves between tables by reducing the number of copies conducted. For larger components, this is a huge win. Themany_cubes
stress test saw a ~16% speed boost in theprepare_uniform_components
system, which relies heavily on commands / table moves.@DJMcNab
removed no-op drop function calls for ECS storage internals, which reduced the dropping time for themany_cubes
stress test from ~150μs to ~80μs.@james7132
changedComponentSparseSet
indices fromusize
tou32
, which makes them use less space / making some operations more cache friendly. Sparse Set iteration became ~15% faster with this change.
Label Optimizations #
Bevy relies on "labels" to identify things like systems, stages, and apps. This is useful for things like defining system dependencies. The traits SystemLabel
, StageLabel
, and AppLabel
build on the same underlying "typed label" system. It enables developers to define custom labels while retaining type safety. Much better than using something like a string or an integer label!
In Bevy 0.8 we've optimized the internal representation of labels by removing boxing / trait objects in favor of a single cheap-to-copy-and-compare "system label id" type.
This new representation sped up schedule construction by ~30%!
time to prepare and compute schedule with 100 systems (in milliseconds, less is better) #
This change also removed a number of trait requirements from our label derives:
// Old (Bevy 0.7)
#[derive(SystemLabel, Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum MovementSystem {
Velocity,
Gravity,
}
// New (Bevy 0.8)
#[derive(SystemLabel, Clone)]
enum MovementSystem {
Velocity,
Gravity,
}
Hierarchy Commands #
Bevy's entity hierarchy system is based on two components: Parent
(which points to an entity's parent) and Children
(which points to a list of the entity's children). This separation is important, as it makes it easy and cheap to query for "hierarchy roots":
fn system(roots: Query<Entity, Without<Parent>>) { }
In past versions of Bevy, we built a complex system to "maintain" the integrity of the hierarchy. As Parent
/ Children
components were added/removed/changed for an entity, we would do our best to sync everything up across the hierarchy.
However this meant that for a given point in time, the hierarchy could be "out of sync" and incorrect.
Our solution to this problem is to remove the deferred "hierarchy maintenance system" in favor of making hierarchy changes "transactional". Hierarchy changes are now done via transactional Commands
, and directly modifying the component fields individually is no longer possible. This ensures that for a given point in time, the hierarchy is "correct".
For most Bevy developers this is a non-breaking change, as most hierarchies are already constructed using with_children
commands:
commands
.spawn_bundle(SpatialBundle::default())
.with_children(|parent| {
parent.spawn_bundle(SpriteBundle {
texture: player_texture,
..default()
});
parent.spawn_bundle(SpriteBundle {
texture: hat_texture,
..default()
});
});
However for logic that adds/removes child entities from parents at runtime, the following commands must be used:
// removes the given children from the parent
commands.entity(some_parent).remove_children(&[child1, child2]);
// pushes the given children to the "end" of the parent's Children list
commands.entity(some_parent).push_children(&[child3, child4]);
// inserts the given children into the parent's Children list at the given index
commands.entity(some_parent).insert_children(1, &[child5]);
We've also added HierarchyEvent
, which makes it possible for developers to track changes in the hierarchy.
There are still a couple of small holes to close, but staying on the "happy path" is much easier now:
- removing only one of the components is possible (although heavily discouraged)
- adding default values of only one of the components manually is still possible (although heavily discouraged)
We're discussing ways to resolve this class of problem, such as Archetype Rules / Invariants.
Bevy Reflection Improvements #
Bevy's "Rust reflection" system bevy_reflect
is a core, foundational piece of Bevy's scene system. It provides a way to dynamically interact with Rust types at run-time without knowing their actual types. We've invested heavily in it this release to prepare for scripting support and scene system improvements.
bevy_reflect
aims to be a "generic" Rust reflection system. It can be used without Bevy. We believe it fills a very real gap in the Rust ecosystem and we encourage the wider Rust community to use it (and contribute!).
"Untyped" Reflection #
The Reflect
derives now automatically add a new ReflectFromPtr
struct to the TypeRegistry
for each reflected type. This enables using the new untyped ECS APIs in combination with the reflection system. This helps enable things like 3rd party scripting and modding.
Default Trait Reflection #
It is now possible to construct Reflect
types using their Default
trait impl, provided they register it as part of the Reflect
derive:
#[derive(Reflect, Default)]
#[reflect(Default)]
struct MyStruct {
foo: String,
bar: usize,
}
let registration = type_registry.get(TypeId::of::<MyStruct>()).unwrap();
let reflect_default = registration.data::<ReflectDefault>().unwrap();
// This contains a MyStruct instance with default values
let my_struct: Box<dyn Reflect> = reflect_default.default();
This enables constructing components for entities without any compile time information, which is useful for dynamic scenarios like scripting and scenes.
Array Reflection #
Bevy's reflection system now supports reflecting Rust arrays, which can be interacted with in a type-erased manner using the new Array
trait.
#[derive(Reflect)]
struct Sprite {
position: [f32; 2],
}
let sprite = Sprite {
position: [0.1, 0.2],
};
let position = sprite.field("position").unwrap();
if let ReflectRef::Array(array) = position.reflect_ref() {
let x = array.get(0).unwrap();
assert_eq!(x.downcast_ref::<f32>(), Some(&0.1));
}
Static TypeInfo #
The Reflect
trait provides dynamic access to a specific instance of a type, but some scenarios (such as deserializing) benefit from knowing type information before we have an instance of a type. This opens the doors to building a Reflect-based serde
alternative (or at the very least, a serde-less Bevy Scene deserializer).
Bevy 0.8 adds the ability to retrieve TypeInfo
for any type implementing Reflect
:
#[derive(Reflect)]
struct Foo {
a: f32,
b: usize,
}
let info = Foo::type_info();
if let TypeInfo::Struct(info) = info {
assert!(info.is::<Foo>());
assert_eq!(info.type_name(), std::any::type_name::<Foo>(),);
assert!(info.field("a").unwrap().is::<f32>());
assert!(info.field_at(1).unwrap().is::<usize>());
}
Note that type_info()
returns &'static TypeInfo
: it will lazily allocate and store TypeInfo
the first time it is requested, then reuse that on each subsequent request.
Generic types also support TypeInfo
:
#[derive(Reflect)]
struct Foo<T> {
value: T
}
let info = Foo::<f32>::type_info();
if let TypeInfo::Struct(info) = info {
assert!(info.field("value").unwrap().is::<f32>());
}
Resource Reflection #
Bevy ECS resources can now be reflected:
#[derive(Reflect)]
#[reflect(Resource)]
struct Scoreboard {
points: usize,
}
This registers a ReflectResource
in the TypeRegistry
entry for the type, enabling type-erased read/write operations for the resource in an ECS World
.
Pretty Reflect Debug Formatting #
"Debug printing" Reflect
references now provides pretty / useful outputs.
Consider the following example:
#[derive(Reflect)]
struct Foo {
a: f32,
b: Bar,
}
#[derive(Reflect)]
struct Bar {
x: String,
y: usize,
}
let foo = Foo {
a: 42.0,
b: Bar {
x: "hello".to_string(),
y: 123,
},
};
let foo_reflect: &dyn Reflect = &foo;
println!("{:#?}", foo_reflect);
In previous versions of Bevy, this would have printed:
Reflect(my_crate::Foo)
In Bevy 0.8, it prints:
my_crate::Foo {
a: 42.0,
b: my_crate::Bar {
x: "hello",
y: 123,
},
}
Much better!
bevy_reflect Internal Refactors #
Now that bevy_reflect
is starting to get some serious investment and usage, we've invested time in reworking the internals to make them easier to maintain and extend:
Reflect
Derive Reorganization: the derive logic was broken up into smaller, more maintainable pieces. "Metadata structs" were added to collect and organize derive inputs. (@MrGVSV
)- The
Reflect
trait is now safe to implement: Soundness no longer hinges on the implementor doing the right thing, thanks to some changes to theReflect
interface. As a result, we were able to remove theunsafe
keyword from theReflect
trait. (@PROMETHIA-27
) Serialize
logic is now implemented usingTypeRegistry
type data like other reflected trait logic, rather than being hard-coded intoReflect
impls. (@jakobhellermann
)
Render World Extract #
Note: The renderer APIs discussed here are for developers of advanced custom rendering features and core Bevy renderer developers. If this seems verbose or the intent is confusing, don't worry!
Bevy's new renderer "extracts" data needed for rendering from the "main" Bevy app, which enables parallel pipelined rendering. To facilitate this, in previous versions of Bevy we made the ECS RenderStage::Extract
"special" (and more than a little bit weird). Systems in that stage ran on the "main" app world, but applied the system Commands
to the "render" app world.
This accomplished the goal, but it:
- Was confusing: render feature developers had to "know" that this stage behaved differently from the other "normal" ECS stages in the schedule. Implicitly,
Commands
behaved differently and the ECS data access was "flipped". Using "normal" entity spawning APIs would not work as expected because theCommands
parameter internally still used the main app's Entities collection. - Prevented parallelism: directly modifying existing "render world" resources required exclusive access to
ResMut<RenderWorld>
, which prevented these systems from running in parallel. Making this access parallel required unnecessary allocations usingCommands
, which for "large" (or incrementally updated) extractions was inefficient.
// Old: Bevy 0.7 (limited parallelism)
fn extract_score(score: Res<Score>, mut render_world: ResMut<RenderWorld>) {
*render_world.resource_mut::<ExtractedScore>() = ExtractedScore::from(score);
}
// Old: Bevy 0.7 (unnecessary allocations / prevents incremental updates)
fn extract_score(mut commands: Commands, score: Res<Score>) {
commands.insert_resource(ExtractedScore::from(&score));
}
In Bevy 0.8, we've made the extract stage "normal". It runs directly on the "render world", just like the other render app stages. To "extract" data from the main app world, just wrap the relevant system parameters in the new Extract
type to retrieve that parameter from the main app world instead:
// New: Bevy 0.8 (parallel and not weird!)
fn extract_score(mut extracted_score: ResMut<ExtractedScore>, score: Extract<Res<Score>>) {
*extracted_score = ExtractedScore::from(&score);
}
The extract system is now parallel, the data access is consistent with other renderer ECS stages, and the intent of the system is clearer.
ExtractResource Trait and Plugin #
Some ECS resources have very simple extract logic:
fn extract_cool_color(mut extracted_cool_color: ResMut<CoolColor>, cool_color: Extract<Res<CoolColor>>) {
*extracted_cool_color = cool_color.clone();
}
Rather than force developers to write this out manually, Bevy 0.8 now provides the ExtractResource
trait / derive:
#[derive(ExtractResource, Clone)]
struct CoolColor {
color: Color,
}
Then, just add the ExtractResourcePlugin<CoolColor>
to your App
and the resource will be automatically extracted.
ExtractResource
can also be implemented manually if you need custom logic (or the type needs to change):
impl ExtractResource for ExtractedCoolColor {
type Source = CoolColor;
fn extract_resource(source: &CoolColor) -> Self {
Self {
color: source.color.as_rgba_linear(),
}
}
}
Taffy migration: a refreshed UI layout library #
Bevy's moved off the abandoned stretch
UI layout crate and onto its new community-maintained hard fork: taffy
. Together with the Dioxus team, we've dramatically cleaned up the code base, solved a critical performance issue with deep UI trees and freshened up the docs.
We're looking forward to its continued maintenance and development as the team continues to improve its performance, fix bugs, and add support for alternative layout paradigms.
ECS Soundness / Correctness Improvements #
Bevy ECS received a solid number of soundness and correctness bug fixes this release:
- Removed
EntityMut::get_unchecked
: The only way to soundly use this API is already encapsulated withinEntityMut::get
. Therefore there was no reason to keep this unsafe API around. - Fixed unsoundness with some
Or
/AnyOf
/Option
component access: Previous Bevy versions allowed unsound versions of these queries. We now properly prevent those uses. - Improve soundness of
CommandQueue
: It is now sound to store Commands with padding or uninitialized bytes. A "use after move" case was also removed. - Fix some memory leaks detected by Miri: Miri detected a case that leaks in our
BlobVec
drop impl. That is now fixed. - Lint for missing SAFETY comments in
bevy_ecs
: We now require safety comments for unsafe code blocks inbevy_ecs
.
As Bevy ECS matures, our bar for unsafe code blocks and soundness must also mature. Bevy ECS will probably never be 100% free of unsafe code blocks because we are modeling parallel data access that Rust cannot reason about without our help. But we are committed to both removing as much unsafe code as we can and improving the quality of the unsafe code that remains.
Android Progress: We aren't there yet, but we're closer! #
Bevy now "kind of" runs on Android again!
However Android support is not ready yet. There are issues with how we manage render contexts that must be resolved that sometimes break rendering at startup and always break rendering when apps are minimized. Audio also doesn't work yet.
Here is the load_gltf
Bevy example running on my Pixel 6:
That being said, this is an important step forward, as Bevy developers can now build, deploy, (and in some cases test) Bevy apps on Android!
If you are itching to test Bevy on mobile platforms, our iOS support is much more polished. Bevy developers have already started publishing Bevy-based iOS apps to the Apple App Store!
CI / Build System Improvements #
As always, Bevy's CI had plenty of improvements this cycle:
- Examples are now run in WASM when validating builds. Screenshots are taken and stored as part of the build outputs to ensure rendering works (
@mockersf
). - The Bevy examples are now run on a Windows VM once per day to ensure they aren't broken (
@mockersf
). - License files are now automatically added to all published crates (
@NiklasEi
). - There is now a workflow to automatically generate a PR with version number bumps for all Bevy crates (
@mockersf
). - To make the occasional nightly Rust breakage less disruptive, we've parameterized the nightly toolchain to make it easier to pin to a specific nightly. (
@mockersf
)
Example: Post Processing #
We've added a new example that shows how to use the new Camera Driven Rendering and Shader Materials to build a "chromatic aberration" post processing effects using a full screen quad and "render to texture".
We plan on building more formal post processing APIs in future releases, but this approach is relatively straightforward and opens up a lot of doors. Much simpler than extending the lower level RenderGraph
!
Run it by cloning the Bevy repo and running cargo run --release --example post_processing
.
Example: Many Animated Foxes #
This is a fun stress test of our Skeletal Animation System that renders many animated foxes walking around in a circle.
Run it by cloning the Bevy repo and running cargo run --release --example many_foxes
.
WASM Example Build Tool #
We've built a tool to make it easier to build and run Bevy's examples in your browser:
In the root of the Bevy repo, run the following command:
cargo run -p build-wasm-example -- lighting
This will run the cargo build
and wasm-bindgen
commands, and place the output in the examples/wasm
folder. Run your favorite "local webserver" command there, such as python3 -m http.server
and open that url in your browser!
Website: Improved Examples Page #
The Bevy WASM Examples pages have been reworked:
- They now display loading bars while Bevy App content and assets load
- The design / layout of the page is now much nicer
Bevy Org Changes #
As Bevy grows, we are constantly re-evaluating our development process to accommodate an ever-increasing volume of development. We're long past the point where I can make every decision and I've been slowly delegating responsibilities as my trust in the knowledge and experience of our community members grows.
This release cycle, there were two major changes to the Bevy Org:
- All existing developers with "delegated merge rights" (
@mockersf
and@alice-i-cecile
) now have the title "maintainer". - Rob Swain (
@superdump
) is now a maintainer. You will probably recognize them from their work on Bevy's renderer. They've been a veritable force of nature, driving forward clustered forward rendering, directional and point light shadows, visibility / frustum culling, alpha blending, compressed GPU textures, and more. Rob has demonstrated deep understanding of rendering algorithms, Bevy internals, and Bevy project direction. I'm certainly looking forward to what they build next!
Being a "maintainer" now works like this:
- Maintainers now have no (hard) limits on the "area" of PRs they can merge. No more limits on "docs only", "rendering only", etc. It is now each maintainers' responsibility to evaluate their areas of comfort. This does increase risk to an extent, but I think it's an important step to allow maintainers to grow organically.
- Maintainers can merge "relatively uncontroversial" PRs with at least two community approvals. Maintainers will collectively decide and enforce what is uncontroversial. Controversial PRs should be labeled with the
S-Controversial
label. Note that "two community approvals" is the minimum requirement. Maintainers are responsible for ensuring the appropriate people have approved a PR. - Maintainers can merge "completely trivial" PRs without two community approvals. Some examples of "completely trivial": typo fixes, removing unused dependencies or code, and small "API consistency" fixes.
- Controversial Decision Making on a Timer: For all controversial PRs (including RFCs), if two maintainers approve, the PR can be labeled with a
S-Ready-For-Final-Review
label. As soon as this label is added and I have been pinged, a clock starts. If I have not responded with actionable feedback, a "snooze button" / "we aren't ready for this yet", or a veto within a month and a half (45 days), maintainers are free to merge the PR. This gives me the ability to dictate project direction in areas where that is important while also empowering maintainers to move things forward in parallel when that makes sense. We will be calibrating this approach as we go to make sure we strike the right balance between progress, quality, and consistent vision. - I still reserve the right to veto all code changes and make unilateral code changes. This includes reverting "controversial changes" merged via (4).
We've used this process for most of the last cycle and I'm loving how it is working so far: more trust, more eyes on each decision, faster development velocity, no more trivial fixes sitting in limbo. I still get to enforce consistent vision when that matters, but the community is empowered to drive efforts forward.
What's Next? #
- Post Processing: We have a lot of post processing work in the pipeline (some of it almost made it in to this release). The next release will make it easier to write post processing effects (thanks to intermediate HDR textures and a separate tonemapping step), and it will also include built-in effects like bloom and upscaling.
- Asset Preprocessing: We will be investing heavily in our asset pipeline, with a focus on:
- Pre-processing assets to do expensive work "during development time", so Bevy Apps can be deployed with assets that are prettier, smaller, and/or faster to load.
- Enabling configuring assets with
.meta
files. For example, you could define a texture compression level, the filter it should use, or the target format.
- Scene System Improvements: This release saw a lot of investment in Reflection. We can now build the next iteration of the scene system on top of it, with a nicer scene format, nested scenes, and improved workflows.
- Bevy UI Improvements: In preparation for the visual Bevy Editor, we will be improving the capabilities and user experince of Bevy UI.
- Bevy Jam #2: Bevy Jam #1 was a massive success: 74 entries, 1,618 ratings, and lots of good community vibes. Now that Bevy 0.8 is released, it's time to jam again! We'll release details on this soon. To stay in the loop, follow @BevyEngine on Twitter and join the Official Bevy Discord.
Support Bevy #
Sponsorships help make our work on Bevy sustainable. If you believe in Bevy's mission, consider sponsoring us ... every bit helps!
- Carter Anderson (@cart): Full-time lead developer, project manager, and creator of Bevy. Focused on building out core engine systems, guiding project direction, and managing the community.
- Alice Cecile (@alice-i-cecile): Full-time technical project manager, mad scientist, and documentation lead. While she regularly leads expeditions into new domains, ECS will always be home base.
- François Mockers (@mockersf): CI whisperer. Making sure everything is running smoothly and improving Bevy one PR at a time.
- Rob Swain (@superdump): Wielder of light. Turning data into shiny with massive parallelism. Currently hobby hacking so please donate to/sponsor the rest of the team. ❤️
Contributors #
A huge thanks to the 130 contributors that made this release (and associated docs) possible! In random order:
- @spooky-th-ghost
- @afonsolage
- @mlodato517
- @ostwilkens
- @mattwilkinsonn
- @geckoxx
- @SarthakSingh31
- @zicklag
- @teoxoy
- @nsarlin
- @HackerFoo
- @elijaharita
- @inact1v1ty
- @bjorn3
- @james-j-obrien
- @Daniikk1012
- @nihohit
- @Ku95
- @superdump
- @dilyankostov
- @SkiFire13
- @edwardvear
- @jakobhellermann
- @KDecay
- @TheRawMeatball
- @fadhliazhari
- @colepoirier
- @brandon-reinhart
- @Davier
- @ManevilleF
- @Bobox214
- @RalfJung
- @robtfm
- @its-danny
- @alice-i-cecile
- @MonaMayrhofer
- @yilinwei
- @MrGVSV
- @ickshonpe
- @bzm3r
- @nagisa
- @fgiordana
- @DJMcNab
- @oliverpauffley
- @64kramsystem
- @alteous
- @maniwani
- @hoshino111
- @Kanabenki
- @JoJoJet
- @x-52
- @djeedai
- @BoxyUwU
- @MDeiml
- @GarettCooper
- @hymm
- @mockersf
- @nebkor
- @2ne1ugly
- @BGR360
- @SUPERCILEX
- @CGMossa
- @infmagic2047
- @CleanCut
- @YoshieraHuang
- @kornelski
- @mdickopp
- @SpecificProtagonist
- @PROMETHIA-27
- @eiei114
- @Hoidigan
- @Wcubed
- @adsick
- @nicopap
- @siph
- @C-BJ
- @tamasfe
- @object71
- @LegNeato
- @Elabajaba
- @bytemuck
- @AronDerenyi
- @makspll
- @cryscan
- @NiklasEi
- @grace125
- @NathanSWard
- @IceSentry
- @Vrixyz
- @Piturnah
- @its-justus
- @dataphract
- @thomas992
- @Olexorus
- @ShadowCurse
- @LoipesMas
- @ImDanTheDev
- @johanhelsing
- @wrapperup
- @james7132
- @rebelroad-reinhart
- @SuperSamus
- @manokara
- @Nilirad
- @NeoRaider
- @thebracket
- @sarkahn
- @MrPicklePinosaur
- @Shatur
- @themasch
- @devil-ira
- @fluunke
- @DGriffin91
- @aevyrie
- @henryksloan
- @bwasty
- @MiniaczQ
- @rparrett
- @komadori
- @ChristopherBiscardi
- @dtaralla
- @Sheepyhead
- @TethysSvensson
- @Neopallium
- @FraserLee
- @cart
- @Obdzen
- @oddfacade
- @CAD97
- @XBagon
Full Change Log #
Added #
- Callable PBR functions
- Spotlights
- Camera Driven Rendering
- Camera Driven Viewports
- Visibilty Inheritance, universal
ComputedVisibility
, andRenderLayers
support - Better Materials:
AsBindGroup
trait and derive, simplerMaterial
trait - Derive
AsBindGroup
Improvements: Better errors, more options, update examples - Support
AsBindGroup
for 2d materials as well - Parallel Frustum Culling
- Hierarchy commandization
- Generate vertex tangents using mikktspace
- Add a
SpatialBundle
withVisibility
andTransform
components - Add
RegularPolygon
andCircle
meshes - Add a
SceneBundle
to spawn a scene - Allow higher order systems
- Add global
init()
andget()
accessors for all newtypedTaskPools
- Add reusable shader functions for transforming position/normal/tangent
- Add support for vertex colors
- Add support for removing attributes from meshes
- Add option to center a window
- Add
depth_load_op
configuration field toCamera3d
- Refactor
Camera
methods and add viewport rect - Add
TextureFormat::R16Unorm
support forImage
- Add a
VisibilityBundle
withVisibility
andComputedVisibility
components - Add ExtractResourcePlugin
- Add depth_bias to SpecializedMaterial
- Added
offset
parameter toTextureAtlas::from_grid_with_padding
- Add the possibility to create custom 2d orthographic cameras
- bevy_render: Add
attributes
andattributes_mut
methods toMesh
- Add helper methods for rotating
Transform
s - Enable wgpu profiling spans when using bevy's trace feature
- bevy_pbr: rework
extract_meshes
- Add
inverse_projection
andinverse_view_proj
fields to shader view uniform - Add
ViewRangefinder3d
to reduce boilerplate when enqueuing standard 3DPhaseItems
- Create
bevy_ptr
standalone crate - Add
IntoIterator
impls for&Query
and&mut Query
- Add untyped APIs for
Components
andResources
- Add infallible resource getters for
WorldCell
- Add
get_change_ticks
method toEntityRef
andEntityMut
- Add comparison methods to
FilteredAccessSet
- Add
Commands::new_from_entities
- Add
QueryState::get_single_unchecked_manual
and its family members - Add
ParallelCommands
system parameter - Add methods for querying lists of entities
- Implement
FusedIterator
for eligibleIterator
types - Add
component_id()
function toWorld
andComponents
- Add ability to inspect entity's components
- Add a more helpful error to help debug panicking command on despawned entity
- Add
ExactSizeIterator
implementation forQueryCombinatonIter
- Added the
ignore_fields
attribute to the derive macros for*Label
types - Exact sized event iterators
- Add a
clear()
method to theEventReader
that consumes the iterator - Add helpers to send
Events
fromWorld
- Add file metadata to
AssetIo
- Add missing audio/ogg file extensions: .oga, .spx
- Add
reload_asset
method toAssetServer
- Allow specifying chrome tracing file path using an environment variable
- Create a simple tool to compare traces between executions
- Add a tracing span for run criteria
- Add tracing spans for
Query::par_for_each
and its variants. - Add a
release_all
method onInput
- Add a
reset_all
method onInput
- Add a helper tool to build examples for wasm
- bevy_reflect: add a
ReflectFromPtr
type to create&dyn Reflect
from a*const ()
- Add a
ReflectDefault
type and add#[reflect(Default)]
to all component types that implement Default and are user facing - Add a macro to implement
Reflect
for struct types and migrate glam types to use this for reflection - bevy_reflect: reflect arrays
- bevy_reflect: reflect char
- bevy_reflect: add
GetTypeRegistration
impl for reflected tuples - Add reflection for
Resources
- bevy_reflect: add
as_reflect
andas_reflect_mut
methods onReflect
- Add an
apply_or_insert
method toReflectResource
andReflectComponent
- bevy_reflect:
IntoIter
forDynamicList
andDynamicMap
- bevy_reflect: Add
PartialEq
to reflectedf32
s andf64
s - Create mutable versions of
TypeRegistry
methods - bevy_reflect: add a
get_boxed
method toreflect_trait
- bevy_reflect: add
#[reflect(default)]
attribute forFromReflect
- bevy_reflect: add statically available type info for reflected types
- Add an
assert_is_exclusive_system
function - bevy_ui: add a multi-windows check for
Interaction
(we dont yet support multiple windows)
Changed #
- Depend on Taffy (a Dioxus and Bevy-maintained fork of Stretch)
- Use lifetimed, type erased pointers in bevy_ecs
- Migrate to
encase
fromcrevice
- Update
wgpu
to 0.13 - Pointerfication followup: Type safety and cleanup
- bevy_ptr works in no_std environments
- Fail to compile on 16-bit platforms
- Improve ergonomics and reduce boilerplate around creating text elements
- Don't cull
Ui
nodes that have a rotation - Rename
ElementState
toButtonState
- Move
Size
tobevy_ui
- Move
Rect
tobevy_ui
and rename it toUiRect
- Modify
FontAtlas
so that it can handle fonts of any size - Rename
CameraUi
- Remove
task_pool
parameter frompar_for_each(_mut)
- Copy
TaskPool
resoures to sub-Apps - Allow closing windows at runtime
- Move the configuration of the
WindowPlugin
to aResource
- Optionally resize
Window
canvas element to fit parent element - Change window resolution types from tuple to
Vec2
- Update time by sending frame
Instant
through a channel - Split time functionality into
bevy_time
- Split mesh shader files to make the shaders more reusable
- Set
naga
capabilities corresponding towgpu
features - Separate out PBR lighting, shadows, clustered forward, and utils from pbr.wgsl
- Separate PBR and tonemapping into 2 functions
- Make
RenderStage::Extract
run on the render world - Change default
FilterMode
ofImage
toLinear
- bevy_render: Fix KTX2 UASTC format mapping
- Allow rendering meshes without UV coordinate data
- Validate vertex attribute format on insertion
- Use
Affine3A
forGlobalTransform
to allow any affine transformation - Recalculate entity
AABB
s when meshes change - Change
check_visibility
to use thread-local queues instead of a channel - Allow unbatched render phases to use unstable sorts
- Extract resources into their target location
- Enable loading textures of unlimited size
- Do not create nor execute render passes which have no
PhaseItems
to draw - Filter material handles on extraction
- Apply vertex colors to
ColorMaterial
andMesh2D
- Make
MaterialPipelineKey
fields public - Simplified API to get NDC from camera and world position
- Set
alpha_mode
based on alpha value - Make
Wireframe
respectVisibleEntities
- Use const
Vec2
in lights cluster and bounding box when possible - Make accessors for mesh vertices and indices public
- Use
BufferUsages::UNIFORM
forSkinnedMeshUniform
- Place origin of
OrthographicProjection
at integer pixel when usingScalingMode::WindowSize
- Make
ScalingMode
more flexible - Move texture sample out of branch in
prepare_normal
- Make the fields of the
Material2dKey
public - Use collect to build mesh attributes
- Replace
ReadOnlyFetch
withReadOnlyWorldQuery
- Replace
ComponentSparseSet
's internals with aColumn
- Remove QF generics from all
Query/State
methods and types - Remove
.system()
- Make change lifespan deterministic and update docs
- Make derived
SystemParam
readonly if possible - Merge
matches_archetype
andmatches_table
- Allows conversion of mutable queries to immutable queries
- Skip
drop
whenneeds_drop
isfalse
- Use u32 over usize for
ComponentSparseSet
indicies - Remove redundant
ComponentId
inColumn
- Directly copy moved
Table
components to the target location SystemSet::before
andSystemSet::after
now takeAsSystemLabel
- Converted exclusive systems to parallel systems wherever possible
- Improve
size_hint
onQueryIter
- Improve debugging tools for change detection
- Make
RunOnce
a non-manualSystem
impl - Apply buffers in
ParamSet
- Don't allocate for
ComponentDescriptors
of non-dynamic component types - Mark mutable APIs under ECS storage as
pub(crate)
- Update
ExactSizeIterator
impl to support archetypal filters (With
,Without
) - Removed world cell from places where split multable access is not needed
- Add Events to
bevy_ecs
prelude - Improve
EntityMap
API - Implement
From<bool>
forShouldRun
. - Allow iter combinations on custom world queries
- Simplify design for
*Label
s - Tidy up the code of events
- Rename
send_default_event
tosend_event_default
on world - enable optional dependencies to stay optional
- Remove the dependency cycles
- Enforce type safe usage of Handle::get
- Export anyhow::error for custom asset loaders
- Update
shader_material_glsl
example to include texture sampling - Remove unused code in game of life shader
- Make the contributor birbs bounce to the window height
- Improve Gamepad D-Pad Button Detection
- bevy_reflect: support map insertion
- bevy_reflect: improve debug formatting for reflected types
- bevy_reflect_derive: big refactor tidying up the code
- bevy_reflect: small refactor and default
Reflect
methods - Make
Reflect
safe to implement bevy_reflect
: putserialize
into externalReflectSerialize
type- Remove
Serialize
impl fordyn Array
and friends - Re-enable
#[derive(TypeUuid)]
for generics - Move primitive type registration into
bevy_reflect
- Implement reflection for more
glam
types - Make
reflect_partial_eq
return more accurate results - Make public macros more robust with
$crate
- Ensure that the parent is always the expected entity
- Support returning data out of
with_children
- Remove
EntityMut::get_unchecked
- Diagnostics: meaningful error when graph node has wrong number of inputs
- Remove redundant
Size
import - Export and register
Mat2
. - Implement
Debug
forGamepads
- Update codebase to use
IntoIterator
where possible. - Rename
headless_defaults
example tono_renderer
for clarity - Remove dead
SystemLabelMarker
struct - bevy_reflect: remove
glam
from a test which is active without the glam feature - Disable vsync for stress tests
- Move
get_short_name
utility method frombevy_reflect
intobevy_utils
- Derive
Default
for enums where possible - Implement
Eq
andPartialEq
forMouseScrollUnit
- Some cleanup for
bevy_ptr
- Move float_ord from
bevy_core
tobevy_utils
- Remove unused
CountdownEvent
- Some minor cleanups of asset_server
- Use
elapsed()
onInstant
- Make paused
Timers
updatejust_finished
on tick - bevy_utils: remove hardcoded log level limit
- Make
Time::update_with_instant
public for use in tests - Do not impl Component for Task
- Remove nonexistent
WgpuResourceDiagnosticsPlugin
- Update ndk-glue requirement from 0.5 to 0.6
- Update tracing-tracy requirement from 0.8.0 to 0.9.0
- update image to 0.24
- update xshell to 0.2
- Update gilrs to v0.9
- bevy_log: upgrade to tracing-tracy 0.10.0
- update hashbrown to 0.12
- Update
clap
to 3.2 in tools usingvalue_parser
- Updated
glam
to0.21
. - Update Notify Dependency
Fixed #
- bevy_ui: keep
Color
as 4f32
s - Fix issues with bevy on android other than the rendering
- Update layout/style when scale factor changes too
- Fix
Overflow::Hidden
so it works correctly withscale_factor_override
- Fix
bevy_ui
touch input - Fix physical viewport calculation
- Minimally fix the known unsoundness in
bevy_mikktspace
- Make
Transform
propagation correct in the presence of updated children StorageBuffer
uses wrong type to calculate the buffer size.- Fix confusing near and far fields in Camera
- Allow minimising window if using a 2d camera
- WGSL: use correct syntax for matrix access
- Gltf: do not import
IoTaskPool
in wasm - Fix skinned mesh normal handling in mesh shader
- Don't panic when
StandardMaterial
normal_map
hasn't loaded yet - Fix incorrect rotation in
Transform::rotate_around
- Fix
extract_wireframes
- Fix type parameter name conflicts of
#[derive(Bundle)]
- Remove unnecessary
unsafe impl
ofSend+Sync
forParallelSystemContainer
- Fix line material shader
- Fix
mouse_clicked
check for touch - Fix unsoundness with
Or
/AnyOf
/Option
component access - Improve soundness of
CommandQueue
- Fix some memory leaks detected by miri
- Fix Android example icon
- Fix broken
WorldCell
test - Bugfix
State::set
transition condition infinite loop - Fix crash when using
Duration::MAX
- Fix release builds: Move asserts under
#[cfg(debug_assertions)]
- Fix frame count being a float
- Fix "unused" warnings when compiling with
render
feature but withoutanimation
- Fix re-adding a plugin to a
PluginGroup
- Fix torus normals
- Add
NO_STORAGE_BUFFERS_SUPPORT
shaderdef when needed