#Selective despawn?

1 messages · Page 1 of 1 (latest)

sharp surge
#

I want to despawn children of an entity, but only the ones that have a specific component. What's the best way to do this?

fierce mica
#

I would imagine something like rs // replace entity with however you specify fn remove_t<T>(entity: Entity, mut commands: Commands, children: Query<&Children>, query: Query<Entity, With<T>>) { for child in children.get(entity).unwrap().iter() { if query.contains(child) { commands.entity(child).despawn(); } } }

sharp surge
fierce mica
#

In the world? no

sturdy fjord
#
fn remove_t<T: Component>(
    entity: Entity,
    mut commands: Commands,
    query: Query<&Children, With<T>>,
) {
    if let Ok(children) = query.get(entity) {
        for child in children.iter() {
            commands.entity(*child).despawn_recursive();
        }
    }
}
#

Oh I might have misunderstood sorry, when you say "the ones that have a specific component" do you mean parents with the component, or children with the component?

#

I have the former and I think s33n has the latter

#

For more optimal performance on the latter you'll need relationships (not implemented in bevy yet)

#

I don't think it's possible to describe that in a single query at the moment

#

If possible you could put some kind of marker component on the parent, which will mean you're not getting literally every entity with children 😅

sharp surge
#

Let me give a more concrete example

#

I have a world made up of terrain patches. Each patch has children: ground mesh, water mesh, and flora (trees and shrubs). When editing, I want to delete all the flora children - that is, all children that have the Flora component - and replace them with newly generated entities based on the updated positions.

#

Now, I can do this by making a dummy entity for flora and then making the trees the children of that - in other words, making them the grandchildren of the terrain patch instead of the children. But I was wondering whether this extra level of indirection is necessary or not.

sturdy fjord
#

Or do you only want to do it for 1 terrain patch at a time

sturdy fjord
#

Another option is to maintain a component on the parent that keeps track of the Entity ids of all the children of different types, but that sounds like a lot of boilerplate to achieve what your grouping-children-by-type with a dummy entity does.

#

The ideal way would be if bevy supported relationship queries, so you could directly query for what you're describing.

I made up this query syntax, but hopefully it illustrates what you've described.

fn delete_flora(
    mut commands: Commands,
    terrain_id: Entity,
    query: Query<Children<Entity, With<Flora>>, With<Terrain>>,
) {
    if let Ok(flora) = query.get(terrain_id) {
        for flora_id in flora.iter() {
            commands.entity(*flora_id).despawn_recursive();
        }
    }
}
#

Another option would be to put the terrain id on the flora as a component, then you can iterate through flora and check it, but again it's suboptimal.

fn delete_flora(
    mut commands: Commands,
    target: Entity,
    query: Query<(Entity, &TerrainID), With<Flora>>,
) {
    query.for_each(|(id, terrain_id)| {
        if terrain_id == target {
            commands.entity(id).despawn_recursive();
        }
    });
}