This Week in Bevy

What happened this week in the Bevy Engine ecosystem

Links

Required Components, Curves, and the Bevy CLI Working Group

2024-09-02

Welcome back to This Week in Bevy!

This week we've got some great progress on Scenes/UI work with Required Components merging, a new Bevy CLI working group, and some great progress in the Curves group.

We've also got some exciting crate releases including an official bevy_magic_light_2d crates.io release and a new Avian Pickup plugin for portal-like shenanigans.

Required Components

Required Components is part of the recent Scenes/bsn! work and has been merged! This has a huge impact on Bundle use cases, although Bundles have not gone anywhere. (note: do not worry, the team is putting great thought into how these APIs will evolve and this is the beginning work, not the end-state).

Required Components show up in end-user APIs as a require attribute macro on Components.

#[require(Node, UiImage)]

As is common when talking about work that was just merged, Required Components are a beginning step in the Next Generation Scene / UI Proposal so expect further work in this area before official release.

The most succinct way I've seen to show the difference Required Component makes is to show the impact on an existing bundle, like the ButtonBundle.

#[derive(Component)]
#[require(Node, UiImage)]
struct Button;

commands.spawn((
    Button,
    Style { 
        width: Val::Px(100.0),
        height: Val::Px(50.0),
        ..default()
    },
    FocusPolicy::Block,
));

Note that generally, required components are for invariants. That is, additional components that the component in question does not work without. This is especially relevant when considering library code but it is worth noting that as with any new functionality, the lines are still being drawn.

Meshlet software raster

meshlets overlaid on render

meshlet debug output overlaid on a rendered scene

Meshlets see improvements in #14623, which includes work towards faster meshlet rasterization path for small triangles, avoiding having to allocate and write out a triangle buffer, and more. The PR is wonderfully documented and includes technical details for changes.

The MeshletPlugin now comes with a cluster_buffer_slots

MeshletPlugin {
    cluster_buffer_slots: 8192,
}

The rough tldr; on cluster_buffer_slots is that it needs to be set to the worst case amount of clusters per pass in your scene over all cameras, which is a number that can obviously vary per-user. If you get the number wrong (as in, too low), you'll notice missing or flickering areas.

Observers

Debug for Trigger

#14857 introduces a Debug implementation for Trigger, which enables a more streamlined developer experience when debugging scaffolded Observers.

.observe(|e: Trigger<OnAdd, Skeleton>| {
    dbg!(e);
});

The output includes the event information, propagation, and ObserverTrigger.

on_add_mine: Trigger {
    event: OnAdd,
    propagate: false,
    trigger: ObserverTrigger {
        observer: 2v1#4294967298,
        event_type: ComponentId(
            0,
        ),
        entity: 454v1#4294967750,
    },
    _marker: PhantomData<observers::Mine>,
}

on_unimplemented for IntoObserverSystem

Observer systems must have a Trigger as their first argument and in #14840 the error message when this isn't the case includes a reminder.

for function ObserverSystems, ensure the first argument is a Trigger<T> and any subsequent ones are SystemParam

The Type type

#14838 introduces the Type struct to bevy_reflect. This type contains both the TypeId and the TypePathTable of the given type, allowing it to be used like TypeId but have the debugging capacity of TypePath.

Screenshots

As of #14833, screenshots can now use any RenderTarget and have a new Component-and-Observer-based API.

use bevy_render::view::screenshot::{save_to_disk, Screenshot};

commands
    .spawn(Screenshot::primary_window())
    .observe(save_to_disk(path));

New Run Conditions

In #14917 two new Conditions were introduced including:

  • condition_changed, which changes whenever the inner condition changes
  • condition_changed_to, which returns true whenever the inner condition changes to match true or false, depending on user configuration

Plane3d Gizmo updates

Plane3d gizmo

As of #14650 the Plane3d primitive gizmo now displays as a grid to better show the existence of a plane. Previously it was axes which had some issues when trying to view distant or off-axis plane locations.

gizmos
    .primitive_3d(
        &Plane3d {
            normal: Dir3::Y,
            half_size: Vec2::splat(1.0),
        },
        Isometry3d::new(
            Vec3::ONE * 4.0 + Vec2::from(time.elapsed_seconds().sin_cos()).extend(0.0),
            Quat::from_rotation_x(PI / 2. + time.elapsed_seconds()),
        ),
        GREEN,
    )
    .cell_count(UVec2::new(5, 10))
    .spacing(Vec2::new(0.2, 0.1));

Binary Size Reductions

#14865 is a GitHub Discussion that takes a look at generic/monomorphized code to see where there could be some savings in final binary size by moving some code around without changing existing APIs. #14865 is the first follow up on this research by splitting GenericTypeCell::get_or_insert up.

This work results in a 2% size reduction (approx 428KiB) of the final binary when building the 3d_scene example.

Further work is happening in #14934 which is seeing even more improvements already (which we'll cover in the future when/if it merges).

atomicow

#11478 details the desire to shrink the bevy_utils crate and put the functionality inside it in better places. As part of this, CowArc was moved to the new, generally usable outside Bevy, atomicow crate and its usage inside Bevy was replaced with the new crate in #14975.

CowArc is an enum that represents owned, borrowed, or static data, that is: cheap immutable references that can be converted into an owned form when mutation or ownership is required.

pub enum CowArc<'a, T: ?Sized + 'static> {
    Borrowed(&'a T),
    Static(&'static T),
    Owned(Arc<T>),
}

IMO: It should really have an atomic cow logo... :laughing:

Working Groups

bevy_mod_picking: the upstreamening

sprite_picking

#14757 adds a sprite backend to the upstreamed bevy_picking and adds a new example in examples/picking/sprite_picking.rs showing off the functionality. Go click some bevy birds!

Curve Crew

2d curves

3d curves

New curve gizmos have been added for 2d and 3d in #14971 based on the previous bevy_math Curve work.

As of #14815 you can now sample curves from IntoIterator types. This allows sampling a curve at specific times t.

let times = [-0.5, 0.0, 0.5, 1.0, 1.5];

let finite_curve = function_curve(Interval::new(0.0, 1.0).unwrap(), |t| t * 3.0 + 1.0);
let samples = finite_curve.sample_iter(times).collect::<Vec<_>>();
let [y0, y1, y2, y3, y4] = samples.try_into().unwrap();

assert_eq!(y0, None);
assert_eq!(y1, Some(0.0 * 3.0 + 1.0));
assert_eq!(y2, Some(0.5 * 3.0 + 1.0));
assert_eq!(y3, Some(1.0 * 3.0 + 1.0));
assert_eq!(y4, None);

bevy_cli: please clap

A new working group dedicated to building a Bevy CLI has been created! The working group's initial scope can be found on hackmd and includes a bunch of relevant information. Give it a read if you're interested in what a Bevy CLI might look like!

The working group's discussions can be found in the official Bevy Discord, as can be all of the other working groups.


Alice's Merge Train is a maintainer-level view into active PRs, both those that are merging and those that need work.

Showcase

Bevy work from the #showcase channel in Discord and around the internet. Use hashtag #bevyengine.

space gamespace dude

Space Dude

showcase

Ships! Planets! Space! Here's an in-progress look at a space game.

scene editor

Visual Novel Editor

showcase

This visual novel scene editor powers adding new sprites, removing all or one sprite, switching the target window and scene, editing selected sprites, and saving scene files supported. It has a novel script system with IDE-support and a virtual window system.

card game

Creature Card Game

showcase

A card game where instead of mana you need to have a certain amount of creatures already in play to be allowed to play specific cards (and you play one card per turn), for now the "ai"-opponent just plays the first valid card in its hand.

bevy_2d_line

bevy_2d_line

showcase

behold. lines. of varying thickness. in 2 dimensions.

vehicle physics

Vehicle Physics

showcase

Early progress on a vehicle physics demo. It currently involves the forces needed to drive the car back and forth with steering.

Collide and Slide: Avian Physics

showcase

If you implement enough character controllers, you'll eventually come across the term "Collide and Slide". Functionally, this means when your character hits an angled wall it shouldn't stop, but rather continue sliding along that wall.

The goal of this project is to make an FPS example project that others can learn from and today's showcase is the collide-and-slide implementation.

ui improvementsui improvements

UI Improvements

showcase

Some UI Improvements for this game. Next up: creature models!

dr luke

Dr Luke's VJ Set

showcase

We've previously covered Dr Luke's VJ set, which now has a full recording uploaded on YouTube to enjoy.

pokemon-type shooterpokemon-type shooter

Pokemon-style Shooter

showcase

This scene in this Pokemon-style shooter has about 770,000 faces. The loading time is about 16 seconds and there are some great comments about serializing the computed colliders to optimize that loading time.

ominous building wipbuildingmonster

Ominous, Brutalist Building WIP

showcase

This ominous, brutalist building is being loaded using Qevy from a Quake .map.

4x terrain4x terrain after

4x terrain

showcase

Terrain generation for this 4x game was recently overhauled including the author's first wgsl shader.

spore-likespore-like

Spore-like Creatures

showcase

These spore-like creatures are procedurally created (inspired by this talk), and use 3d segments of a cylinder on particles, which will make more sense if you watch the talk.

top down shootertop down shooter

Top Down Shooter

showcase

Progress on this top-down shooter which uses gizmos instead of meshes to focus on the game logic. It started off with the bevy quickstart template and continued with a basic character controller, 2D rotation and Avian Physics Colliders and RigidBodies

animation blendinganimation blending ground

Blended node animations

showcase

Progress on an almost seamless blending, blended node animations with common pre-imported animations.

dronesdrones

either for SoloDev Jam #4

showcase

Launch and Recall drones in this SoloDev Jam entry. Launched drones will orbit the player and attack enemies.

Crates

New releases to crates.io and substantial updates to existing projects

bevy foliage tool

Bevy Foliage Tool

crate_release

Bevy Foliage Tool crate allows you to set height maps on a Foliage Scene, then paint density on foliage layers (each corresponding to one type of foliage) using events. Instanced mesh entities are spawned in chunks (for render distance occlusion) based on the heightmap + density + noise

bevy_magic_light_2d basebevy_magic_light_2d blurbevy_magic_light_2d final

bevy_magic_light_2d 0.8.0

crate_release

bevy_magic_light_2d is a dynamic 2D global illumination system for Bevy, based on SDF ray-marching and screen space irradiance cache probes.

Two new maintainers have been added to bevy_magic_light_2d (congrats if you're watching) and they've put in work to get a 0.8 release out for Bevy 0.14.1. This is effectively the first official crates.io release for the library, even though the code has been around awhile and powers the lighting in Jarl.

avian_pickupavian_pickup ai throw

avian_pickup

crate_release

Avian Pickup is a plugin for picking up, manipulating and throwing dynamic RigidBody props in Avian Physics.

Pick up nearby dynamic rigid bodies, pull far away ones towards you, and throw them around or drop them gently.

alertalert textbox

bevy_web_popups

crate_release

bevy_web_popups enables alert boxes on the web and on phones. That means you can use alerts with or without text boxes using a unified API across platforms.

fn bevy_system() {
    alert("important msg");

    show_textinput("set nickname:", "ok", "cancel", true);
}

// system processing events coming from the web plugin
fn process_events(
    mut events: EventReader<WebAlertResponse>,
) {
    for e in events.read() {
        if let WebAlertResponse::InputOk(text) = e {
            info!("user confirmed with text: {text}");
        }
    }
}

bevy_capture

crate_release

bevy_capture is a plugin for capturing frames from a Bevy application. It comes with some built-in encoders, e.g. for creating gifs or videos, and can be extended with custom encoders.

No devlogs this week
No Educational this week
Pull Requests Merged This Week
Contributing

Want to contribute to Bevy?

Here you can find two types of potential contribution: Pull Requests that might need review and Issues that might need to be worked on.

How do I contribute?

Pull Requests Opened this week

Issues Opened this week