# Bevy Ecs Components

> Use when defining `#[derive(Component)]`, declaring required components with `#[require(...)]`, writing observers with `On<E>` (NOT `Trigger<E>` — renamed in 0.17), choosing between Table and SparseSet storage, or registering `on_add`/`on_remove` hooks in Bevy 0.18.

- **Type:** Skill
- **Install:** `agentstack add skill-chrisgliddon-bevy-skills-bevy-ecs-components`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [chrisgliddon](https://agentstack.voostack.com/s/chrisgliddon)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [chrisgliddon](https://github.com/chrisgliddon)
- **Source:** https://github.com/chrisgliddon/bevy-skills/tree/main/skills/bevy-ecs-components

## Install

```sh
agentstack add skill-chrisgliddon-bevy-skills-bevy-ecs-components
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Bevy 0.18 — ECS Components

## When to use this skill

- Defining a new `Component` for game state.
- Bundling components via `#[require(...)]` (the modern replacement for "bundles").
- Reacting to component lifecycle: spawning, despawning, inserting, removing.
- Observers — reacting to entity-targeted events with `On`.
- Choosing storage: Table (default, fast iteration) vs SparseSet (fast add/remove).

## Canonical pattern

```rust
use bevy::prelude::*;

// 1. Plain components.
#[derive(Component, Default)]
struct Health(f32);

#[derive(Component)]
struct Velocity(Vec3);

// 2. Required components — spawning `Player` auto-spawns the rest.
//    `#[require]` calls each form: `Type` (Default), `Type::ctor(...)`, or
//    `Type = expression`.
#[derive(Component)]
#[require(Health = Health(100.0), Velocity = Velocity(Vec3::ZERO), Transform)]
struct Player;

// 3. Sparse storage for components added/removed every frame (e.g. tags
//    flipped by gameplay). Default Table storage is faster to iterate.
#[derive(Component)]
#[component(storage = "SparseSet")]
struct Stunned;

// 4. An entity-targeted event reacted to by observers.
#[derive(EntityEvent)]
struct Damage {
    entity: Entity, // EntityEvent requires an `entity` field.
    amount: f32,
}

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, spawn_player)
        .add_systems(Update, deal_damage)
        .add_observer(on_damage)
        .run();
}

fn spawn_player(mut commands: Commands) {
    commands.spawn(Player);
}

fn deal_damage(mut commands: Commands, query: Query>) {
    for entity in &query {
        commands.trigger(Damage { entity, amount: 10.0 });
    }
}

// Observer parameter is `On`, not `Trigger` (renamed in 0.17, PR #19596).
fn on_damage(damage: On, mut query: Query) {
    let event = damage.event();
    if let Ok(mut hp) = query.get_mut(event.entity) {
        hp.0 -= event.amount;
    }
}
```

## Gotchas (0.18)

- **`Trigger` is gone.** Observer params are `On` in 0.17+. Methods: `event()`, `event_mut()`, `observer()`, `original_event_target()`, `propagate(bool)`.
- **`EntityEvent::set_target`** requires `use bevy::ecs::entity::SetEntityEventTarget;` — not in the prelude.
- **Storage choice is irrevocable**: it's compiled into the component. SparseSet adds/removes faster but iterates 2–5× slower. Use Table (default) unless profiling proves SparseSet wins.
- **`#[require(T)]` runs `T::default()`**. If `T: !Default`, use `#[require(T = expression)]` or `#[require(T = T::new(...))]`.
- **Required components are non-recursive at the spec layer** but the spawning machinery does insert transitive requires. If you change a required-component graph, run a full scene reload to catch missing inserts.
- **Hooks** (`on_add`, `on_insert`, `on_replace`, `on_remove`) are sharp tools — they run inside `World` mutations, can't take arbitrary `SystemParam`s, and can't despawn the entity they fire on. Use observers when you need flexibility.
- **`Bundle` derive still exists** but most use-cases are better served by `#[require(...)]` on a "marker" component, which keeps the spawn surface ergonomic.

## See also

- `bevy-ecs-queries` — reading components back out.
- `bevy-ecs-systems` — observers are themselves systems.
- `bevy-migration-0-17-to-0-18` — full `Trigger`→`On` and event→message rename map.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [chrisgliddon](https://github.com/chrisgliddon)
- **Source:** [chrisgliddon/bevy-skills](https://github.com/chrisgliddon/bevy-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** yes
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-chrisgliddon-bevy-skills-bevy-ecs-components
- Seller: https://agentstack.voostack.com/s/chrisgliddon
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
