elevator-core
From a 5-story office to a space elevator — same engine, same API.
An engine-agnostic, tick-based elevator simulation library for Rust.
Plug it into Bevy, Unity, your own renderer, or run headless.
Guide · API Reference · Examples
▶ Try the live playground — race two dispatch strategies on the same traffic, side-by-side in your browser.
What it does
You define stops at arbitrary positions on a 1-D axis, spawn riders, and call step(). The engine handles dispatch, trapezoidal motion, doors, boarding, and metrics — your code just reacts to events.
use *;
use ElevatorConfig;
The README snippet above prints Tick N: rider … delivered! once the rider arrives. To run a slightly more elaborate example, with three riders and aggregate metrics:
# All riders arrived at tick 335!
# Delivered: 3
# Avg wait: 5.0 ticks
# Avg ride: 328.0 ticks
Use cases
| Scenario | How |
|---|---|
| Office building with 5 floors | Stops at 0, 4, 8, 12, 16 |
| Skyscraper with sky lobbies | Multi-group dispatch, express zones |
| Space elevator | Stops at 0 and 1,000 — same engine |
| Player-controlled car | ServiceMode::Manual + velocity commands |
| Custom AI dispatch | Implement DispatchStrategy::rank() |
| VIP passengers, cargo, robots | Extension storage — attach any data |
Features
- Arbitrary stop positions: not limited to uniform floors; model buildings, towers, orbital tethers
- Pluggable dispatch: built-in SCAN, LOOK, Nearest Car, ETD, Destination; or bring your own via the
DispatchStrategytrait - Rider lifecycle: Waiting → Boarding → Riding → Exiting → Arrived/Abandoned, with hooks at each transition
- Extension storage: attach arbitrary typed data to riders, elevators, and stops
- O(1) population queries: who's waiting, riding, or resident at any stop, instantly
- Deterministic replay: same inputs produce the same simulation every time
- Snapshot save/load: serialize full simulation state for replays or networking
- Metrics: wait times, ride times, throughput, delivered counts, all built-in
Hosts
elevator-core itself is headless. Pick the host that matches your engine:
| Host | Crate | Use it for |
|---|---|---|
| Bevy | elevator-bevy |
2-D Rust game with HUD, mesh, and keyboard controls |
| Browser | elevator-wasm |
wasm-bindgen surface; powers the live playground |
| Unity / .NET / GameMaker | elevator-ffi |
C ABI wrapper for native consumers |
| Godot | elevator-gdext |
gdext extension |
| Terminal | elevator-tui |
tick-by-tick debugger and headless smoke runner |
Anything not on the list? Drive Simulation::step() yourself — the API is engine-agnostic.
Non-goals
This is a simulation library, not a game. It deliberately does not include:
- Rendering or UI — see the host crates above, or roll your own
- AI passengers or traffic generation — use the optional
trafficfeature flag, or drive arrivals yourself - Building layout or 2-D floor plans — the sim is 1-D by design
Visual demo
The workspace includes a Bevy frontend that renders the simulation in 2-D:
TUI debugger
For tick-by-tick debugging or headless smoke runs, the workspace also ships elevator-tui — a terminal viewer with pause/step controls, event log, dispatch summary, and snapshot save/load on a hotkey. See the TUI Debugger guide.
Feature flags
| Flag | Default | Adds |
|---|---|---|
traffic |
yes | Poisson arrivals, daily traffic patterns. Pulls in rand. |
energy |
no | Per-elevator energy/regen modeling. |
Workspace
elevator-core is the simulation library. The hosts above wrap it. A handful of supporting crates (elevator-contract, elevator-layout-derive, elevator-layout-runtime, elevator-layout-codegen) are build-time / test-only and exist to keep the host bindings in sync. See CLAUDE.md for the full layout.
See also
- Stability and Versioning — what counts as a breaking change and what doesn't.
elevator-corechangelog — release-please-managed.- AI disclosure — how AI tools are used in this repo.
License
MIT or Apache 2.0, at your option.