bevy-ecs-systems について
bevy-ecs-systemsは、Bevy 0.19のECSシステム、パラメーター、セット、実行条件、状態スケジュールを扱うスキルです。Bevyアプリケーションの開発者向けに、システムの順序付け、実行時の削除、曖昧性エラーへの対処を解説します。
主な機能
- 01SystemParamによる状態の集約
- 02SystemSetによるシステムのグループ化と順序付け
- 03実行条件によるシステムの制御
- 04状態遷移に応じたシステムの実行
- 05実行時のセットからのシステム削除
- 06スケジュールの曖昧性エラーの診断
活用シーン
- 01関連システムのセットへの整理
- 02条件を満たす場合のみシステムを実行
- 03アプリケーションの状態遷移への対応
- 04実行時のデバッグシステム削除
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ chrisgliddon/ bevy-skills --skill bevy-ecs-systemsインストール後、Claude Code で/bevy-ecs-systemsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/ordering.mdrun-conditions.mdruntime-removal.mdstate-schedules.mdsystem-params.mdsystem-sets.md詳細
Bevy 0.19 — ECS システム(パラメーター、セット、実行条件)
このスキルを使用する場面
#[derive(SystemParam)]を使って、関連する状態を単一のシステムパラメーターにまとめる場合。- システムを
SystemSetにグループ化し、呼び出し元がグループ全体に対して実行順序を指定できるようにする場合。 - 実行条件(
run_if、on_message、in_state、resource_exists、any_with_component)でシステムの実行を制御する場合。 OnEnter(S)/OnExit(S)/OnTransition { from, to }を使って状態遷移にフックする場合。remove_systems_in_setを使って、実行時にシステムを取り除く場合(例:デバッグオーバーレイを終了する)。ScheduleBuildErrorによる曖昧性のパニックが発生した場合。エグゼキューターは推測しなくなりました。
基本パターン
use bevy::ecs::system::SystemParam;
use bevy::prelude::*;
#[derive(SystemSet, Hash, PartialEq, Eq, Clone, Debug)]
enum GameLoop { Input, Simulate, Render }
#[derive(States, Default, Hash, PartialEq, Eq, Clone, Debug)]
enum AppState { #[default] Loading, Playing }
#[derive(Resource, Default)]
struct Score(u32);
#[derive(Message)]
struct GoalScored { team: u8 }
// Composite param: pass one argument, get four.
// 'w = world borrow; 's = system-local state borrow.
#[derive(SystemParam)]
struct GameCtx<'w, 's> {
time: Res<'w, Time>,
score: ResMut<'w, Score>,
goals: MessageReader<'w, 's, GoalScored>,
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.init_resource::<Score>()
.add_message::<GoalScored>()
.init_state::<AppState>()
.configure_sets(Update, (GameLoop::Input, GameLoop::Simulate, GameLoop::Render).chain())
// State schedule: fires once when entering Playing.
.add_systems(OnEnter(AppState::Playing), spawn_level)
// State schedule: fires once when leaving Playing.
.add_systems(OnExit(AppState::Playing), despawn_level)
.add_systems(Update, read_input.in_set(GameLoop::Input))
.add_systems(
Update,
tally_goals
.in_set(GameLoop::Simulate)
.run_if(on_message::<GoalScored>),
)
.add_systems(Update, draw_hud.in_set(GameLoop::Render))
.run();
}
#[derive(Component)]
struct LevelEntity;
fn spawn_level(mut commands: Commands) {
commands.spawn((LevelEntity, Name::new("level")));
}
fn despawn_level(mut commands: Commands, query: Query<Entity, With<LevelEntity>>) {
for e in &query { commands.entity(e).despawn(); }
}
fn read_input(mut writer: MessageWriter<GoalScored>) {
writer.write(GoalScored { team: 0 });
}
fn tally_goals(mut ctx: GameCtx) {
let _ = ctx.time.delta_secs();
for goal in ctx.goals.read() {
ctx.score.0 += 1;
info!("team {} scored, total {}", goal.team, ctx.score.0);
}
}
fn draw_hud(score: Res<Score>) { let _ = score.0; }
実行条件の早見表
| 組み込み条件 | 実行される条件 |
|---|---|
on_message::<M> | Messages<M> バッファーに未読の項目がある場合。 |
resource_exists::<R> | リソース R が World に存在する場合。 |
resource_changed::<R> | このティックで R が変更された場合。 |
in_state(MyState::X) | 現在の State<MyState> が X と等しい場合。 |
state_changed::<MyState> | このティックで状態が変更された場合。 |
any_with_component::<C> | C を持つエンティティが少なくとも1つある場合。 |
.and() / .or() と組み合わせます:run_if(in_state(GameState::Playing).and(resource_exists::<NetSession>()))。
トピック
| トピック | リファレンス |
|---|---|
#[derive(SystemParam)]、'w/'s のライフタイム、Local<T>、Commands の遅延適用 | references/system-params.md |
#[derive(SystemSet)] の要件、.in_set、.configure_sets、.chain() | references/system-sets.md |
すべての組み込み条件、.and()/.or()/not()、カスタム条件、コストに関する規則 | references/run-conditions.md |
OnEnter(S) / OnExit(S) / OnTransition、NextState<S>、set_if_neq | references/state-schedules.md |
.before、.after、.chain()、.ambiguous_with、曖昧性エラーのデバッグ | references/ordering.md |
remove_systems_in_set、クリーンアップポリシー、スケジュールをまたぐ実行時の削除、副作用の制限 | references/runtime-removal.md |
Bevy 0.19 の注意点
- 共有アクセスでは実行順序は決まりません。 競合する可変システムは直列化されますが、相互の実行順序は未指定です。曖昧性診断を有効にし、動作が順序に依存する場合は
.before、.after、または.chain()を追加してください。references/ordering.md を参照してください。 EventReader/EventWriterではなく、MessageReader/MessageWriterを使います。 0.17 で名称が変更されました。トレイトの derive は#[derive(Message)]、登録にはapp.add_message::<M>()を使います。- 0.18 では
next_state.set(S)を呼ぶと、常にOnExit/OnEnterが実行されます。 以前の動作にするにはset_if_neqを使ってください。references/state-schedules.md を参照してください。 Schedulesを介して、現在実行中のスケジュールを削除しないでください。 そのリソースから一時的に取り除かれています。Updateのシステムは、Lastなど、後に実行される別のスケジュールから削除してください。references/runtime-removal.md を参照してください。- 0.19 では
Resource: Componentです。 ジェネリックなシステムパラメーターでは引き続きRes<T>/ResMut<T>を使いますが、T: Resourceの境界だけでは、Tがコンポーネントクエリに現れないことは保証されなくなりました。
関連項目
bevy-core-concepts— システムを追加するスケジュール(Startup、Update、FixedUpdate)。bevy-ecs-queries— クエリは多数あるSystemParamの1つです。Changed<T>/Added<T>フィルターについても説明しています。bevy-ecs-components— システムが操作するComponent型の定義。bevy-migration-0-17-to-0-18— Message/Event の全面的な名称変更、MaterialPluginの変更。bevy-migration-0-18-to-0-19— リソースの境界とエグゼキューターの設定。
コメント
Markdown 対応