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_scene API 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;
    }
}

References