Search code examples
rustbevy

iter_mut() doesn't run whenever I try to add status in Bevy 0.8.1


I added collision between the player and the ground, and I want to add a jumping mechanic into my game with on_ground. However, whenever I try to add status, it just stops iterating entirely.

fn collision_detection(
    ground: Query<&Transform, (With<Ground>, Without<Player>)>,
    mut player: Query<(&mut Transform, &mut PlayerStatus), With<Player>>,
) {
    let player_size = Vec2::new(PLAYER_SIZE_X, PLAYER_SIZE_Y);
    let ground_size = Vec2::new(GROUND_SIZE_X, GROUND_SIZE_Y);

    for ground in ground.iter() {
        for (mut player, mut status) in player.iter_mut() {
            if collide(
                player.translation,
                player_size,
                ground.translation,
                ground_size,
            )
            .is_some()
            {
                status.on_ground = true;
                println!("ON GROUND")
            } else {
                status.on_ground = false;
            }
            if status.on_ground {
                player.translation.y += GRAVITY;
            }
        }
    }
}

For some reason, this part wouldn't run

for (mut player, mut status) in player.iter_mut() {
            if collide(
                player.translation,
                player_size,
                ground.translation,
                ground_size,
            )
            .is_some()
            {
                status.on_ground = true;
                println!("ON GROUND")
            } else {
                status.on_ground = false;
            }
            if status.on_ground {
                player.translation.y += GRAVITY;
            }
        }

It works if I only do this though:

for mut player in player.iter_mut() {
    if collide(
        player.translation,
        player_size,
        ground.translation,
        ground_size,
    )
    .is_some()
    {
        player.translation.y += GRAVITY;
    }
}

Solution

  • If you have only one player, you can use get_single_mut() instead of iter_mut() on the query.

    It returns a result, so you can check in your function easily whether the player entity had been found at all. And if not send yourself some nice debugging message :)

    if let Ok((mut player, mut status)) = player.get_single_mut() {
        // do your collision check
    } else {
        // player not found in the query
    }
    

    https://docs.rs/bevy/latest/bevy/prelude/struct.Query.html#method.get_single_mut

    Edit: Looking at your comment above: if you have an already spawn entity you can always add new components to it using .insert_bundle or .insert.