Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query.removed() is always empty #941

Closed
lukors opened this issue Nov 28, 2020 · 5 comments
Closed

Query.removed() is always empty #941

lukors opened this issue Nov 28, 2020 · 5 comments

Comments

@lukors
Copy link
Contributor

lukors commented Nov 28, 2020

Bevy version
rev 72b2fc9

Operating system & version
Windows 10

What you did
Here is a simple example:

use bevy::prelude::*;

struct MyComponentOne;
struct MyComponentTwo;

fn main() {
    App::build()
        .add_plugins(DefaultPlugins)
        .add_system(spawn.system())
        .add_system(remove.system())
        .add_system(print.system())
        .run();
}

fn spawn(
    commands: &mut Commands,
) {
    commands.spawn((MyComponentOne, MyComponentTwo));
}

fn remove(
    commands: &mut Commands,
    query: Query<Entity>,
) {
    for entity in query.iter() {
        commands.remove_one::<MyComponentOne>(entity);
    }
}

fn print(
    query: Query<Entity>,
) {
    for thing in query.removed::<MyComponentOne>() {
        println!("{:?}", thing);
    }
}

What you expected to happen
To see something printed in the console.

What actually happened
Nothing is printed.

Additional information
It's been suggested in the Discord that perhaps Query.removed() is not meant to be used in this way. If so, how is it meant to be used? We should add this information to the documentation of the function.

If it's not meant to be used in this way, is there some best practice yet for how to check for removed components in Bevy? This would be great knowledge to have in the community as it's been very hard to find any information about this.

@cart
Copy link
Member

cart commented Nov 28, 2020

Your example above doesn't work for a couple of reasons:

  1. all three systems were added to the same (default) stage, so they all run in parallel. the "remove" system should always run after "spawn" and the "print" system must run after components are actually removed.
  2. remove_one and spawn are Commands, which are always applied after a stage has finished executing. this means that even if the parallel execution order happens to line up, query.removed::() will return nothing because the remove commands haven't been applied yet.

You can fix it by adding your systems to different stages to force execution order. This prints the expected output:

.add_system_to_stage(stage::PRE_UPDATE, spawn.system())
.add_system_to_stage(stage::UPDATE, remove.system())
.add_system_to_stage(stage::POST_UPDATE, print.system())

(note that you should create your own stages after stage::UPDATE for scenarios like this instead of adding them to PRE/POST update)

@cart
Copy link
Member

cart commented Nov 28, 2020

I do want to give optional, more fine grained control over execution order within a stage, but for now using stages is the recommended approach.

I'm closing this issue as it isn't a bug / the system is behaving as intended.

@cart cart closed this as completed Nov 28, 2020
@ndarilek
Copy link
Contributor

ndarilek commented Nov 28, 2020 via email

@cart
Copy link
Member

cart commented Nov 28, 2020

Yeah an example illustrating this issue is a good idea. Feel free to pr it 😄

@lukors
Copy link
Contributor Author

lukors commented Nov 28, 2020

I'll get on a PR for the example.

And then the documentation, unless someone else takes it on first.

Just announcing here to avoid any duplicated work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants