//! This example illustrates how to react to component and resource changes.12use bevy::prelude::*;3use rand::Rng;45fn main() {6App::new()7.add_plugins(DefaultPlugins)8.add_systems(Startup, setup)9.add_systems(10Update,11(12change_component,13change_component_2,14change_resource,15change_detection,16),17)18.run();19}2021#[derive(Component, PartialEq, Debug)]22struct MyComponent(f32);2324#[derive(Resource, PartialEq, Debug)]25struct MyResource(f32);2627fn setup(mut commands: Commands) {28// Note the first change detection log correctly points to this line because the component is29// added. Although commands are deferred, they are able to track the original calling location.30commands.spawn(MyComponent(0.0));31commands.insert_resource(MyResource(0.0));32}3334fn change_component(time: Res<Time>, mut query: Query<(Entity, &mut MyComponent)>) {35for (entity, mut component) in &mut query {36if rand::rng().random_bool(0.1) {37let new_component = MyComponent(time.elapsed_secs().round());38info!("New value: {new_component:?} {entity}");39// Change detection occurs on mutable dereference, and does not consider whether or not40// a value is actually equal. To avoid triggering change detection when nothing has41// actually changed, you can use the `set_if_neq` method on any component or resource42// that implements PartialEq.43component.set_if_neq(new_component);44}45}46}4748/// This is a duplicate of the `change_component` system, added to show that change tracking can49/// help you find *where* your component is being changed, when there are multiple possible50/// locations.51fn change_component_2(time: Res<Time>, mut query: Query<(Entity, &mut MyComponent)>) {52for (entity, mut component) in &mut query {53if rand::rng().random_bool(0.1) {54let new_component = MyComponent(time.elapsed_secs().round());55info!("New value: {new_component:?} {entity}");56component.set_if_neq(new_component);57}58}59}6061/// Change detection concepts for components apply similarly to resources.62fn change_resource(time: Res<Time>, mut my_resource: ResMut<MyResource>) {63if rand::rng().random_bool(0.1) {64let new_resource = MyResource(time.elapsed_secs().round());65info!("New value: {new_resource:?}");66my_resource.set_if_neq(new_resource);67}68}6970/// Query filters like [`Changed<T>`] and [`Added<T>`] ensure only entities matching these filters71/// will be returned by the query.72///73/// Using the [`Ref<T>`] system param allows you to access change detection information, but does74/// not filter the query.75fn change_detection(76changed_components: Query<Ref<MyComponent>, Changed<MyComponent>>,77my_resource: Res<MyResource>,78) {79for component in &changed_components {80// By default, you can only tell that a component was changed.81//82// This is useful, but what if you have multiple systems modifying the same component, how83// will you know which system is causing the component to change?84warn!(85"Change detected!\n\t-> value: {:?}\n\t-> added: {}\n\t-> changed: {}\n\t-> changed by: {}",86component,87component.is_added(),88component.is_changed(),89// If you enable the `track_location` feature, you can unlock the `changed_by()`90// method. It returns the file and line number that the component or resource was91// changed in. It's not recommended for released games, but great for debugging!92component.changed_by()93);94}9596if my_resource.is_changed() {97warn!(98"Change detected!\n\t-> value: {:?}\n\t-> added: {}\n\t-> changed: {}\n\t-> changed by: {}",99my_resource,100my_resource.is_added(),101my_resource.is_changed(),102my_resource.changed_by() // Like components, requires `track_location` feature.103);104}105}106107108