```Show HN:一个用 Rust 和 Bevy 编写的自动运行太空经济模拟器```
Show HN: A self-running space economy SIM in Rust and Bevy

原始链接: https://github.com/Kalcode/spaceprojectsim

“太空项目”(The Space Project)是一个基于 Rust 和 Bevy 构建的开源、智能体驱动型经济模拟器。与传统游戏不同,它没有脚本剧情或玩家目标;它更像是一个“上帝模式”的沙盒,让一个完全自主的经济系统自行运转。 该模拟包含约 500 个智能体,包括飞船、设施和派系,它们均使用目标导向动作规划(GOAP)来运行。飞船自行管理燃料、货物和贸易路线,而设施则负责处理生产、损耗以及由实时供需驱动的市场定价。从市场合约、人口迁移到船员士气,每一个方面都是经过模拟的,而非虚构。 在技术层面,该项目利用了 Rust 编写的高性能同步核心“sim_core”,并直接嵌入到基于 Bevy 的 3D 客户端中,以实现零延迟渲染。数据通过 SQLite 持久化存储,使得宇宙能够从中断处精确恢复。 该项目以 MIT 许可证发布,旨在为开发者提供基础。创作者鼓励用户分叉(fork)代码仓库,并在其“扎实的架构基础”上进行构建。对于希望将此模拟扩展为完整游戏或专用引擎的开发者,项目提供了详细的文档和结构化的架构。

开发者“kalcode”发布了一款基于 Rust 语言和 Bevy 游戏引擎构建的自运行太空经济模拟器。该项目在 Claude 的大力协助下完成,包含数百艘拥有独立 GOAP(目标导向行动规划)系统的自主飞船。 该模拟完全非脚本化:飞船自主管理贸易、补给和士气,动态市场则根据供需关系调整价格。目前该系统支持约 500 个代理且性能表现优异,但开发者计划将其扩展至 10 万个。 在技术层面,该项目采用了直接嵌入 Bevy 渲染器中的自定义同步“hecs”ECS(实体组件系统),实现了无需数据编组的无缝集成。虽然目前该项目是一个没有特定获胜条件或目标的沙盒,但开发者已将代码开源,欢迎他人在此基础上进行构建。 该项目在 Hacker News 上引发了关于大语言模型在软件开发中作用的讨论。用户指出,此类项目证明了人工智能辅助如何显著降低了复杂、实验性软件构建的准入门槛,而这些构建在过去往往因过于耗时而难以实现。
相关文章

原文

The Space Project is an agent-driven economic simulation wrapped in a native 3D client. There's no scripted storyline and no player objective — you're an observer (and god-mode admin) watching an economy run itself.

Every ship is an autonomous agent with its own credits, crew, fuel, cargo hold, and a GOAP planner that decides what to do next: chase the highest-margin trade route, accept a delivery contract, seek out a shipyard to retrofit, or dock and let its crew rest before morale collapses. Facilities run production recipes, degrade and self-repair, level up, and get abandoned when they go broke. Factions collect taxes and post subsidies. Populations consume food, produce labor, and pack up and leave when sentiment craters. Markets price everything off a coverage model with shortage urgency multipliers — no fixed prices anywhere.

It started as an Elixir/Phoenix prototype and was rewritten in Rust because the BEAM scheduler struggled on Windows gaming PCs. The engine (sim_core) is pure, synchronous, IO-free Rust; the Bevy client embeds it directly as a library, so the simulation and the renderer share the same ECS world with zero marshalling between them.

Scale today: ~485 live agents (282 ships · 93 facilities · 27 populations · 8 factions · 60 celestial bodies), ticking at p50 ≈ 10–20 ms inside a 125 ms budget. The architecture is built to push toward 100k+.


🌌 A note on where this is going

Nowhere, on its own — and that's kind of the point.

This started as a fun idea: a from-scratch space economy that actually simulates itself instead of faking it. It grew way past what I expected, mostly in late-night sessions pairing with Claude. But I'm not pretending it's a game with a roadmap, and I'm not actively pushing it toward "shippable."

I'm putting it out under MIT because the bones are genuinely good and I'd rather someone do something with it than let it sit in a private repo. So: fork it, gut it, rename it, bolt a game on top of it, rip the economy engine out and use it somewhere else entirely. Build the thing I didn't.

PRs and issues are welcome and I'll look at them, but I can't promise a cadence. If you want to take it somewhere real, see CONTRIBUTING.md — there's a "directions you could take this" section written exactly for you.



System What happens
Ship AI (GOAP) A forward planner scores every goal — trade, deliver, refuel, retrofit, rest, explore — over an abstract world state, then builds a behavior tree to execute the cheapest plan. Ships replan mid-flight when a better option appears.
Economy An order-book market per station prices 13 commodities off a coverage model with shortage-urgency multipliers. Ships move real supply between markets as they trade.
Contracts Six kinds — Delivery, Courier, Passenger, Subsidy, Supply, CrewMission — with a full posted → accepted → paid lifecycle, reputation gating, auto-renewal, and age-escalating payments.
Facilities Run production recipes (smelting, refining, manufacturing, farming, mining), degrade over time, self-repair with tools, level up 1–10, restock from local markets, and get abandoned when chronically broke.
Factions Collect taxes on member facilities, post subsidy contracts for chronic shortages, fund construction of new facilities where demand is unmet, and hold pairwise relations.
Populations Consume food and fuel, produce labor, post food and passenger contracts under stress, and physically migrate to happier systems when sentiment collapses.
Crew Aggregate hunger / fatigue / morale with derived tasks (piloting, engineering, trading, eating, resting), skill progression, wages, and a morale death-spiral guard.
Construction Chronic shortages spawn construction sites that accrete delivered cargo 0 → 1.0, then materialize into a real, persistent facility.
Persistence Everything flushes to SQLite; a sim resumes from the exact tick it left off. A per-universe world_seed keeps the nebula backdrop and landmarks stable across restarts.
Spatial LOD Distant ships tick less often (with rate-scaled state changes) so the frame budget goes where you're looking.

For the deep dive — tick phase ordering, the AI stack, the economic feedback loop, runtime ownership — see docs/ARCHITECTURE.md, which has mermaid diagrams for all of it.


You need a Rust toolchain (stable). Then:

make run
# equivalent to: cargo run -p client_bevy

That boots the Bevy app into the main menu. Start opens a fresh universe (name it, or take the default); Load Game lists every save in the binary's directory. Saves live next to the binary as <universe-name>.db — default sim.db.

Other entry points:

Goal Command
Windowed client (debug) make run
Release build make build → binary at target/release/client_bevy
Headless (no window, for CI / smoke tests) cargo run -p client_bevy -- --headless
Verify (build + test + clippy, strict) make verify
Smoke test (boot headless, print DB counts) scripts/smoke.sh [secs]

One binary, one process. client_bevy is the whole thing — the simulation runs in-process. Headless mode spins up the HTTP/WebSocket server (from the sim_server library crate) for scripted and CI use; there is no separate server binary to run.


Input Action
Left-drag Orbit camera
Right-drag / WASD Pan
Scroll Zoom
Left-click Select ship or facility → opens its details panel
Right-click Context menu (Inspect / Follow / POV / Destroy)
Space Pause / resume
Esc Close top panel · clear selection · open pause menu
P Pause menu
F12 Screenshot
Top bar Toggle panels (Ships, Markets, Factions, Contracts, Events, …), set speed (1× / 2× / 5× / 10×), spawn ships/facilities

Every panel reads the ECS world live — the inspector is effectively a real-time debugger with full component access. Click a ship to see its credits, crew, fuel, current goal, fitting, route memory, and its last few AI commands.


Five crates in one Cargo workspace:

sim_core     Pure simulation logic — hecs ECS, GOAP planner, economy,
             contracts. No async, no IO, no framework. Trivially testable.
sim_db       SQLite persistence (sqlx) — pool, seeder, ECS loader,
             persistence worker, migrations.
sim_server   Library crate — HTTP/WebSocket handlers + engine apply
             helpers. Drives headless mode; embedded by the client.
sim_protocol WebSocket wire types (headless / CI only).
client_bevy  The binary. Bevy 0.18 + egui. Embeds sim_core as a Bevy
             Resource; the renderer queries the hecs world directly.

Three rules keep it honest:

  1. sim_core never imports tokio, sqlx, or axum. Pure logic only, so the whole simulation is reasoned about and unit-tested without async.
  2. hecs is the source of truth during a tick. The tick loop holds exclusive mutable access — no per-agent locks.
  3. Cross-entity effects go through a command buffer (SimCommand). A phase reads world state and writes commands; the next phase applies them. Deterministic, no mid-phase write conflicts.

The full tick phase order, ownership model, and feedback loops are diagrammed in docs/ARCHITECTURE.md.

The original Godot client lives on in history as a parity reference, but it's no longer the front end — the pivot to an embedded Bevy client removed the socket boundary entirely, and every feature now lands in client_bevy.


The Makefile wraps cargo + rustup + codesign + packaging:

make build              # release binary (host target)
make build-mac          # arm64 macOS  (also: build-mac-intel, build-mac-universal)
make build-win          # Windows MSVC (run on a Windows host)
make build-linux        # Linux        (best on a Linux host)

make package-mac        # .app bundle + ad-hoc codesign + Info.plist
make dmg                # macOS .dmg
make package-win        # Windows .zip
make package-linux      # Linux .tar.gz

The workspace version in the root Cargo.toml is the single source of truth — the binary reads it via env!("CARGO_PKG_VERSION") and the Makefile greps the same field for Info.plist and archive names, so packaged builds never drift.


  • Rust (edition 2021) — the whole thing
  • Bevy 0.18 — renderer, ECS-driven main loop, custom WGSL shaders (procedural planets, sun corona, nebulae, starfield)
  • hecs — the simulation's own ECS (separate from Bevy's, deliberately)
  • egui (via bevy_egui) — every inspector panel
  • bevy_hanabi — GPU particle trails and explosions
  • sqlx + SQLite — persistence, bundled so there's no runtime dependency
  • axum + tokio — the headless HTTP/WebSocket harness

Contributions are welcome — see CONTRIBUTING.md for dev setup, the conventions that keep the codebase clean, and a list of concrete directions if you want to take this somewhere real.

The fastest sanity check before any PR:

make verify   # build + ~250 tests + clippy, strict

MIT © 2026 Kalcode (David Clausen). Do whatever you like with it.


Built for fun in Rust & Bevy · By Kalcode & Claude · Made with ❤️ in Illinois

联系我们 contact @ memedata.com