# Bevy Admin Guide

This guide is for engine integrators, technical leads, and architects who need to understand how Bevy is built, how to configure and deploy it, and how to operate and extend it at depth. It covers the workspace architecture, the ECS and rendering internals, the full configuration surface, security considerations, build/deployment targets, performance tuning, and known limitations.

> [!NOTE]
> This guide documents the `0.19.0-dev` development line (the `main` branch, crate version `0.19.0-dev`). Bevy releases roughly quarterly with breaking changes and official [migration guides](https://bevy.org/learn/migration-guides/). Pin a specific version in production and treat each upgrade as a planned migration.

---

## 1. Executive Summary

Bevy is a free, open-source, data-driven game engine written in Rust. Its defining characteristics:

| Property | Detail |
|----------|--------|
| **Language** | Rust (edition 2024). MSRV tracks close to the latest stable release. |
| **Architecture** | A modular **Cargo workspace** of ~80 `bevy_*` crates, composed via a plugin system. |
| **Core paradigm** | Entity Component System (ECS) — data-oriented, automatically parallelized. |
| **Rendering** | Built on `wgpu` 29.x (Vulkan / Metal / DX12 / OpenGL / WebGPU / WebGL2). |
| **Math** | `glam` 0.32 (SIMD-accelerated), re-exported via `bevy_math`. |
| **Windowing/Input** | `winit` 0.30; gamepad via `gilrs`; accessibility via `accesskit` 0.24. |
| **Licensing** | Dual MIT OR Apache-2.0. |
| **Targets** | Windows, macOS, Linux, Web (Wasm), Android, iOS, and `no_std`. |

The engine's central design principle is **modularity**: every feature — including rendering itself — is a plugin gated behind a Cargo feature. Applications compose exactly the subset they need, trading functionality against compile time and binary size.

---

## 2. Architecture

### 2.1 The umbrella crate and sub-crates

The `bevy` crate is a thin **facade**. It contains almost no logic of its own; it re-exports the sub-crates as modules and pulls in `bevy_internal`:

```text
bevy (umbrella facade, #![no_std])
  └── pub use bevy_internal::*;
        ├── DefaultPlugins / MinimalPlugins  (default_plugins.rs)
        ├── prelude                          (re-exports each sub-crate's prelude)
        └── pub use bevy_app as app, bevy_ecs as ecs, bevy_render as render, …
```

Each module of `bevy` (except `prelude`) is published independently on crates.io as `bevy_<name>`. Consumers may depend on the umbrella crate for convenience or on individual crates for fine-grained control. `bevy_internal` exists as a separate crate specifically to enable simple dynamic linking (the `bevy_dylib` crate).

### 2.2 Crate map

The workspace is organized under `crates/`. The most significant crates, grouped by concern:

| Layer | Crates |
|-------|--------|
| **Foundation** | `bevy_ecs` (the ECS), `bevy_app` (App/Plugin/schedules), `bevy_reflect` (runtime reflection), `bevy_ptr`, `bevy_platform` (platform abstraction, `no_std` support), `bevy_tasks` (task pools), `bevy_utils`, `bevy_derive`, `bevy_macro_utils`. |
| **Math & time** | `bevy_math` (glam wrapper, curves, primitives, bounding volumes, sampling), `bevy_transform`, `bevy_time`. |
| **Assets & scenes** | `bevy_asset` (async loading, processing, IO backends), `bevy_scene`, `bevy_world_serialization`, `bevy_gltf`, `bevy_image`, `bevy_mesh`, `bevy_shader`, `bevy_material`. |
| **Rendering** | `bevy_render` (render graph, wgpu integration), `bevy_core_pipeline`, `bevy_pbr` (3D PBR), `bevy_sprite` / `bevy_sprite_render` (2D), `bevy_camera`, `bevy_light`, `bevy_anti_alias`, `bevy_post_process`, `bevy_gizmos` / `bevy_gizmos_render`, `bevy_solari` (experimental raytracing). |
| **Windowing & input** | `bevy_window`, `bevy_winit`, `bevy_input`, `bevy_input_focus`, `bevy_gilrs`, `bevy_a11y`, `bevy_clipboard`. |
| **UI** | `bevy_ui`, `bevy_ui_render`, `bevy_ui_widgets`, `bevy_feathers`, `bevy_text`. |
| **App services** | `bevy_audio`, `bevy_animation`, `bevy_state`, `bevy_picking`, `bevy_log`, `bevy_diagnostic`, `bevy_dev_tools`, `bevy_remote`, `bevy_settings`. |

> [!NOTE]
> This separation is deliberate: a headless server can depend on `bevy_app` + `bevy_ecs` + `bevy_time` without ever pulling in `bevy_render` or `wgpu`. The `default_app` and `default_platform` feature collections exist to make this composition ergonomic.

### 2.3 The App and SubApp model

`App` is the top-level container. Internally it holds a **`SubApps`** collection: one "main" `SubApp` plus any number of labeled secondary sub-apps. Each `SubApp` owns its own `World`, schedules, and plugin registry. `App`'s methods operate on the main sub-app unless you explicitly target another via `sub_app_mut(label)`.

The renderer uses this: `bevy_render` runs a separate **Render** sub-app with its own world, and each frame "extracts" data from the main world into the render world. This is what allows pipelined rendering (the render world processing frame *N* while the main world simulates frame *N+1*).

```text
App
 ├── SubApps.main      → World (game state) + schedules
 └── SubApps[Render]   → World (GPU-facing state) + render schedules
                          (added by RenderPlugin; runs on its own thread when
                           PipelinedRenderingPlugin is active)
```

### 2.4 The plugin lifecycle

Plugins are added via `App::add_plugins`. Each plugin progresses through a four-phase lifecycle, tracked by `PluginsState` (`Adding → Ready → Finished → Cleaned`):

| Phase | Method | Purpose |
|-------|--------|---------|
| **build** | `Plugin::build(&self, app)` | Register systems, resources, types. Runs immediately on `add_plugins`. |
| **ready** | `Plugin::ready(&self, app) -> bool` | Poll until asynchronous setup (e.g. GPU init) completes. |
| **finish** | `Plugin::finish(&self, app)` | Final setup once all plugins are ready. |
| **cleanup** | `Plugin::cleanup(&self, app)` | One-time teardown of build-time scaffolding. |

`App::run` drives this: it blocks while any plugin is in `Adding`, ticking the global task pools, then calls `finish` and `cleanup` before invoking the runner. Adding plugins after `finish`/`cleanup` panics. Duplicate plugins (by name) are rejected with `AppError::DuplicatePlugin` unless the plugin opts out of uniqueness via `is_unique() == false`.

### 2.5 DefaultPlugins composition (build order)

`DefaultPlugins` is defined with the `plugin_group!` macro in `crates/bevy_internal/src/default_plugins.rs`. Build order matters and is encoded explicitly. The sequence (each entry gated by its feature flag):

```text
PanicHandlerPlugin → LogPlugin → TaskPoolPlugin → FrameCountPlugin → TimePlugin
→ TransformPlugin → DiagnosticsPlugin → InputPlugin → InputFocusPlugin/InputDispatchPlugin
→ [ScheduleRunnerPlugin if no window] / WindowPlugin + AccessibilityPlugin
→ TerminalCtrlCHandlerPlugin → WebAssetPlugin (if http/https) → AssetPlugin
→ WorldSerializationPlugin → ScenePlugin → WinitPlugin → [DlssInitPlugin]
→ RenderPlugin → ImagePlugin → MeshPlugin → CameraPlugin → LightPlugin
→ PipelinedRenderingPlugin → CorePipelinePlugin → PostProcessPlugin → AntiAliasPlugin
→ SpritePlugin → SpriteRenderPlugin → ClipboardPlugin → TextPlugin → UiPlugin
→ UiRenderPlugin → GltfPlugin → PbrPlugin → AudioPlugin → GilrsPlugin
→ AnimationPlugin → GizmoPlugin → GizmoRenderPlugin → StatesPlugin
→ [CiTestingPlugin] → [RenderDebugOverlayPlugin] → [HotPatchPlugin]
→ UiWidgetsPlugins → DefaultPickingPlugins → IgnoreAmbiguitiesPlugin
```

Ordering constraints worth noting (encoded in source comments):
- `WebAssetPlugin` loads **before** `AssetPlugin` to register HTTP/HTTPS asset sources.
- `WinitPlugin` loads **after** `AssetPlugin` because custom cursors are assets.
- `ImagePlugin` loads **after** `RenderPlugin` so it knows the renderer's supported compressed texture formats.
- `IgnoreAmbiguitiesPlugin` runs last to suppress known, benign system-ordering ambiguities between plugin pairs (e.g. `bevy_ui` vs `bevy_animation` both touching `Transform` in `PostUpdate`).

`MinimalPlugins` is the bare runtime: `TaskPoolPlugin → FrameCountPlugin → TimePlugin → ScheduleRunnerPlugin`.

### 2.6 The schedule pipeline

The `Main` schedule (added by `MainSchedulePlugin`) runs a fixed ordered list of sub-schedules each frame. The full pipeline:

```text
Startup (once):  PreStartup → Startup → PostStartup

Per frame:       First
                 PreUpdate
                 RunFixedMainLoop ──► (FixedFirst → FixedPreUpdate → FixedUpdate
                                        → FixedPostUpdate → FixedLast)  × 0..N
                 Update
                 SpawnScene
                 PostUpdate
                 Last
```

`RunFixedMainLoop` consumes accumulated real time in fixed-size steps (`Time<Fixed>`, default 64 Hz), running the `FixedMain` schedule zero or more times to catch up. This decouples deterministic simulation from variable render frame rate.

### 2.7 ECS internals

`bevy_ecs` is the engine's foundation. Its storage and execution model:

| Concept | Implementation |
|---------|----------------|
| **Entity** | A 32-bit index + generation. Lightweight handle; owns no data. |
| **Component** | Data with `#[derive(Component)]`. Stored either in **Table** (dense, default — cache-friendly for iteration) or **SparseSet** (fast add/remove) storage, selectable via `#[component(storage = "...")]`. |
| **Archetype** | The set of entities sharing an identical component set. The world has one archetype per unique component combination; archetypes are created but never freed. |
| **Table** | The columnar backing store. Multiple archetypes may share a table; they differ only by their sparse-set components. |
| **Query** | A typed view over matching archetypes. Access (`&`/`&mut`) is analyzed for conflicts so non-overlapping systems parallelize. |
| **Edges** | Cached archetype graph transitions for bundle insert/remove, avoiding recomputation when entities change shape. |
| **Schedule executor** | Runs a schedule's systems, parallelizing those with disjoint access. `ApplyDeferred` flushes queued `Commands` at sync points. |

Modules within `bevy_ecs`: `archetype`, `bundle`, `change_detection`, `component`, `entity`, `entity_disabling`, `error`, `event`, `hierarchy`, `message`, `observer`, `query`, `reflect`, `relationship`, `resource`, `schedule`, `spawn`, `storage`, `system`, `world`, `lifecycle`, `name`, `template`, `traversal`.

> [!IMPORTANT]
> Archetypes and tables are **never garbage-collected** — they persist until the `World` is dropped. Code that rapidly creates and destroys entities with many distinct component combinations can grow archetype/table count unbounded. Prefer reusing entities or marker-component toggling over churning archetypes.

### 2.8 Communication models

Bevy offers three distinct mechanisms, each with different delivery semantics:

| Mechanism | Delivery | Use for |
|-----------|----------|---------|
| **Messages** (`Message`, `MessageReader`/`MessageWriter`) | Double-buffered queue, ~2-frame lifetime, polled | Decoupled, batch-processed, many-to-many communication. |
| **Observers** (`Event`/`EntityEvent`, `On<…>`, `add_observer`) | Immediate, synchronous, targeted | Reactive, must-handle, one-off responses. |
| **Lifecycle events** (`Add`/`Insert`/`Remove`/`Despawn`, `RemovedComponents<T>`) | Engine-fired on structural change | Reacting to component/entity lifecycle. |

The change-detection system (`Added<T>`, `Changed<T>`, `Ref<T>`, `DetectChanges`) is a fourth, pull-based reactive primitive built on per-component change ticks.

### 2.9 Rendering architecture

`bevy_render` integrates `wgpu` and defines a **render graph** — a DAG of render nodes (passes). Each frame the renderer:

1. **Extract** — copies needed data from the main world into the render sub-app's world.
2. **Prepare** — uploads GPU resources (buffers, textures, bind groups).
3. **Queue** — assigns entities to render phases.
4. **Sort & Render** — executes the render graph, encoding draw commands.

`bevy_core_pipeline` provides the 2D/3D core passes and tonemapping; `bevy_pbr` adds physically-based 3D shading, clustered lighting, shadows, prepass, deferred shading, SSAO/SSR, atmosphere, and (experimentally) meshlets and Solari raytracing. Shaders are written in WGSL and compiled via `naga`.

---

## 3. System Requirements

| Concern | Requirement |
|---------|-------------|
| **Rust** | Recent stable (MSRV ≈ latest stable). Edition 2024 support required. |
| **GPU** | A backend supported by wgpu 29: Vulkan (Linux/Windows/Android), Metal (macOS/iOS), DirectX 12 (Windows), OpenGL/GLES (fallback), WebGPU/WebGL2 (web). |
| **Linux display** | X11 and/or Wayland (`x11`, `wayland` features; both default). Vulkan loader and drivers installed. |
| **Web** | A browser with WebGL2 or WebGPU; the `wasm32-unknown-unknown` target. |
| **Android** | NDK/SDK; API level 33 in examples; minimum API 26 if `bevy_audio` is used. |
| **Disk/RAM (build)** | A full-engine debug build is heavy; budget several GB of RAM and disk for `target/`. |

---

## 4. Configuration Mastery

Bevy is configured almost entirely in code, by customizing the plugins in `DefaultPlugins` via `.set(...)`, plus a small number of environment variables. There is no central config file.

### 4.1 Window configuration (`WindowPlugin`)

```rust
DefaultPlugins.set(WindowPlugin {
    primary_window: Some(Window {
        title: "My Game".into(),
        resolution: (1920.0, 1080.0).into(),
        present_mode: bevy::window::PresentMode::AutoVsync,
        mode: bevy::window::WindowMode::Windowed,
        resizable: true,
        ..default()
    }),
    // Quit the app when the last window closes:
    exit_condition: bevy::window::ExitCondition::OnAllClosed,
    close_when_requested: true,
    ..default()
})
```

| Field | Controls |
|-------|----------|
| `primary_window` | The initial window's properties (or `None` for headless). |
| `present_mode` | VSync behavior (`AutoVsync`, `AutoNoVsync`, `Fifo`, `Immediate`, `Mailbox`). |
| `mode` | Windowed / borderless / fullscreen. |
| `exit_condition` | When the app should exit relative to window closure. |

### 4.2 Renderer configuration (`RenderPlugin` / `WgpuSettings`)

The renderer is configured through `RenderPlugin { render_creation: WgpuSettings { … } }` (defined in `crates/bevy_render/src/settings.rs`):

```rust
use bevy::render::settings::{Backends, WgpuSettings, RenderCreation, PowerPreference};
use bevy::render::RenderPlugin;

DefaultPlugins.set(RenderPlugin {
    render_creation: RenderCreation::Automatic(WgpuSettings {
        backends: Some(Backends::VULKAN),
        power_preference: PowerPreference::HighPerformance,
        ..default()
    }),
    ..default()
})
```

| Setting | Effect |
|---------|--------|
| `backends` | Restrict to specific wgpu backends (`VULKAN`, `METAL`, `DX12`, `GL`, `BROWSER_WEBGPU`). |
| `power_preference` | `HighPerformance` (discrete GPU) vs `LowPower` (integrated). |
| `features` / `limits` | Required wgpu `Features` and `Limits`. |
| `priority` | Read from the `WGPU_SETTINGS_PRIO` environment variable to bias compatibility vs. functionality. |

> [!TIP]
> wgpu also honors its own environment variables independent of Bevy: `WGPU_BACKEND` forces a backend (`vulkan`, `metal`, `dx12`, `gl`), and `WGPU_POWER_PREF` sets the power preference. These are useful for debugging GPU-selection issues without recompiling.

### 4.3 Logging configuration (`LogPlugin`)

`bevy_log` integrates with the `tracing` ecosystem.

```rust
use bevy::log::LogPlugin;

DefaultPlugins.set(LogPlugin {
    level: bevy::log::Level::INFO,
    filter: "wgpu=error,bevy_render=info,my_game=debug".into(),
    ..default()
})
```

| Field | Controls |
|-------|----------|
| `level` | The minimum log level. |
| `filter` | A per-target `RUST_LOG`-style filter string. |
| `custom_layer` | Hook to add your own `tracing` layers. |

Environment variable: **`TRACE_CHROME`** (read in `crates/bevy_log/src/lib.rs`) — when the `trace_chrome` feature is enabled, controls the output path of the Chrome-format trace file. The `RUST_LOG` environment variable also overrides the filter at runtime.

### 4.4 Asset configuration (`AssetPlugin`)

```rust
use bevy::asset::AssetPlugin;

DefaultPlugins.set(AssetPlugin {
    file_path: "assets".into(),
    watch_for_changes_override: Some(true), // hot-reload (needs file_watcher feature)
    ..default()
})
```

`bevy_asset` supports multiple IO backends (`file`, `embedded`, `web`/HTTP) and an optional asset **processor** (the `asset_processor` feature) that transforms source assets into optimized runtime assets. Web asset sources are enabled by the `http` / `https` features and the `WebAssetPlugin`.

### 4.5 Task pools (`TaskPoolPlugin`)

`TaskPoolPlugin` configures the compute/async-compute/IO thread pools. By default it sizes them based on available CPU cores. Override via `TaskPoolOptions` if you need to reserve cores. The `multi_threaded` feature (default on) enables parallel execution; disabling it forces all engine work onto one thread (useful for Wasm and debugging).

### 4.6 Environment variable summary

| Variable | Read by | Effect |
|----------|---------|--------|
| `RUST_LOG` | `bevy_log` (tracing) | Override log filter at runtime. |
| `TRACE_CHROME` | `bevy_log` (`trace_chrome` feature) | Chrome trace output path. |
| `WGPU_SETTINGS_PRIO` | `bevy_render` settings | Bias wgpu settings priority (compatibility/functionality). |
| `WGPU_BACKEND` | wgpu | Force a specific GPU backend. |
| `WGPU_POWER_PREF` | wgpu | Force power preference. |
| `CARGO_MANIFEST_DIR` | build tooling (`build-easefunction-graphs`) | Build-time asset path resolution. |
| `GITHUB_ACTIONS` | CI example harness | Detect CI for automated example testing. |

---

## 5. Security Analysis

Bevy is a client-side game engine, but several subsystems have real security implications, especially for networked or web-deployed games.

### 5.1 Remote asset loading (HTTP/HTTPS)

The `http` and `https` features enable `WebAssetPlugin`, letting the engine download assets from URLs at runtime.

> [!CAUTION]
> Loading assets over the network executes parsing/decoding code (image, glTF, audio decoders) on **untrusted, attacker-controllable data**. The feature documentation explicitly warns of security implications. Only enable `http`/`https` when you control the asset sources, validate URLs, and prefer `https` over `http`. The `web_asset_cache` feature caches downloads on disk but **never invalidates entries** — a poisoned cache entry persists.

### 5.2 The Bevy Remote Protocol (`bevy_remote`)

`bevy_remote` (the `bevy_remote` feature) exposes the Bevy Remote Protocol — a remote interface for inspecting and mutating a running app's world (used by editors and tooling).

> [!WARNING]
> The remote protocol grants powerful read/write access to the ECS world. Treat any open remote port as an administrative interface: bind it to localhost, never expose it on untrusted networks, and disable the feature entirely in shipped builds unless required.

### 5.3 Deserialization (scenes & reflection)

`bevy_scene` and `bevy_world_serialization` deserialize world state via `bevy_reflect` and `serde`. Loading a scene file instantiates components by reflected type.

> [!IMPORTANT]
> Treat scene/world files as code-equivalent trust boundaries. Only load scene files from trusted sources; a malicious scene can spawn arbitrary registered components and resources. Validate or sandbox any user-supplied scene content.

### 5.4 Native code and `unsafe`

`bevy_ecs` uses `unsafe` deliberately for performance (storage access, parallel execution). `bevy_internal` and the umbrella crate set `#![forbid(unsafe_code)]`, isolating unsafety to the lower-level crates where it is audited (the workspace lints enforce `undocumented_unsafe_blocks = "warn"` and `unsafe_op_in_unsafe_fn = "warn"`). Optional C-backed dependencies (`zstd_c`, `statically-linked-dxc`) introduce native code; the pure-Rust alternatives (`zstd_rust`) are the safe defaults.

### 5.5 Dependency surface

The engine pulls in a large dependency tree (wgpu, winit, glam, image codecs, audio codecs, accesskit). Audit transitive dependencies with `cargo audit` / `cargo deny` in CI, and minimize the feature set to shrink the attack surface. Disabling image/audio format features you don't use removes their decoders entirely.

---

## 6. Build, Packaging & Deployment

### 6.1 Profiles and optimization

```toml
# Optimize dependencies even in dev builds (big runtime win, small build cost):
[profile.dev.package."*"]
opt-level = 3

[profile.dev]
opt-level = 1

# A tuned release profile:
[profile.release]
lto = "thin"
codegen-units = 1
```

| Build | Command |
|-------|---------|
| Dev | `cargo run` |
| Release | `cargo run --release` / `cargo build --release` |
| Fast iteration | `cargo run --features bevy/dynamic_linking` |

> [!CAUTION]
> `dynamic_linking` must be disabled for shipped builds — it requires the Bevy shared library at runtime and is unsupported on Wasm.

### 6.2 Desktop packaging

Ship the executable **and** the `assets/` directory (the `AssetServer` resolves paths relative to it). On Linux, ensure end users have Vulkan drivers. Consider `cargo` bundling tools for `.app`/`.msi`/AppImage packaging.

### 6.3 Web (WebAssembly)

```sh
rustup target add wasm32-unknown-unknown
cargo build --release --target wasm32-unknown-unknown
# then wasm-bindgen / trunk / wasm-server-runner to produce JS glue and serve
```

Pick exactly one web backend:

| Feature | Trade-off |
|---------|-----------|
| `webgl2` | Broadest browser support; no compute shaders; some advanced effects unavailable. |
| `webgpu` | Best performance and full feature set; narrower browser support. **Overrides `webgl2`** when both are set. |

The `web` feature enables browser API access; the `bevy_dylib`-style dynamic linking is unavailable on Wasm. Consider `multi_threaded` carefully — threading support on the web requires cross-origin isolation headers.

### 6.4 Mobile

| Platform | Notes |
|----------|-------|
| **Android** | `android-game-activity` (default, GameActivity) or `android-native-activity` (legacy, for `cargo-apk`). Targets: `aarch64-linux-android`, `armv7-linux-androideabi`. Examples target API 33; `bevy_audio` requires API ≥ 26. `bevy_android` provides the entry glue. |
| **iOS** | An Xcode project (`examples/mobile`) drives a static/cdylib build. `App::run` never returns on iOS (event-loop-owned). |

### 6.5 Headless / server deployment

For dedicated servers and CLI tools, avoid the renderer entirely:

```toml
bevy = { version = "0.18", default-features = false, features = ["default_app"] }
```

```rust
use bevy::prelude::*;
use bevy::app::ScheduleRunnerPlugin;
use std::time::Duration;

App::new()
    .add_plugins(MinimalPlugins.set(
        ScheduleRunnerPlugin::run_loop(Duration::from_secs_f64(1.0 / 60.0))
    ))
    .run();
```

> [!NOTE]
> Without a fixed `run_loop` duration, `ScheduleRunnerPlugin` spins as fast as possible and saturates a CPU core. Always cap the tick rate for servers.

---

## 7. Operations

### 7.1 Diagnostics

`bevy_diagnostic` (always included) collects runtime metrics. Add the built-in plugins to surface them:

```rust
use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin};

app.add_plugins((FrameTimeDiagnosticsPlugin::default(), LogDiagnosticsPlugin::default()));
```

This logs FPS, frame time, and entity counts. The `sysinfo_plugin` feature adds CPU/memory system diagnostics. `EntityCountDiagnosticsPlugin` reports live entity counts — watch this to catch archetype/entity leaks.

### 7.2 Tracing and profiling

| Feature | Tool |
|---------|------|
| `trace` | Base `tracing` spans throughout the engine. |
| `trace_tracy` | Stream spans to the [Tracy](https://github.com/wolfpld/tracy) profiler (frame-by-frame timeline). |
| `trace_tracy_memory` | Tracy with allocation tracking. |
| `trace_chrome` | Emit a Chrome-tracing JSON file (path via `TRACE_CHROME`). |
| `detailed_trace` | Compile-in extra-fine spans (off by default; expensive). |

### 7.3 Developer tools

The `dev` feature collection (`debug` + `bevy_dev_tools` + `file_watcher`) enables hot-reloading and debug overlays. `bevy_dev_tools` includes CI testing harnesses, a frame-time graph, schedule inspection (`schedule_data` feature), and (with `bevy_pbr`) a render debug overlay. The `bevy_debug_stepping` feature enables stepping execution through systems one at a time.

> [!WARNING]
> The `dev` collection and `bevy_dev_tools` are for development only. Never enable them in shipped builds — they add overhead and expose internals.

### 7.4 Logs

Logging is driven by `tracing`. Control verbosity with the `LogPlugin` filter or the `RUST_LOG` environment variable. A common production filter quiets noisy subsystems: `RUST_LOG="wgpu=error,naga=error,info"`.

---

## 8. Performance Tuning

| Lever | Guidance |
|-------|----------|
| **Feature trimming** | Disable unused Cargo features (image/audio formats, experimental renderers). Fewer features = faster builds, smaller binaries, less surface. |
| **`multi_threaded`** | Keep enabled for parallel system execution on native targets. |
| **Change detection** | Use `Changed<T>`/`Added<T>` to avoid recomputing unchanged data every frame. |
| **Query design** | Prefer `Table` storage (default) for components iterated in hot loops; `SparseSet` for components frequently added/removed. |
| **Fixed timestep** | Put heavy simulation in `FixedUpdate` so it runs at a bounded rate, not per render frame. |
| **System ordering** | Avoid over-constraining order; unordered systems parallelize. Only add `.before`/`.after`/`.chain` where correctness requires. |
| **Batching / instancing** | The PBR/sprite renderers automatically batch and GPU-instance compatible draws. Stress examples (`bistro`, `caldera_hotel`) expose flags to toggle frustum/occlusion culling, automatic batching, and indirect drawing for profiling. |
| **Pipelined rendering** | `PipelinedRenderingPlugin` (auto-enabled on native + `multi_threaded`) overlaps the render world with the next simulation frame. |
| **Texture compression** | Use compressed formats (KTX2 with `zstd_rust`/`zstd_c`, Basis Universal, BCn) to cut VRAM and load time. |
| **Benchmarks** | The `benches` crate uses Criterion; run with `cargo bench -p benches --bench <ecs|render|…>` and compare baselines with `--save-baseline`/`--baseline`. |

> [!TIP]
> The renderer auto-batches and auto-instances by default. If profiling a draw-call bottleneck, the large-scene examples document `--no-automatic-batching`, `--no-frustum-culling`, `--no-indirect-drawing`, and `--no-cpu-culling` flags to isolate which stage is the cost.

---

## 9. Repository Structure (for contributors)

```text
bevy/
├── crates/              ~80 bevy_* sub-crates (the engine)
├── src/lib.rs           Umbrella facade: pub use bevy_internal::*
├── examples/            Hundreds of runnable examples, grouped by topic
│   ├── 2d/ 3d/ ui/ ecs/ shader/ animation/ audio/ …
│   ├── mobile/          Android (GameActivity & native) + iOS projects
│   ├── stress_tests/    Performance stress scenarios
│   └── large_scenes/    bistro, caldera_hotel, bevy_city (real-world scenes)
├── benches/             Criterion benchmarks (ecs, render, reflect, …)
├── tools/               Internal tooling
│   ├── ci/              The CI command runner (cargo run -p ci)
│   ├── build-templated-pages/   Generates docs/cargo_features.md
│   ├── build-wasm-example/      Wasm example builder
│   └── example-showcase/        Example catalog/screenshot generator
├── tests/ tests-integration/    Integration tests
├── errors/              Error code documentation
├── docs/                cargo_features.md and other docs
└── assets/              Example assets (not shipped in published crates)
```

### 9.1 Contributing workflow

- **CI** is orchestrated by `tools/ci` (`cargo run -p ci`), which runs formatting, clippy, tests, doc checks, and compile-fail tests on stable Rust.
- **Compile-fail tests** (`crates/*/compile_fail`) assert exact compiler errors for macros; they live outside the workspace to avoid breaking `crater`.
- **Workspace lints** are strict: `undocumented_unsafe_blocks`, `unsafe_op_in_unsafe_fn`, `allow_attributes_without_reason`, `std_instead_of_core` (for `no_std` crates), and many clippy pedantic lints are set to `warn`.
- **`no_std` support**: foundation crates compile without `std`. CI checks against `x86_64-unknown-none`, `wasm32v1-none`, and `thumbv6m-none-eabi` targets using `libm` + `critical-section`.
- **RFCs** for large architectural changes go to the [bevyengine/rfcs](https://github.com/bevyengine/rfcs) repository.

---

## 10. Quick Reference

### 10.1 App builder methods

| Method | Purpose |
|--------|---------|
| `App::new()` / `App::empty()` | Full / minimal app scaffolding. |
| `add_plugins(p)` | Install plugin(s) or group(s). |
| `add_systems(schedule, sys)` | Add systems to a schedule. |
| `configure_sets(schedule, sets)` | Order/gate system sets. |
| `insert_resource(v)` / `init_resource::<T>()` | Provide resources. |
| `add_message::<M>()` | Enable a message type. |
| `add_observer(obs)` | Register a global observer. |
| `register_type::<T>()` | Register a reflected type. |
| `register_required_components::<T, R>()` | Declare `R` required by `T`. |
| `set_runner(f)` | Replace the main-loop runner. |
| `run()` | Build and start the app. |

### 10.2 Schedules

| Group | Schedules |
|-------|-----------|
| Startup | `PreStartup`, `Startup`, `PostStartup` |
| Main (per frame) | `First`, `PreUpdate`, `RunFixedMainLoop`, `Update`, `SpawnScene`, `PostUpdate`, `Last` |
| Fixed (in `RunFixedMainLoop`) | `FixedFirst`, `FixedPreUpdate`, `FixedUpdate`, `FixedPostUpdate`, `FixedLast` |

### 10.3 Feature profiles & collections

| Tier | Examples |
|------|----------|
| Profiles | `default`, `2d`, `3d`, `ui` |
| Collections | `dev`, `audio`, `audio-all-formats`, `scene`, `picking`, `default_app`, `default_platform`, `common_api`, `default_no_std` |
| Render backends | `webgl2`, `webgpu`, `raw_vulkan_init` |
| Platform | `x11`, `wayland`, `android-game-activity`, `std`, `libm`, `critical-section` |

### 10.4 Key environment variables

`RUST_LOG`, `TRACE_CHROME`, `WGPU_SETTINGS_PRIO`, `WGPU_BACKEND`, `WGPU_POWER_PREF`.

---

## 11. Known Limitations & Improvement Areas

Drawn from the engine's own warnings, feature documentation, and the community issue tracker at the documented commit.

### 11.1 Engine-level caveats

- **Pre-1.0, breaking releases** — the API changes roughly quarterly; the README explicitly warns important features are still missing and documentation is sparse.
- **Archetypes/tables never freed** — high-churn entity shapes can grow memory unbounded (§2.7).
- **MSRV churn** — tracks latest stable Rust closely; older toolchains are unsupported.
- **WebGL2 limits** — no compute shaders; several rendering features are WebGPU-only.
- **`web_asset_cache` never invalidates** — cached downloads persist indefinitely (§5.1).
- **Experimental subsystems** — `bevy_solari` (raytracing), `meshlet`, `dlss`, `experimental_pbr_pcss`, and ghost UI nodes are explicitly experimental and may change or carry GPU-compatibility risk.

### 11.2 Community-reported issues (at commit `457b918`)

| Issue | Status | Summary |
|-------|--------|---------|
| #24525 | Open | `bevy_dev_tools` didn't receive a release candidate. |
| #24521 | Open | Docs for `bevy::asset::io::android` are not generated. |
| #19625 | Open | objc2 framework panics on a macOS 26 developer beta. |
| #24508 | Open | `MouseScrollUnit` handling is inconsistent — input-scaling caveat for scroll. |
| #24517 | Open | `AtmosphereEnvironmentMapLight` / `GeneratedEnvironmentMapLight` are very slow — a performance watch item. |
| #24510 | Open | Re-enable the `std_instead_of_core` lint (no_std hygiene). |
| #24483 | Open | `bevy_extract` tracking (planned extract-stage refactor). |
| #24356 | Closed | `FeathersNumberInput` failed when spawned in `Update` — fixed. |
| #24346 | Closed | "CommandQueue has un-applied commands" on delayed-command exit — fixed. |

> [!NOTE]
> Issue counts are a point-in-time snapshot. The live tracker is the authoritative source: <https://github.com/bevyengine/bevy/issues>.

### 11.3 Recommendations for integrators

- **Pin and plan migrations.** Lock to a published version and schedule upgrades around the quarterly release + migration guide cadence.
- **Trim features aggressively.** Start from `default-features = false` and a profile (`2d`/`3d`/`default_app`), adding only what you need.
- **Gate dev/remote features out of release builds.** Ensure `bevy_dev_tools`, `dev`, and `bevy_remote` are absent from shipped binaries.
- **Treat asset/scene/network inputs as untrusted.** Validate sources; prefer pure-Rust decoders; keep `http` off unless required.
- **Add diagnostics early.** Wire up `FrameTimeDiagnosticsPlugin` and entity-count diagnostics from day one to catch leaks and regressions.

---

_Generated June 2026 from bevyengine/bevy at 457b918. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
