<div align="center">
# 🦀 Crabby Engine
**A fast 2D and 3D game engine for simulating millions of things.**
Colonies, crowds, armies, ecosystems, factories: games where the number of
simulated things is the point. Written in Rust, with a C++ API at close to
the same speed.
[](https://github.com/bozoslav/crabbyengine/actions/workflows/ci.yml)
[](https://bozoslav.github.io/crabbyengine/)
[](https://bozoslav.github.io/crabbyengine/api/crabbyengine/)
[](#license)

[**▶ Play in your browser**](https://bozoslav.github.io/crabbyengine/play/battle/) ·
[**Guide**](https://bozoslav.github.io/crabbyengine/) ·
[**Examples**](#examples) ·
[**Benchmarks**](https://bozoslav.github.io/crabbyengine/performance.html) ·
[**C and C++**](https://bozoslav.github.io/crabbyengine/c-cpp.html) ·
[**AI agents**](https://bozoslav.github.io/crabbyengine/agents.html)
<img src="book/src/images/battle.jpg" alt="The battle demo: two armies of 10,000 units each march around rocks and mud on flow fields and meet in two fronts" width="100%">
<sub>The battle demo: 20,000 units on flow fields, 0.8 ms of simulation per frame.
It runs a million units headless at 19 ms per tick.</sub>
</div>
## Why Crabby Engine
- **Built for scale.** Its own archetype ECS runs queries on every CPU
core: 10 million agents tick in 8.7 ms headless, and a million small
sprites render at 120 FPS. A fixed-rate simulation clock runs separately from
drawing, so the simulation can pause, step one tick, run at up to 64×, or
run with no window at all.
- **A full 3D renderer on the same ECS.** Behind the `3d` feature: PBR
materials and custom WGSL shaders, glTF meshes, a physically based sky
with fog, cascaded sun shadows, clustered point and spot lights,
heightfield terrain streamed around the camera, compute passes, screen
effects, and 3D physics with a walking character and raycast-wheel
vehicles. Unity scenes, prefabs and colliders import through
`crabby_unity`.
- **Fast iteration.** Images, sounds, fonts and JSON data files reload while
the game runs, and so does game code (`dx serve --hot-patch`), with all
game state kept. Press `` ` `` for an in-game inspector that lists every
entity and edits components live.
- **Agents can play it.** An [MCP](https://modelcontextprotocol.io) server
lets AI coding agents launch your game, inspect and edit entities, step
the simulation, watch events, read logs, and take screenshots.
- **Runs in the browser.** The same game builds for the web (WebGPU, with
WebGL2 as a fallback): [play the battle demo](https://bozoslav.github.io/crabbyengine/play/battle/).
- **Rust or C++.** A header-only C++17 wrapper over a C API covers nearly the
whole engine. The C++ version of the battle demo is within 6% of the Rust
speed.
- **Simple, replaceable parts.** One obvious way to do each thing. Everything
the engine does on its own (drawing sprites, camera controls, attachments)
is a plain system you can remove or replace.
## A first look
<table>
<tr><th>Rust</th><th>C++</th></tr>
<tr>
<td>
```rust
use crabbyengine::*;
struct Vel(Vec2);
fn movement(ctx: &mut Ctx) {
let dt = ctx.dt();
ctx.world
.query::<(&mut Transform2D, &Vel)>()
.par_for_each(|(t, v)| t.position += v.0 * dt);
}
fn main() {
Game::new("Crabs", 1280, 720)
.sim_system(movement)
.run(|ctx| {
let crab = ctx.load_texture("crab.png");
for i in 0..100_000 {
let pos = vec2((i % 1280) as f32, (i / 1280) as f32 * 8.0);
ctx.world.spawn((
Transform2D::at(pos),
Sprite::new(crab),
Vel(vec2(20.0, 0.0)),
));
}
});
}
```
</td>
<td>
```cpp
#include "crabby.hpp"
using namespace crabby;
struct Vel { vec2 v; };
void movement(ctx& ctx) {
const float dt = ctx.dt();
ctx.world().each_par([dt](transform2d& t, const Vel& v) {
t.position += v.v * dt;
});
}
int main() {
game("Crabs", 1280, 720)
.sim_system(movement)
.run([](ctx& ctx) {
auto crab = ctx.load_texture("crab.png");
for (int i = 0; i < 100000; ++i) {
vec2 pos{float(i % 1280), float(i / 1280) * 8};
ctx.world().spawn(transform_at(pos), sprite_of(crab),
Vel{{20, 0}});
}
});
}
```
</td>
</tr>
</table>
## Getting started
You need a recent stable Rust (`rustup update stable`). Add the engine to a
new project:
```sh
cargo new my_game && cd my_game
cargo add crabbyengine
```
Then follow [Getting started](https://bozoslav.github.io/crabbyengine/getting-started.html)
in the guide. For C++, build `crabby_ffi` and include `include/crabby.hpp`:
see [C and C++](https://bozoslav.github.io/crabbyengine/c-cpp.html).
## Examples
```sh
git clone https://github.com/bozoslav/crabbyengine && cd crabbyengine
cargo run --release --example battle # two armies, 20k units; click to rally
cargo run --release --example terrain --features 3d # hills, grass, a lake
```
| [`battle`](examples/battle.rs) | The flagship demo: two armies on flow fields, spatial grids, fights and reinforcements. `HEADLESS=1 UNITS=1000000` for a million units |
| [`flow`](examples/flow.rs) | Flow-field pathfinding: 20,000 agents find their way around walls and mud to a goal you click |
| [`ants`](examples/ants.rs) | Ant colonies with pheromone trails, foraging and growth, up to millions of ants |
| [`boids`](examples/boids.rs) | Flocking with spatial queries on all cores |
| [`hotpatch`](examples/hotpatch.rs) | Edit a system while the game runs |
| [`ui`](examples/ui.rs) | Camera, shapes, text, panels and buttons |
| [`tiles`](examples/tiles.rs) | A big tilemap (up to 16 million tiles) with animated sprites |
| [`headless`](examples/headless.rs) | A million agents with no window or GPU |
| [`examples/cpp`](examples/cpp) | Boids and the battle in C++ |
<table>
<tr>
<td width="33%"><img src="book/src/images/flow.jpg" alt="Flow fields: 20,000 yellow agents stream along branching paths around rocks toward one goal"></td>
<td width="33%"><img src="book/src/images/ants.jpg" alt="Ant colony: ants spread out from a nest, laying green pheromone trails to food"></td>
<td width="33%"><img src="book/src/images/inspector.jpg" alt="The inspector panel next to the battle, listing entities, resources and system timings"></td>
</tr>
<tr>
<td align="center"><sub>Flow fields, 20k agents</sub></td>
<td align="center"><sub>Ant colonies</sub></td>
<td align="center"><sub>The inspector</sub></td>
</tr>
</table>
### In 3D
The 3D examples need `--features 3d`, the physics ones
`--features physics3d`, added to any command below. This is the same ECS
and the same systems, not a second engine: 3D models sit next to sprites
if you like, and simulate with the same fixed-rate clock.
| [`3d`](examples/3d.rs) | Meshes and glTF models, a sun, thousands of instanced cubes; `BENCH_SECONDS=8` runs the Unity-comparison benchmark |
| [`terrain`](examples/terrain.rs) | Heightfield terrain in 5 × 5 tiles with four LODs, grass, dirt and rock blended by a weight map, a lake and an underwater effect |
| [`shaders`](examples/shaders.rs) | Custom material shaders in WGSL: lake waves, grass in the wind, a procedural pattern, post-processing |
| [`lights`](examples/lights.rs) | 1,000 clustered point and spot lights (`LIGHTS` to change the count) |
| [`streaming`](examples/streaming.rs) | An endless landscape built on worker threads and streamed in around the camera |
| [`compute`](examples/compute.rs) | A compute pass running a wave simulation on the GPU: rain bending a pond's normals |
| [`physics3d`](examples/physics3d.rs) | Walk on hilly terrain in first person, climb steps, push crates |
| [`vehicle`](examples/vehicle.rs) | Drive a raycast-wheel car over terrain |
| [`scene_viewer`](examples/scene_viewer.rs) | Fly around a scene file, like the Unity importer writes |
<table>
<tr>
<td width="33%"><img src="book/src/images/terrain.jpg" alt="Heightfield terrain: hills of grass, dirt and rock around a lake, drawn coarser in the distance"></td>
<td width="33%"><img src="book/src/images/shaders.jpg" alt="Custom material shaders: grass swaying in the wind beside a lake with its own wave shader"></td>
<td width="33%"><img src="book/src/images/lights.jpg" alt="A dark scene lit by one thousand colored point and spot lights"></td>
</tr>
<tr>
<td align="center"><sub>Terrain tiles with LOD, streamed by distance</sub></td>
<td align="center"><sub>Custom WGSL shaders, hot reloaded</sub></td>
<td align="center"><sub>1,000 clustered lights</sub></td>
</tr>
</table>
## Performance
Native release builds on a MacBook Pro (M4 Max); web builds run on one thread and are slower. Every number has a command to
reproduce it on the [benchmarks page](https://bozoslav.github.io/crabbyengine/performance.html).
| ECS iteration, 1M entities: Crabby / bevy_ecs / hecs | **0.15** / 0.36 / 1.77 ms |
| Headless simulation, 10M agents | 8.7 ms per tick |
| Battle, 1M units: flow fields, spatial grids, fighting | 18.9 ms per tick |
| Ant colonies, 1M ants | 15 ms per tick |
| Boids, 1M, with neighbor search | ~33 ms per tick |
| 100k events sent and read | 0.42 ms per tick |
| 1M moving sprites (1.6 px), rendered | 120 FPS (display cap) |
| 3D, 100k spinning cubes with shadows: Crabby / Unity 6 ([details](https://bozoslav.github.io/crabbyengine/performance.html#3d-crabby-vs-unity)) | **402** / 54 FPS (7.5x) |
| Memory per entity, 1M agents | 76 bytes |
### 3D: Crabby vs Unity 6
The same scene in both: N spinning, tinted cubes, 12 PBR spheres, a sun
with soft shadows and 4x MSAA. Unity is built the normal way (one
GameObject with an `Update()` script per cube, URP). Fullscreen, native
resolution, vsync off, M4 Max, median of three 10-second runs.
| 1,000 | 728 FPS | **750 FPS** | 0.65 / **0.17** ms |
| 10,000 | 398 FPS | **724 FPS** (1.8x) | 2.51 / **0.43** ms |
| 100,000 | 54 FPS | **402 FPS (7.5x)** | 18.7 / **2.48** ms |
What's not equal, and how to rerun both sides, is on the
[benchmarks page](https://bozoslav.github.io/crabbyengine/performance.html#3d-crabby-vs-unity).
## Features
**Simulation**
- Own archetype ECS: queries, `par_for_each` on all cores, commands, resources, runtime-registered components
- Fixed-rate sim clock: pause, step, 1–64× speed, systems that run only every N ticks
- Spatial grids (radius, rectangle, nearest), flow-field pathfinding, events between systems, attachments
- Lockstep multiplayer for 2–8 players over UDP or Steam (lobbies, invites, relays): only inputs cross the network (~50 bytes/tick), desyncs reported by component
- 2D physics (rapier, `physics` feature): rigid bodies and colliders as components, collision events, rays, impulses; optionally bit-identical across platforms
- Deterministic: seeded randomness per (seed, tick, system, entity), even in parallel; save and load the whole world
- Headless runs for tests, servers and batch simulations; the build without a window has about half as many crates
- Web builds: WebGPU or WebGL2, assets fetched before setup, sound through WebAudio ([guide](https://bozoslav.github.io/crabbyengine/web.html))
**3D** (`3d` feature, `physics3d` adds physics)
- PBR meshes: instanced per mesh and culled to the view, from glTF, your
own triangles or Unity scenes; custom `vertex`/`surface` shaders in WGSL
(hot reloaded), with render targets (mirrors), compute passes and screen
effects; depth prepass, HDR, 2 or 4× MSAA, bloom and tone mapping
- A physically based sky with a day-night cycle, height and distance fog;
cascaded sun shadows; clustered point and spot lights; per-mesh shadow
switches (`ShadowMesh`, `set_mesh_shadows`)
- Heightfield terrain: tiles with four LODs, up to 8 ground layers blended
by a weight map, triplanar on cliffs, streamed in on worker threads
(`CellStreamer`) and freed behind the camera
- 3D physics (rapier3d, `physics3d`): rigid bodies, heightfield colliders,
ray and shape queries, a kinematic walking character, raycast-wheel
vehicles
- Scenes and prefabs: `ctx.load_scene`, `ctx.spawn_prefab`; the
`crabby_unity` importer brings Unity projects (scenes, prefabs,
materials, colliders) into Crabby scene files
**Drawing, sound, input**
- wgpu sprite batcher: instancing, z-order, tint, rotation, scale
- 2D camera (pan, zoom, follow), text, shapes, simple UI (panels, buttons, labels)
- Sprite sheets, animation, tilemaps; sound through kira
- Keyboard, mouse and gamepads (Xbox, PlayStation, Switch, hot-plugged),
named action maps all of them feed; CPU and GPU timings per frame
**Iteration and tools**
- Hot reload of images, sounds, fonts and JSON data files; hot-patching of game code
- Runtime inspector (egui): entities, live component editing, level
editing (drag, scene save and load, prefabs) while paused, resources,
system timings, sim controls
- Reflection: components and resources as JSON, used by the inspector, save files and agents
- Control endpoint and MCP server for AI agents and external tools
- Per-system timings always on; frame stats, per-pass GPU timings, a
performance HUD, Perfetto traces and an offscreen benchmark mode
(`CRABBY_BENCH`); puffin profiler behind a feature
**C and C++**
- C API (`crabby_ffi`) with a generated header, plus a header-only C++17 wrapper (`include/crabby.hpp`)
- C++ components are plain structs found by type; `world.each([](transform2d& t, const Vel& v) {...})` loops inline over component arrays, as fast as Rust, with no per-entity calls across the language boundary
## Working with AI agents
The repository ships an MCP server, so coding agents (Claude Code, Cursor,
Codex, ...) can run the game and look inside it instead of guessing from
source code:
```sh
cargo install crabby_mcp
claude mcp add crabby -- crabby-mcp
```
An agent can then launch a game headless, run 600 ticks, ask "how many
units per team, and how hurt are they?", change a component, and take a
screenshot. See [Working with AI agents](https://bozoslav.github.io/crabbyengine/agents.html).
## Status
Crabby Engine is tested on Windows, macOS and Linux on every change, and
the guide is kept in sync with `main`. From 1.0 the API follows semver:
[STABILITY.md](STABILITY.md) says what is promised (the API, the minimum
Rust version, the C ABI, saved worlds, determinism) and what isn't. See
the [changelog](CHANGELOG.md) for what changed.
## Contributing
Contributions are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md) to get
started. The full rules for humans and coding agents are in
[AGENTS.md](AGENTS.md). Please follow the [code of conduct](CODE_OF_CONDUCT.md).
Report security issues privately, as described in [SECURITY.md](SECURITY.md).
## License
Crabby Engine is created by Leon Mamić (see [NOTICE](NOTICE)). It's licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
at your option.
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.