bevy-ecs-queries について
Bevy 0.19 の ECS クエリを扱うスキルです。システム内でのコンポーネント操作、エンティティのフィルタリング、並列反復を扱い、変更されたクエリ境界や反復方法、エラー処理を説明します。
主な機能
- 01エンティティコンポーネントの読み書き
- 02コンポーネントや変更状態による絞り込み
- 03par_iter_mut による並列反復
- 04レンズによるクエリ部分の借用
- 05Bevy 0.19 のクエリ境界の解説
活用シーン
- 01Bevy システムのクエリ処理の実装
- 02大量のエンティティの絞り込みや並列処理
- 03更新後に発生したクエリのコンパイルエラー解決
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ chrisgliddon/ bevy-skills --skill bevy-ecs-queriesインストール後、Claude Code で/bevy-ecs-queriesを入力して読み込まれたか確認します。
詳細
Bevy 0.19 — ECS クエリ
このスキルを使う場面
- システムからコンポーネントを読み取る、または書き込む場合。
- 存在によるフィルタリング(
With/Without)、選択(Or)、変更検出(Changed/Added)を行う場合。 par_iter_mutを使って、大量のエンティティを並列処理する場合。- レンズ(
transmute_lens)を使って、クエリの一部を借用する場合。 - 0.19 へのアップグレード後に、
IterQueryDataまたはSingleEntityQueryDataに関するコンパイラーエラーが発生した場合。
標準的なパターン
use bevy::prelude::*;
#[derive(Component, Default)]
struct Health(f32);
#[derive(Component, Default)]
struct Velocity(Vec3);
#[derive(Component)]
struct Player;
#[derive(Component)]
struct Enemy;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Update, (
move_things,
on_health_changed,
damage_visible_enemies,
integrate_in_parallel,
))
.run();
}
// Sequential iteration. `&` for read, `&mut` for write.
fn move_things(time: Res<Time>, mut q: Query<(&Velocity, &mut Transform)>) {
let dt = time.delta_secs();
for (vel, mut tf) in &mut q {
tf.translation += vel.0 * dt;
}
}
// Change detection. `Changed<T>` triggers on insert OR mutation.
// `Added<T>` triggers only on insert.
fn on_health_changed(q: Query<(Entity, &Health), Changed<Health>>) {
for (entity, hp) in &q {
info!("entity {:?} now has {} hp", entity, hp.0);
}
}
// Combined filters. `With`/`Without` constrain entities;
// `Or<(...)>` alternates over filters (not components).
fn damage_visible_enemies(
mut q: Query<&mut Health, (With<Enemy>, Without<Player>, Or<(Added<Enemy>, Changed<Transform>)>)>,
) {
for mut hp in &mut q {
hp.0 -= 1.0;
}
}
// Parallel iteration. Use when N is large (>10k) and per-entity work is non-trivial.
// Cannot use `Commands` or external mutable state — task pool runs items in parallel.
fn integrate_in_parallel(mut q: Query<(&Velocity, &mut Transform)>) {
q.par_iter_mut().for_each(|(vel, mut tf)| {
tf.translation += vel.0 * 0.016;
});
}
// Query lens: temporarily view a query as a narrower one. Useful for
// passing a stricter query into a helper without re-binding the system's
// SystemParam list.
#[allow(dead_code)]
fn use_lens(mut q: Query<(&mut Transform, &Velocity)>) {
// Read-only narrowed view of just the Transform column.
let mut lens = q.transmute_lens::<&Transform>();
let _read_only: Query<&Transform> = lens.query();
}
Bevy 0.19 で注意する点
- 0.19 ではネストされたクエリアクセスに境界が追加されました。 ジェネリックな可変イテレーションでは通常、
D: IterQueryDataが必要です。単一エンティティへのアクセス、クエリの型変換/結合、トラバーサル、ソートでは、D: SingleEntityQueryDataが必要になる場合があります。読み取り専用のイテレーションでは、引き続きより広い境界が適用されます。 - イテレーションできないクエリデータでは、貸し出し型のイテレーションを使います。
D: QueryDataを維持し、let mut iter = query.iter_mut()を呼び出してから、ネストされたクエリアイテムが複数のエンティティにアクセスする可能性がある場合は、iter.fetch_next()を繰り返し呼び出します。 EntityMut::get_components_mut::<(&mut A, &mut B)>()は、1つのエンティティから2つの&mutを安全に取得する方法であり、現在はSingleEntityQueryData境界も必要です。これはResultを返します。未チェックのエイリアスを使わないでください。Query::get/get_mutはOptionではなくResultを返します。 エラー型にはエンティティが含まれるため、検索に失敗した理由を知る必要がある場合は、.ok()でエラーを無視しないでください。Or<(With<A>, With<B>)>—Orが選択するのは生のコンポーネント型ではなく、フィルターです。Or<(A, B)>はコンパイルできません。Changed/Addedはティックベースです。 システムの前回実行時点と比較するため、通常の実行条件によって途中の変更が見落とされることはありません。検出するのは変更であり、意味上の不等価性ではありません。すべての発生や旧値/新値が必要な場合は、オブザーバー/メッセージを使ってください。par_iter_mutとCommandsを組み合わせないでください。 並列システムが書き込むResourceキューを読み取る逐次システムから、スポーン/デスポーンを実行してください。
関連項目
bevy-ecs-components— ここでクエリするコンポーネントの宣言。bevy-ecs-systems—SystemParamと実行条件の中でクエリを使う方法。bevy-migration-0-17-to-0-18—EntityMut::get_components_mutとティック型の移動。bevy-migration-0-18-to-0-19— ネストされたクエリのトレイト境界とクエリ内のリソース。
コメント
Markdown 対応