Ralith / hecs

A handy ECS
Apache License 2.0
989 stars 84 forks source link

Deleting all entities #2

Closed JohnDoneth closed 4 years ago

JohnDoneth commented 4 years ago

I had some code like this to delete all entities in my code to reset everything on a button press.

for (entity, _) in world.iter() {
    world.despawn(entity);                                    
}    

But I run into a borrowing issue as world cannot be borrowed as mutable while also being iterated on. Maybe a iter_mut() would be desired on world?

To solve the issue I collect the ID's in a Vec before de-spawning but this seems inefficient for large numbers of entities. Maybe a simple clear method on world would be useful?

let ids = world.iter().map(|(id, _)| id).collect::<Vec<_>>();  

for id in ids {
    world.despawn(id);                                        
}

All in all, just a small issue I ran into with some ideas for possible improvement. I'm loving the crate so far. The simplicity and freedom is wonderful!

Ralith commented 4 years ago

Thanks for the issue! World::clear should be easy; I'll bang that out some time today.

In general, adding/removing entities while iterating or querying has the same problems you'd encounter trying to add/remove elements from a Vec while iterating over it. I'm exploring possibilities, including elaborate interior mutability shenanigans and an analog to Vec::retain, but it's not yet clear what will be feasible.

Ralith commented 4 years ago

this seems inefficient for large numbers of entities.

Just as a side note, I'm not actually sure how true this is: the cost to delete entities is always linear with regard to the number of entities deleted (assuming constant entity size), and so is the amortized cost to create such a vector, and it's at large numbers where that amortization will be smoothest.

Ralith commented 4 years ago

Fixed in v0.1.2.

Friendly-Banana commented 9 months ago

an analog to Vec::retain

Has this or something similar been implemented?

Ralith commented 9 months ago

Nope. To achieve something similar, you should collect a list of entities to remove in a second pass. Feel free to open an issue if that turns out to be too costly for your application.