Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.12: One-Shot Systems #769

Merged
merged 13 commits into from
Oct 27, 2023
63 changes: 63 additions & 0 deletions content/news/2023-10-21-bevy-0.12/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,69 @@ Since our last release a few months ago we've added a _ton_ of new features, bug

<div class="release-feature-authors">authors: @author</div>

## One-Shot Systems

<div class="release-feature-authors">authors: @alice-i-cecile @pascualex, @Trashtalk217, @Zeenobit</div>

Previously, in order to run a system you'd have to add it to a schedule. But while schedules are very useful, not every system needs that sort of overhead. Hence the introduction of one-shot systems.
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved

```rust
#[derive(Resource, Default, Debug)]
struct Counter(u8);

fn increment(mut counter: ResMut<Counter>) {
counter.0 += 1;
println!("{}", counter.0);
}

let mut world = World::new();
Trashtalk217 marked this conversation as resolved.
Show resolved Hide resolved
world.init_resource::<Counter>();
let id = world.register_system(increment);
let _ = world.run_system(id); // prints 1
let _ = world.run_system(id); // prints 2
```

There is now a new way to run systems. First you need to register a system within a world, by calling `world.register_system(your_system)`. The `SystemId` that is returned can then be used to run that system, either within an exclusive system via `world.run_system(id)` or via a command `commands.run_system(id)`.

One-shot systems are very flexible. For example, you can have multiple instances of one system registered at the same time. One-shot systems can be nested (although not recursive), and you can also wrap `SystemId`s into components, making it possible to treat registered systems like entities.
Trashtalk217 marked this conversation as resolved.
Show resolved Hide resolved
Trashtalk217 marked this conversation as resolved.
Show resolved Hide resolved

```rust
use bevy::ecs::system::SystemId;

#[derive(Component)]
struct Callback(SystemId);

// calling all callbacks!
fn call_all(query: Query<&Callback>, mut commands: Commands) {
for callback in query.iter() {
commands.run_system(callback.0);
}
}
```

Currently, there are some drawbacks and limitations. Most importantly, one-shot systems are not ran in parallel, so running slow systems like this can become a bottleneck. Additionally, exclusive systems, systems with `In` arguments, and systems that return values, are not supported.
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved

Registering and running systems is useful and allows for a great degree of control. However, if you __just_ want to run a system - sans registration - there's `RunSystemOnce`, a new trait that does just that.
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved

```rust
use bevy::ecs::system::RunSystemOnce;

#[derive(Resource, Default, Debug)]
struct Counter(u8);

fn increment(mut counter: ResMut<Counter>) {
counter.0 += 1;
println!("{}", counter.0);
}

let mut world = World::new();
world.init_resource::<Counter>();
world.run_system_once(increment); // prints 1
world.run_system_once(increment); // prints 2
```

This is great for unit testing systems and queries, and it's a lot simpler to use. However, there is one caveat. Some systems have state, either in the form of `Local` arguments or change detection (`Changed`, `Added`). This state isn't saved between two `run_system_once` calls, this may create some unexpected behavior. Be careful and you should be fine.
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved

## <a name="what-s-next"></a>What's Next?

We have plenty of work that is pretty much finished and is therefore very likely to land in **Bevy 0.13**:
Expand Down
Loading