#Dynamically removing observers

1 messages · Page 1 of 1 (latest)

waxen ridge
#

Is it possible to dynamically remove observers without storing their entities? I'd like to clear all the observers watching some entity.

mellow pier
#

How about defining marker components like this and then removing them all at once?

struct ExamplePlugin;

impl Plugin for ExamplePlugin {
    fn build(&self, app: &mut App) {
        app
            .add_systems(Startup, observe)
            .add_systems(Update, remove_observers.run_if(on_timer(Duration::from_secs(1))));
    }
}

#[derive(Component)]
struct GoodBye;

fn observe(mut commands: Commands) {
    let entity = commands.spawn_empty().id();
    let mut observer = Observer::new(|_trigger: Trigger<OnAdd>| {});
    observer.watch_entity(entity);
    commands.spawn((
        GoodBye,
        observer,
    ));
}

fn remove_observers(
    mut commands: Commands,
    observers: Query<Entity, With<GoodBye>>,
){
    for entity in observers.iter(){
        commands.entity(entity).despawn();
    }
}
waxen ridge
#

thingy is the DX is way worse when spawning observres like that, so I wanted to avoid doing that

#

although I gues I could make it an extension that wraps this

mellow pier
#

Hmm, I'm not sure I've fully grasped the intent of your question.
Do you mean you want to avoid creating an observer directly and instead create via commands.entity(<entity>).observe(<system>), and remove it?

waxen ridge
#

yep

#

observe an entity, then later stop watching it (on some state change)

mellow pier
#

The only other approach I can think of is to iterate over all observers and filter them using the ObserverDescriptor.
However, this approach probably won’t meet your expectations.

fn remove_observers(
    mut commands: Commands,
    observers: Query<(Entity, &Observer)>,
) {
    for (entity, observer) in observers.iter() {
        if observer.descriptor().entities().iter().any(|entity| {
            todo!("filtering")
        }) {
            commands.entity(entity).despawn();
        }
    }
}
waxen ridge
#

I think that code would despawn the observed entity due to the shadowing 🙂

#

but yep, that could work, at least to test it out

waxen ridge
#

@mellow pier
thx, that's fine for now 🥰

#
pub fn remove_observers_for_watched_entity(
    commands: &mut Commands,
    observer_q: Query<(Entity, &Observer)>,
    entity: Entity,
) {
    for (observer_e, _) in observer_q
        .iter()
        .filter(|(_, observer)| observer.descriptor().entities().contains(&entity))
    {
        or_continue!(commands.get_entity(observer_e)).try_despawn();
    }
}