Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add an example demonstrating callbacks with one-shot systems#23197

Open
alice-i-cecile wants to merge 2 commits intobevyengine:mainfrom
alice-i-cecile:callback-example-again
Open

Add an example demonstrating callbacks with one-shot systems#23197
alice-i-cecile wants to merge 2 commits intobevyengine:mainfrom
alice-i-cecile:callback-example-again

Conversation

@alice-i-cecile
Copy link
Member

Objective

This is a powerful pattern, but figuring out the exact incantation to call can be quite challenging!

Solution

Write a little prototype, turn it into a full example!

Testing

cargo run --example callbacks

@alice-i-cecile alice-i-cecile added A-ECS Entities, components, systems, and events C-Examples An addition or correction to our examples D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Mar 3, 2026
@github-project-automation github-project-automation bot moved this to Needs SME Triage in ECS Mar 3, 2026
Copy link
Contributor

@tbillington tbillington left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great example!

I don't want to bloat it, but any thoughts on including the other ways of doing this?

eg world.run_system(id) giving you more explicit ordering (because you are now in an exclusive system), or commands.run_system_with(id, input) to allow passing arguments.

I get they may be overkill for this kind of example, but perhaps just the _with variation might be nice to have as I've used that pattern in the past for button callbacks etc (eg passing Entity), and I think feathers uses it now?

//! Sometimes, you want an extremely flexible way to store logic associated with an entity.
//! This example demonstrates how to store arbitrary systems in components and run them on demand.
//!
//! This pattern will be relatively slow, but it can work well for things like cutscenes, scripted events,
Copy link
Contributor

@tbillington tbillington Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking :D feel free to ignore

This pattern will be relatively slow

Would personally word it more like this??

This pattern trades some performance for flexibility and works well for things like cutscenes, scripted events,

personally if I see something described as "relatively slow" I assume it's like 10x slower, and a light warning by the developers to not use this if you don't have to. I understand it's actually "somewhat slower relative to scheduled systems", but that nuance might not be understood by someone unfamiliar with bevy ecs.

Copy link
Contributor

@ChristopherBiscardi ChristopherBiscardi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use "callback" in bevy's internals and it always means impl Fn*, so the usage of it to mean "a SystemId" is a bit awkward and feels like we're constructing, naming, and front-loading a new term that doesn't match prior usage. I probably would've went with something more like "systems ids in components" or one_shot_systems_in_components for discoverability reasons.

That said, I think this is a fine step to show the functionality. It's a good set of functionality to show, and I even just used similar in my jam entry. It duplicates the functionality in the one_shot_systems example but the overhead of maintaining this additional example seems very small so approving anyway in the interest of having more than one example showing this functionality.

I added a few rename suggestions because I think it is important to note that the logs refer to the function names specifically, and that they are actually systems.

fn setup_callbacks(mut commands: Commands) {
let trivial_callback = Callback {
system_id: commands.register_system(|| {
println!("This is a trivial callback.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
println!("This is a trivial callback.");
println!("This is the trivial callback system");

let ordinary_system_callback = Callback {
system_id: commands.register_system(|query: Query<&Callback>| {
let n_callbacks = query.iter().len();
println!("This is an ordinary callback. There are currently {n_callbacks} callbacks in the world.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
println!("This is an ordinary callback. There are currently {n_callbacks} callbacks in the world.");
println!("This is the ordinary callback system. There are currently {n_callbacks} callbacks in the world.");

let exclusive_callback = Callback {
system_id: commands.register_system(|world: &mut World| {
let n_entities = world.entities().len();
println!("This is an exclusive callback. There are currently {n_entities} entities in the world.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
println!("This is an exclusive callback. There are currently {n_entities} entities in the world.");
println!("This is the exclusive callback system. There are currently {n_entities} entities in the world.");

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-ECS Entities, components, systems, and events C-Examples An addition or correction to our examples D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Needs-Review Needs reviewer attention (from anyone!) to move forward

Projects

Status: Needs SME Triage

Development

Successfully merging this pull request may close these issues.

4 participants