ADR-004: bevy_ecs Adoption (Standalone)
Status: Accepted Date: 2026-01-15
Context
SiliconGhetto needs an Entity-Component-System framework for organizing game state. The ECS pattern provides excellent cache performance, parallelism potential, and a clean separation between data (components) and behavior (systems). We want a mature, well-tested ECS library rather than building our own.
Options Considered
1. bevy_ecs standalone (chosen)
- Extracted from the Bevy engine, usable as a standalone crate
- Archetype-based storage with excellent query performance
- Mature, heavily tested, active development
- Rich query system with filters, change detection, and resources
- Large community producing learning resources
2. hecs
- Lightweight archetype ECS
- Minimal API surface
- Less feature-rich (no built-in resources, events, or change detection)
- Smaller community
3. specs
- Established Rust ECS
- Bitset-based storage (different performance characteristics)
- Less active development in recent years
- API is more verbose
4. Custom ECS
- Full control over design
- Significant implementation effort
- Unproven correctness and performance
- Maintenance burden
Decision
Use bevy_ecs as a standalone dependency. We import only the ECS crate, not the full Bevy engine. This gives us Bevy’s world-class ECS implementation without coupling to Bevy’s renderer, windowing, or plugin systems.
Consequences
Positive
- Battle-tested ECS with excellent performance characteristics
- Rich query system:
Query<(&Transform, &Sprite), With<Visible>> - Built-in resources, events, and change detection
- Components derive
Component— minimal boilerplate - Path to system scheduling and parallelism as the engine grows
Negative
- bevy_ecs is a non-trivial dependency (~200KB compiled)
- API changes with Bevy releases (0.x semver)
- Some features (system scheduling) are more complex than we need initially
- Tight coupling to Bevy’s component model
Mitigations
- Pin to a specific bevy_ecs version (0.18) and update deliberately
- Use only the features we need — World, Query, Component, Resource
- Wrap ECS access in our own
sg_sceneAPI for a stable internal interface
Usage Pattern
use bevy_ecs::prelude::*;
#[derive(Component)]
struct Position { x: f32, y: f32 }
#[derive(Component)]
struct Velocity { x: f32, y: f32 }
fn movement_system(mut query: Query<(&mut Position, &Velocity)>) {
for (mut pos, vel) in &mut query {
pos.x += vel.x;
pos.y += vel.y;
}
}