Skip to content

Commit

Permalink
Improve components hooks docs (#12295)
Browse files Browse the repository at this point in the history
# Objective

- Closes #12256 

## Solution

- Improved component hooks docs.
- Improved component hooks example docs.

---------

Co-authored-by: James Liu <[email protected]>
Co-authored-by: Alice Cecile <[email protected]>
  • Loading branch information
3 people authored Mar 4, 2024
1 parent 4673fb3 commit 15db61a
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 6 deletions.
9 changes: 5 additions & 4 deletions crates/bevy_ecs/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,17 +221,18 @@ 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 {
self.try_on_add(hook)
.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 {
Expand Down
17 changes: 15 additions & 2 deletions examples/ecs/component_hooks.rs
Original file line number Diff line number Diff line change
@@ -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::*;
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 15db61a

Please sign in to comment.