pyri_state
pyri_state is a bevy_state alternative offering flexible change detection & scheduling.
;
app.add_systems;
See the examples and documentation for more information.
Comparison to bevy_state
State pattern-matching
In pyri_state, state pattern-matching is directly supported:
// Save progress when entering level 4, 7, or 10.
app.add_systems;
There are a few ways to do this using bevy_state:
- Add a system for every possible matching state.
for x in
- Use a custom substate.
app.add_systems;
;
- Use a custom schedule.
app.add_systems;
app.add_systems;
;
Note that option 1 is prohibitively expensive when the pattern has too many matches, like Level(x) if x % 2 == 0.
Options 2 and 3 add a confusing layer of indirection and boilerplate, hiding the actual pattern-matching in
the SubStates implementation or the run_my_schedule exclusive system.
Even worse, option 2 is subtly broken: if you transition from state A to B where both states match the pattern,
bevy_state will silently discard the substate's transition because it's a same-state transition.
State refreshing
In pyri_state, state refreshing is supported out-of-the-box:
// Restart game on R press.
app.add_systems;
// Schedule a system for when any level restarts.
app.add_systems;
// Refreshing a state will also reuse its exit, trans, and enter hooks.
app.add_systems;
// You can explicitly check whether the state has changed, if you want.
app.add_systems;
The equivalent in bevy_state requires building your own custom schedules
(e.g. OnReExit, OnReTransition, OnReEnter, OnChangeExit, OnChangeTransition, OnChangeEnter, etc.)
and hooking them into the state transition internals,
as in this example.
This is a seriously discouraging amount of boilerplate for something that should be a basic feature.
And more
- Custom storage: In
pyri_state, the next state can be stored in any custom data structure. For example, you can store the next state in a stack to implement a "back button" feature for a menu state as easily asMenu::pop. This is currently impossible inbevy_state, which only supportsenum NextState. - Direct mutation: In
pyri_state, systems can mutate the next state value directly (e.g.level.0 += 1). Inbevy_state, you have to clone the current state, mutate it, and set that as the next state. As a consequence, if multiple systems mutate the same state on the same frame, they'll completely overwrite each other, leading to rare, confusing bugs that direct mutation would often circumvent entirely. - Local states: In
pyri_state, states can be components. This is currently impossible inbevy_state, which only supports global states.
Bevy version compatibility
bevy version |
pyri_state version |
|---|---|
| 0.18 | 0.6 |
| 0.17 | 0.5 |
| 0.16 | 0.4 |
| 0.15 | 0.3 |
| 0.14 | 0.2 |
| 0.13 | 0.1 |
License
This crate is available under either of MIT or Apache-2.0 at your choice.