bevy-ecs-expert について
Rustでゲームを開発する人向けのBevy ECSガイドです。データ指向のゲームロジック、システムのスケジューリング、クエリ、リソース管理を扱い、クエリの絞り込みや並列実行の考え方も示します。
主な機能
- 01データのみのコンポーネント定義
- 02クエリを使ったシステム作成
- 03グローバルリソース管理
- 04システムのスケジュールと順序設定
- 05エンティティクエリの絞り込み
- 06クエリ競合の解決
活用シーン
- 01Bevy ECSでゲームロジックを構成
- 02互換性のあるシステムの並列実行
- 03エンティティ反復の最適化
- 04オブジェクト指向ロジックの再構成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ sickn33/ agentic-awesome-skills --skill bevy-ecs-expertインストール後、Claude Code で/bevy-ecs-expertを入力して読み込まれたか確認します。
詳細
Bevy ECS エキスパート
概要
Bevy のデータ指向 ECS アーキテクチャを使用して、高パフォーマンスなゲームロジックを構築するためのガイドです。システムの構成方法、クエリの最適化、リソースの管理、並列実行の活用方法を学びます。
このスキルを使用する場面
- Rust で Bevy エンジンを使用したゲームを開発するとき。
- 並列実行が必要なゲームシステムを設計するとき。
- キャッシュミスを最小限に抑えてゲームのパフォーマンスを最適化するとき。
- オブジェクト指向ロジックをデータ指向の ECS パターンにリファクタリングするとき。
手順ガイド
1. コンポーネントの定義
データにはシンプルな構造体を使用します。bevy::prelude::* をインポートし、リフレクションやインスペクションが必要な場合にのみ Reflect を追加します。以下のスニペットはそれぞれ別の方法を示しているため、同じスコープ内で Player と Velocity の定義を重複させないでください。
#[derive(Component, Reflect, Default)]
#[reflect(Component)]
struct Velocity {
x: f32,
y: f32,
}
#[derive(Component)]
struct Player;
2. システムの記述
システムは、コンポーネントをクエリする通常の Rust 関数です。
fn movement_system(
time: Res<Time>,
mut query: Query<(&mut Transform, &Velocity), With<Player>>,
) {
for (mut transform, velocity) in &mut query {
transform.translation.x += velocity.x * time.delta_secs();
transform.translation.y += velocity.y * time.delta_secs();
}
}
3. リソースの管理
グローバルデータ(スコア、ゲーム状態)には Resource を使用します。
#[derive(Resource, Default)]
struct GameState {
score: u32,
}
fn score_system(mut game_state: ResMut<GameState>) {
game_state.score += 10;
}
この例の score_system は各 Update でスコアを増やします。フレームレートに依存しないスコア動作を暗示するのではなく、意味のあるスコア加算にはゲームプレイイベントか明示的なタイマーを使用してください。
4. システムのスケジューリング
必要に応じて実行順序を定義しながら、App ビルダーにシステムを追加します。
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.init_resource::<GameState>()
.add_systems(Update, (movement_system, score_system).chain())
.run();
}
例
例 1:必須コンポーネントを使用したエンティティの生成
use bevy::prelude::*;
#[derive(Component, Reflect, Default)]
#[require(Velocity, Sprite)]
struct Player;
#[derive(Component, Default)]
struct Velocity {
x: f32,
y: f32,
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn((
Player,
Velocity { x: 10.0, y: 0.0 },
Sprite::from_image(asset_server.load("player.png")),
));
}
例 2:クエリフィルター
With と Without を使用して、エンティティを効率的にフィルタリングします。
fn enemy_behavior(
query: Query<&Transform, (With<Enemy>, Without<Dead>)>,
) {
for transform in &query {
// Only active enemies processed here
}
}
ベストプラクティス
- ✅ 推奨:
Queryフィルター(With、Without、Changed)を使用して、反復処理の回数を減らします。 - ✅ 推奨: 読み取り専用アクセスで十分な場合は
ResMutよりResを優先し、並列実行を可能にします。 - ✅ 推奨: 複雑なエンティティをまとめて生成するには
Bundleを使用します。 - ❌ 非推奨: 重いロジックをコンポーネント内に格納しないでください。コンポーネントは純粋なデータとして維持します。
- ❌ 非推奨: コンポーネント内で
RefCellや内部可変性を使用しないでください。通常の ECS の借用を優先します。内部可変性を使う設計でも、有効な Send/Sync と明確な同期上の理由が必要です。
トラブルシューティング
問題: 「Conflict」エラーでシステムがパニックします。
解決策: スケジューラーは通常、競合するシステムの実行順序を調整します。Bevy B0001 は多くの場合、単一のシステム内にある互換性のないクエリが原因です。適切に互いに素となる With/Without フィルター、または ParamSet を使用してください。2 つのシステムをチェーンしても、単一システム内のパラメーター間の競合は解消されません。Bevy B0001 を参照してください。
制限事項
- プロジェクトで使用する Bevy のバージョンを固定し、移行/API ガイドを確認してください。現在の例では delta_secs と必須コンポーネントを使用していますが、古い Bevy のバージョンでは異なる場合があります。Enemy/Dead はアプリケーション側で定義するコンポーネントマーカーであり、player.png はアプリケーションのアセットで、同梱ファイルではありません。ここではエンジンのコンパイルやパフォーマンスのベンチマークを主張していません。
- 出力を、環境固有の検証、テスト、または専門家によるレビューの代わりとして扱わないでください。
- 必要な入力、権限、安全上の境界、または成功基準が不足している場合は、作業を中断して確認を求めてください。