查询

可参考的官方例子: ecs_guide.


查询可以让你访问构成实体的组件

fn check_zero_health(
    // access entities that have `Health` and `Transform` components
    // get read-only access to `Health` and mutable access to `Transform`
    // optional component: get access to `Player` if it exists
    mut query: Query<(&Health, &mut Transform, Option<&Player>)>,
) {
    // get all matching entities
    for (health, mut transform, player) in query.iter_mut() {
        eprintln!("Entity at {} has {} HP.", transform.translation, health.hp);

        // center if hp is zero
        if health.hp <= 0.0 {
            transform.translation = Vec3::ZERO;
        }

        if let Some(player) = player {
            // the current entity is the player!
            // do something special!
        }
    }
}

获取与一个特定 实体 相关的 组件

    if let Ok((health, mut transform)) = query.get_mut(entity) {
        // do something with the components
    } else {
        // the entity does not have the components from the query
    }

通过查询获取你所访问的实体的ID(Entity):

// add `Entity` to `Query` to get Entity IDs
fn query_entities(q: Query<(Entity, /* ... */)>) {
    for (e, /* ... */) in q.iter() {
        // `e` is the Entity ID of the entity we are accessing
    }
}

如果你知道你的查询只会匹配一个实体,你可以使用 single/single_mut 直接获取该实体,而不必使用迭代:

fn query_player(mut q: Query<(&Player, &mut Transform)>) {
    let (player, mut transform) = q.single_mut();

    // do something with the player and its transform
}

(如果查询匹配了一个以上的实体,这种访问方式将引起崩溃)

Bundle

查询适用于单个组件。如果你使用一个 bundle 创建了一个实体,你需要从该 bundle 中查询你所关心的特定组件。

一个常见的初学者的错误是查询 bundle 类型!

查询过滤器

添加查询过滤器来缩小你从查询中得到的实体的范围。

使用 With/Without 来只获得具有特定组件的实体。

fn debug_player_hp(
    // access the health, only for friendly players, optionally with name
    query: Query<(&Health, Option<&PlayerName>), (With<Player>, Without<Enemy>)>,
) {
    // get all matching entities
    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);
        }
    }
}

多个过滤器可以合并使用:

  • 在一个元组中应用所有的过滤器(AND 逻辑)。
  • 使用 Or<(...)> 包装器来检测其中任何一个(OR 逻辑)。
    • (注意里面的元组)