bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
36.16k stars 3.57k forks source link

Queries do not seem to update transforms unless the query is for a tuple of multiple components. #11047

Closed a2aaron closed 10 months ago

a2aaron commented 10 months ago

Bevy version 0.12.1

Relevant system information

If your bug is rendering-related, copy the adapter info that appears when you run Bevy.

AdapterInfo { name: "Apple M1 Pro", vendor: 0, device: 0, device_type: IntegratedGpu, driver: "", driver_info: "", backend: Metal }

SystemInfo { os: "MacOS 12.6 ", kernel: "21.6.0", cpu: "Apple M1 Pro", core_count: "10", memory: "32.0 GiB" }

What you did

I attempted to create a simple toy app to display a moving circle. I based this toy app on the move_sprite.rs example, but ran into a problem with getting the circle to animate.

use bevy::{prelude::*, sprite::MaterialMesh2dBundle};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        // Change "move_circle" to "move_circle_2" to observe the bug.
        .add_systems(Update, move_circle)
        .run();
}

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<ColorMaterial>>,
) {
    commands.spawn(Camera2dBundle::default());
    commands.spawn((
        MaterialMesh2dBundle {
            mesh: meshes.add(shape::Circle::new(50.0).into()).into(),
            material: materials.add(ColorMaterial::from(Color::PURPLE)),
            transform: Transform::from_xyz(100.0, 0.0, 0.0),
            ..Default::default()
        },
        Empty,
    ));
}

#[derive(Component)]
struct Empty;

// This system correctly animates the circle
fn move_circle(mut sprite_position: Query<(&Empty, &mut Transform)>) {
    for (_, mut transform) in &mut sprite_position {
        transform.translation.x = (transform.translation.x + 1.0) % 100.0;
    }
}

// The same system as above, but only querying for the Transform. This system does not animate the circle at all
fn move_circle_2(mut sprite_position: Query<&mut Transform>) {
    for mut transform in &mut sprite_position {
        transform.translation.x = (transform.translation.x + 1.0) % 100.0;
    }
}

What went wrong

When using move_circle as the Update system, the circle animates correctly. However, when I instead use move_circle_2 as the Update system, the circle no longer animates at all. This seems incorrect, since the Transform still gets updated (adding debug print statements inside the for-loop does show that the query returns the Transform and the Transform has it's values set as expected). However, the circle ends up not being animated anyways.

The only difference between the two systems is that the first one queries for (&Empty, &mut Transform) while the second queries just for &mut Transform

a2aaron commented 10 months ago

Nevermind, I just remembered that cameras also have a Transform, so the second system would transform the camera along with the shape...