#Selective despawn?
1 messages · Page 1 of 1 (latest)
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(); } } }
That seems like it would be expensive - iterating on every child in the world just to delete a few.
In the world? no
You can query for children at the same time as the entity
https://github.com/bevyengine/bevy/blob/v0.11.0/examples/ecs/hierarchy.rs#L64C65-L64C65
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 😅
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.
Do you have any flora that aren't children? Do you actually "care" that the flora are children, or could you just query and delete all flora?
Or do you only want to do it for 1 terrain patch at a time
The "dummy" option is legitimately a good solution at this stage imo.
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();
}
}
}
Here is the tracking issue on the Bevy repo https://github.com/bevyengine/bevy/issues/3742
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();
}
});
}