A 2D & 3D node-based game engine, fully deterministic, with scripts that reload in milliseconds.
Written in Rust. A game exports to a single executable.
- Nodes and scenes — a tree of named nodes with scripts attached; scenes are plain TOML.
- Rune scripting — Rust's syntax, async/await, a debugger in the editor.
- Hot reload — save a script while the game runs; live in milliseconds, state intact.
- Determinism — same inputs, same bits, every platform. Record a session and replay it.
- Physics — Rapier in 2D and 3D, stepped on a fixed tick, 60 Hz by default.
- Rendering — wgpu: windowed, offscreen for CI screenshots, or headless.
- Animation — clips, tweens and state machines, 2D bones with skinned polygons, glTF rigs, IK.
- Editor — itself a Balaur project: scene tree, inspector, gizmos, timeline, play-in-editor.
- Networking — HTTP, WebSocket and WebTransport, recorded with the session for replay.
- Platforms — Windows, macOS, Linux; iOS, Android and web cross-compiled in CI on every push.
- Export — one self-contained binary per target: bytecode, scenes and assets fused onto the runtime.
rustup (rust-toolchain.toml pins the version), a C and C++ compiler, and on Linux:
sudo apt-get install -y build-essential pkg-config libasound2-dev libudev-dev \
libx11-dev libxcursor-dev libxrandr-dev libxi-dev libxkbcommon-dev libwayland-devOther platforms and distros: Build from source.
cargo run -p balaur_cli -- new my-game
cargo run -p balaur_cli -- run my-game # dev mode, hot reload on
cargo run -p balaur_cli --features window -- edit my-game # open in the editor
cargo build --release -p balaur_cli # the runtime a game ships on
cargo run -p balaur_cli -- export my-game --runtime target/release/balaurHot reload: run cargo run -p balaur_cli -- run examples/hello --headless and edit
examples/hello/scripts/spinner.rn while it goes.
# scenes/main.toml
[[nodes]]
name = "Ball"
script = { source = "scripts/ball.rn", props = { speed = 3.5 } }
transform = { position = [0.0, 6.0, 0.0] } # from balaur_core
body3d = { kind = "dynamic" } # from balaur_physics
collider3d = { kind = "ball", radius = 0.5 } # from balaur_physics
shape3d = { kind = "ball", radius = 0.5 } # from balaur_render// scripts/ball.rn
pub fn exports() { #{ speed: 2.0 } } // what the inspector may tune
pub fn init(this) { this.angle = 0.0; }
pub fn update(this, dt) { // per frame; fixed_update is per fixed tick
this.angle += dt * this.speed;
this.node.transform.rotation_euler = [0.0, this.angle, 0.0];
}At balaurengine.org: getting started · manual · reference · architecture · roadmap
In this repository:
| File | What it holds |
|---|---|
| ARCHITECTURE.md | every decision |
| docs/ROADMAP.md | what each version holds, and what it does not do yet |
| docs/DETERMINISM.md | writing a game that reproduces; record and replay |
| docs/QUALITY.md | every check CI runs, and what enforces it |
| docs/RELEASING.md | how a nightly and a version are cut, and by what |
| docs/NAMING.md | the naming rules; governs the other docs |
| docs/BENCHMARKS.md | physics and node timings against Godot |
| docs/generated/ | script API, components, assets, crates; written by scripts/gen_docs.py |
| docs/PLAN-*.md | the plan behind each subsystem |
Discord · Discussions · Issues
See CONTRIBUTING.md. Balaur is MIT licensed.
This project uses AI to aid in software development, and accepts AI contributions. What keeps the code sound is what the industry already does: manual testing, automated testing, an architecture written down, spec docs, linting and benchmarking. The quality page says what each one covers.
Every bit of code is tested against this pipeline / process.
There is also a lot of observability and documentation which we use, as the codebase is large and it will keep growing, so having a high level understanding of it is very important, as well as a low level one. For that we have both references from code for nodes/properties, but also documentation and blogposts per features:
If you are interested to see the roadmap of what we plan to build next, and where we are now, be sure to also check: