bevy_gearbox 0.5.1

State machine system for the bevy game engine
Documentation

Gearbox is state machine/chart library for the Bevy game engine.

MIT/Apache 2.0 crates.io docs.rs


Design

  • ECS driven. States and transitions are simple entities, react to changes via observers. If you know bevy, you know gearbox.
  • Ergonomic API. Focus on your logic, not in learning a new library.
  • Data driven. Easily manage state machines as assets if you want to.
  • Visual Editor. (optional) Easily build, edit and monitor your state machines.

The goal of gearbox is simple. You should be able to interact with it exactly like you interact with anything else in bevy. Building a state machine is as simple as spawning entities. Querying for entities in a particular state is as simple as adding a With<ExampleComponent> to the end of a query. Reacting to a transition between two states with just On<EnterState> in the observer.

Table of Contents

Getting started

  1. Run cargo add bevy_gearbox
  2. Add GearboxPlugin to your app:
use bevy::prelude::*;
use bevy_gearbox::GearboxPlugin;

fn main() {
    let mut app = App::new();

    app.add_plugins((
        DefaultPlugins,
        GearboxPlugin,
    ));

    app.run();
}

Features

State Machines

commands.spawn((
  Name::new("My State Machine"),
  InitialState(ready),
  StateMachine::new(),
));

States

commands.spawn((
  Name::new("Ready"),
  SubstateOf(my_state_machine),
));
commands.spawn((
  Name::new("NotReady"),
  SubstateOf(my_state_machine),
));

Transitions

#[derive(SimpleTransition, EntityEvent, Clone)]
struct SetNotReady(Entity);
commands.spawn((
  Name::new("Ready -> Not Ready"),
  Source(ready),
  Target(not_ready),
  EventEdge::<SetNotReady>::default(),
));

#[derive(SimpleTransition, EntityEvent, Clone)]
struct SetReady(Entity);
commands.spawn((
  Name::new("Not Ready -> Ready"),
  Source(not_ready),
  Target(ready),
  EventEdge::<SetReady>::default(),
));

You can alternatively skip SimpleTransition and manually implement TransitionEvent, then add #[transition_event] to the type (make sure use bevy_gearbox::prelude::*; is in scope). Either path participates in inventory-based auto-registration: you don't need to call any explicit app registration for transition events.

Triggering transitions

  // "My State Machine" is Ready
  commands.entity(p).trigger(SetNotReady)
  // "My State Machine" is NotReady

Transition-triggered events

commands
    .entity(not_ready)
    .observe(on_enter_not_ready);

fn on_enter_not_ready(
    on: On<EnterState>,
    entities: Query<Entity, With<NotReady>>,
) {
    let Ok(on.state_machine) = entities.get(on.state_machine) else {
      return
    };

    info!("Entered NotReady state!");
}

Statemachine-wide systems

fn count_ready_entities(
    entities: Query<Entity, With<Ready>>,
) {
    info!(ready_count = entities.iter().count());
}

Your first State Machine/Chart

Inside DOCS.md you'll find an in-depth step by step guide into everything you need to build your first State Machine, interact with it through the ECS, and explanations for every how different parts of the API can be used. States and transitions in gearbox are all just entities. Therefore, if you know how use bevy, you know how to use gearbox.

Using the editor (optional)

Installing the editor

  1. Run cargo add bevy_gearbox --features server
  2. Add the server plugin to your app
use bevy::prelude::*;
use bevy_gearbox::GearboxPlugin;

fn main() {
    let mut app = App::new();

    app.add_plugins((
        DefaultPlugins,
        GearboxPlugin,
        bevy_gearbox::server::ServerPlugin::default(),
    ));

    app.run();
}
  1. Run your app cargo run
  2. Launch the editor as a separate process and connect to your running app (see the editor for launch instructions).

Creating an state machine in the editor

Coming soon.

Future goals

  • Improve usability and erogonomics
    Through user experimentation new edgecases and api ergonomic gotchas are bound to be discovered and improved.
  • Integrate with bsn! and Scenes V2
    This will make defining state machines in code much more powerful, and the entity patching will massively improve usability of statemachine scene assets. Fingers crossed for 0.19!
  • Make the editor completely standalone through BRP (Bevy Remote Protocol).

[!WARNING]

POTENTIAL FOOTGUN

When manually building state machines through commands it is important to add the StateMachine component to your root last. This initializes the machine, and if you don't add the StateMachine to the root after you've added all your InitialState components to other state entities, it will not initialize correctly. The proper "layout" for building statechart entities is demonstrated in the repeater example. This is not a problem if you use a scene to spawn your statechart. You can author statechart scenes using the editor. In the future this will be solved by building state machines through bsn.

TLDR: Insert the StateMachine component after the rest of the state machine has been built.

Version Table

Bevy Gearbox
0.18 0.5
0.17 0.4

Contributing

Feel free to open issues or create pull requests, if you encounter any problems.

Ask us on the Bevy Discord server's Gearbox topic in #ecosystem-crates for larger changes or other things if you feel like so!

License

Bevy gearbox is free and open source. All code in this repository is dual-licensed under either:

at your option.