Component-based state machine plugin for Bevy

Overview

seldom_state

Crates.io MIT/Apache 2.0 Crates.io

seldom_state is a component-based state machine plugin for Bevy. It's useful for AI, player state, and other entities that occupy various states. It allows for greater reusability of state logic between entities, compared to managing mutually-exclusive components directly in your systems.

A state is a bundle (usually with one component) attached to an entity that defines its current behavior, such as (Jumping,) or (Stunned,). A trigger is a type that checks information about entities in the world, such as NearPosition or HealthBelowThreshold. A transition links two states: one to transition from, and one to transition to; once a given trigger has occurred. A state machine is a component attached to an entity that keeps track of that entity's transitions, and automatically changes the entity's state according to those transitions.

State machines are created like so:

commands.spawn()
    // ... (other inserts)
    .insert(
        StateMachine::new((my_initial_state,))
            .trans::<(MyState1,)>(my_trigger_1, (my_state_4,))
            .trans::<(MyState2,)>(my_trigger_2, (my_state_5,))
            .trans::<(MyState3,)>(my_trigger_3, (my_state_6,))
            .insert_on_enter::<(MyState7,)>(my_bundle)
            .remove_on_exit::<(MyState7,), MyBundle>()
            // etc.
    );

For more complete examples, see the examples directory. The chase.rs example is written like a guide, so it is good for learning. If you need help, feel free to ping me on the Bevy Discord server (@Seldom)! If any of the docs need improvement, feel free to submit an issue or pr!

Features

  • State machine component with user-defined states and triggers
  • Three built-in triggers
    • AlwaysTrigger: always triggers
    • NotTrigger: contains a trigger, which it negates
    • DoneTrigger: triggers when the user adds the Done component to the entity
  • Automatically insert bundles upon entering a state, and remove others upon exiting (StateMachine::insert_on_enter and StateMachine::remove_on_exit)

Future Work

  • Dataflow from triggers to states using state builders (I will probably implement this myself)
  • Transitions that can transition from any state (I will probably implement this myself)
  • Automatically insert bundle on transition
  • Built-in timer trigger (I might implement this, and definitely want it)
  • More flexible, composable triggers, such as And(A, B) (I might implement this, and definitely want it)
  • Multiple state machines on an entity (I probably won't implement this, and am still debating whether I want it)

Comparison with big-brain

Finite state machine is an old and well-worn pattern in game AI, so its strengths and limitations are known. It is good for entities that:

  1. Do not have a large number of interconnected states, since the number of transitions can grow quadratically. Then it becomes easy to forget to add a transition, causing difficult bugs.
  2. Act rigidly, like the enemies in Spelunky, who act according to clear triggers such as got-jumped-on-by-player and waited-for-5-seconds, and unlike the dwarves in Dwarf Fortress, who weigh their options of what to do before taking an action.

seldom_state is a finite state machine implementation, so it may not be suitable for all types of game AI. If you need a solution that works with more complex states and transitions, then you may want to implement a behavior tree (I had little luck turning existing implementations into a Bevy plugin without forking them). If you need a solution that operates on fuzzy logic, and do not need to define which transitions should be allowed, then I recommend big-brain. If you need fuzzy logic and defined transitions, you may want to implement a fuzzy state machine. Otherwise, this crate will likely work for you!

seldom_state is not just an AI crate, though. So, you may want to use big-brain for your enemies' AI, and seldom_state to manage state for your player, and control enemies' animation, or something.

Usage

Add to your Cargo.toml

# Replace * with your desired version

[dependencies]
seldom_state = "*"

See the chase.rs example for futher usage.

Compatibility

Bevy seldom_state
0.8 0.1 - 0.2

License

seldom_state is dual-licensed under MIT and Apache 2.0 at your option.

Contributing

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

You might also like...
This plugin provides an interface for storing unencrypted values on the application cache folder.

Tauri Plugin Store This plugin provides an interface for storing unencrypted values on the application cache folder. Architecture This repo shape migh

This is a Pomodoro Clock implemented as a Zellij plugin.

Pomodoro Clock This is a Pomodoro Clock implemented as a Zellij plugin. It shows a Pomodoro time as well as current date time. Prerequisite You must i

A VtubeStudio plugin that allows iFacialMocap to stream data to the app, enabling full apple ARkit facial tracking to be used for 2D Vtuber models.

facelink_rs A VtubeStudio plugin that allows iFacialMocap to stream data to the app, enabling full apple ARkit facial tracking to be used for 2D Vtube

A rollup plugin that compile Rust code into WebAssembly modules

rollup-plugin-rust tl;dr -- see examples This is a rollup plugin that loads Rust code so it can be interop with Javascript base project. Currently, th

A plugin for Devzat that can tell the time at various timezones.

Devzat Time Teller On Devzat, people come from all around the time. It is sometime hard to know what time it is for other peoples. This plugin let you

[SWC plugin] workaround for jest

[SWC plugin] workaround for jest This is a SWC plugin to handle jest compatibility issues. This SWC plugin should be used with @swc/jest. usage instal

Replicated storage docker plugin.

Fractal Docker Plugin This plugin handles the creation and deletion of docker volumes backed by copy-on-write filesystems (BTRFS currently), regular s

Bioinformatics plugin for nushell.

Nushell bio A bioinformatics plugin for nushell. The aim initially is to create a bunch of parsers for all of the common bioinformatics file formats a

SWC plugin for transform Vue3-jsx syntax

swc-plugin-transform-vue3-jsx 💡 SWC plugin for faster conversion vue3-jsx. Installation npm npm install swc-plugin-transform-vue3-jsx -D yarn yarn ad

Owner
Seldom
I make video games
Seldom
Director is a simple, versatile, ergonomic state machine in Rust-lang.

Director Director is a simple, versatile, ergonomic state machine in Rust-lang. (no-std) | Examples | Docs | Latest Note | director = "0.5.0" Why? Bec

Doha Lee 2 Sep 19, 2022
A Polkadot SDK-like state machine written from scratch in Rust.

Rust State Machine This repository is the basis for a tutorial teaching how to develop a simple state machine using Rust. Goal The goal of this tutori

Shawn Tabrizi 10 Nov 29, 2023
Plugin to request a relaunch when uploading a Skyline plugin through cargo skyline

restart-plugin A skyline plugin for allowing cargo-skyline (or other tools) to restart your game without you having to touch your controller. Install

null 1 Nov 21, 2021
A Wasm component optimizer (mostly a wrapper around wasm-opt)

component-opt An optimizer for Wasm Components Current Status This project currently only offers one optimization and does not allow it to be configur

Robin Brown 6 Mar 4, 2024
Rust experiments involving Haskell-esque do notation, state, failure and Nom parsers!

Introduction As a long time Haskell developer recently delving into Rust, something I've really missed is monads and do notation. One thing monadic do

Kerfuffle 23 Feb 28, 2022
💫 Small microservice to handle state changes of Kubernetes pods and post them to Instatus or Statuspages

?? Kanata Small microservice to handle state changes of Kubernetes pods and post to Instatus ?? Why? I don't really want to implement and repeat code

Noel ʕ •ᴥ•ʔ 4 Mar 4, 2022
A lightning fast state management module for Yew.

yewv A lightning fast state management module for Yew built with performance and simplicity as a first priority. Who is this for? If you wish to use a

null 7 Dec 8, 2022
Detect if code is running inside a virtual machine (x86 and x86-64 only).

inside-vm Detect if code is running inside a virtual machine. Only works on x86 and x86-64. How does it work Measure average cpu cycles when calling c

null 34 Oct 3, 2022
Code for connecting an RP2040 to a Bosch BNO055 IMU and having the realtime orientation data be sent to the host machine via serial USB

Code for connecting an RP2040 (via Raspberry Pi Pico) to a Bosch BNO055 IMU (via an Adafruit breakout board) and having the realtime orientation data be sent to the host machine via serial USB.

Gerald Nash 3 Nov 4, 2022
A simple interpreter for the mathematical random-access machine

Random-access machine runner A simple Rust RAM program runner. Lexer/Parser Program executor Code formatter Web Compiled to WASM to run in the browser

Marcin Wojnarowski 5 Jan 14, 2023