diff --git a/crates/bevy_ecs/src/component.rs b/crates/bevy_ecs/src/component.rs index 3e4d97c832a7d..74b0bf342c4b3 100644 --- a/crates/bevy_ecs/src/component.rs +++ b/crates/bevy_ecs/src/component.rs @@ -221,7 +221,8 @@ pub struct ComponentHooks { impl ComponentHooks { /// Register a [`ComponentHook`] that will be run when this component is added to an entity. - /// An `on_add` hook will always be followed by `on_insert`. + /// An `on_add` hook will always run before `on_insert` hooks. Spawning an entity counts as + /// adding all of it's components. /// /// Will panic if the component already has an `on_add` hook pub fn on_add(&mut self, hook: ComponentHook) -> &mut Self { @@ -229,9 +230,9 @@ impl ComponentHooks { .expect("Component id: {:?}, already has an on_add hook") } - /// Register a [`ComponentHook`] that will be run when this component is added or set by `.insert` - /// An `on_insert` hook will run even if the entity already has the component unlike `on_add`, - /// `on_insert` also always runs after any `on_add` hooks. + /// Register a [`ComponentHook`] that will be run when this component is added (with `.insert`) + /// or replaced. The hook won't run if the component is already present and is only mutated. + /// An `on_insert` hook always runs after any `on_add` hooks (if the entity didn't already have the component). /// /// Will panic if the component already has an `on_insert` hook pub fn on_insert(&mut self, hook: ComponentHook) -> &mut Self { diff --git a/examples/ecs/component_hooks.rs b/examples/ecs/component_hooks.rs index 79fc96b79c634..c98891bf02f3c 100644 --- a/examples/ecs/component_hooks.rs +++ b/examples/ecs/component_hooks.rs @@ -1,4 +1,17 @@ -//! This examples illustrates the different ways you can employ component lifecycle hooks +//! This example illustrates the different ways you can employ component lifecycle hooks. +//! +//! Whenever possible, prefer using Bevy's change detection or Events for reacting to component changes. +//! Events generally offer better performance and more flexible integration into Bevy's systems. +//! Hooks are useful to enforce correctness but have limitations (only one hook per component, +//! less ergonomic than events). +//! +//! Here are some cases where components hooks might be necessary: +//! +//! - Maintaining indexes: If you need to keep custom data structures (like a spatial index) in +//! sync with the addition/removal of components. +//! +//! - Enforcing structural rules: When you have systems that depend on specific relationships +//! between components (like hierarchies or parent-child links) and need to maintain correctness. use bevy::ecs::component::{ComponentHooks, TableStorage}; use bevy::prelude::*; @@ -35,7 +48,7 @@ fn main() { fn setup(world: &mut World) { // In order to register component hooks the component must: - // - not belong to any created archetypes + // - not be currently in use by any entities in the world // - not already have a hook of that kind registered // This is to prevent overriding hooks defined in plugins and other crates as well as keeping things fast world