Latest commit 209b722

查询

相关的官方文档:[ecs_guide]


Query 能访问实体的组件。

#![allow(unused)]
fn main() {
fn check_zero_health(
    // 访问带有 `Health` 和 `Transform` 组件的实体
    // 获取对 `Health` 的只读访问和对 `Transform` 的可变访问
    // 可选组件:如果 `Player` 存在,获取只读访问
    mut query: Query<(&Health, &mut Transform, Option<&Player>)>,
) {
    // 获取所有匹配的实体
    for (health, mut transform, player) in query.iter_mut() {
        eprintln!("Entity at {} has {} HP.", transform.translation, health.hp);

        // 读取 `Health`,修改 `Transform`
        if health.hp <= 0.0 {
            transform.translate = Vec3::ZERO;
        }

        // 判断 `Player` 是否存在
        if let Some(player) = player {
            // 做一些事
        }
    }
}
}

获取与特定实体关联的组件:

#![allow(unused)]
fn main() {
if let Ok((health, mut transform)) = query.get_mut(entity) {
    // 做一些事
} else {
    // 实体中没有 query 要求的组件
}

}

获取Query访问的实体的 ID:

#![allow(unused)]
fn main() {
// 把 `Entity` 添加到 `Query` 来获取 Entity 的 ID
fn query_entites(q: Query<(Entity, /* ... */)>) {
    for (e, /* ... */) in q.iter() {
        // `e` 就是我们正在访问的 Entity 的 ID
    }
}
}

如果明确地知道 Query 只匹配一个实体,可以用 singlesingle_mut(返回 Result),而不是 iteriter_mut

#![allow(unused)]
fn main() {
fn query_player(mut q: Query<(&Player, &mut Transform)>) {
    let (player, mut transform) = q.single_mut().expect("单机游戏只有一个玩家!");

    // 做一些事
}
}

(如果 single 查询到多个实体,会 panic!)

Query 查询的是实体的组件,如果某个实体从 Bundle 创建,那么在 Query 中不要查询 Bundle,要查询 Bundle 中的组件。记住:查询“组件”。

查询过滤器

过滤器的作用是缩小查询范围。用 WithWithout 来获取带有特定组件的实体。

#![allow(unused)]
fn main() {
fn debug_player_hp(
    // 访问 `Health`,但只针对队友。可选:具有名字
    query: Query<(&Health, Option<&PlayerName>), (With<Player>, Without<Enemy>)>,
) {
    // 获取所有匹配的实体
    for (health, name) in query.iter() {
        if let Some(name) = name {
            eprintln!("Player {} has {} HP.", name.0, health.hp);
        } else {
            eprintln!("Unknown player has {} HP.", health.hp);
        }
    }
}
}

可以组合多个过滤器:

  • 元组中包含多个过滤器:所有过滤器起作用(逻辑与)。
  • Or<...> 中包含多个过滤器:过滤器其中之一起作用(逻辑或)。
    • (注意元组内部)