Rust Bevy Change Detectionについて
はじめに
本記事はBevy非公式(と思えないほど素晴らしい)サイトのメモである。
メモ
BevyにおいてChange Detectionとはデータの変更を検知する機能
である。
データの変更を検知し、それに応じたアクションを定義できる。
データの変更検知では、以下2つのQuery Filterを使用する。
Added<T>
- 指定した型のComponentの生成を検知する
- Entityに指定したComponentが追加された場合や、指定したComponentを持つEntityが生成された場合、検知する
- 指定した型のComponentの生成を検知する
Changed<T>
- 指定したComponentの変更を検知する
- 指定したComponentの値が変更された場合や、指定したComponentが新たに追加された場合、検知する
- 指定したComponentの変更を検知する
/// PlayerのHealth, Xpの変更をChangedで受け取り、Health、Xpを出力する fn debug_stats_change( query: Query< // components (&Health, &PlayerXp), // filters (Without<Enemy>, Or<(Changed<Health>, Changed<PlayerXp>)>), >, ) { for (health, xp) in query.iter() { eprintln!( "hp: {}+{}, xp: {}", health.hp, health.extra, xp.0 ); } } /// Enemy追加をAddedで検知し、そのHealthを出力する fn debug_new_hostiles( query: Query<(Entity, &Health), Added<Enemy>>, ) { for (entity, health) in query.iter() { eprintln!("Entity {:?} is now an enemy! HP: {}", entity, health.hp); } }
Changed
での検知はDerefMut
によってトリガーされる。
ミュータブルなQueryでComponentにアクセスするだけではトリガーされない。
変更後の値が変更前と同じであっても、トリガーは発動してしまうので、以下のように条件分けする必要がある。
fn update_player_xp( mut query: Query<&mut PlayerXp>, ) { for mut xp in query.iter_mut() { let new_xp = maybe_lvl_up(&xp); // 値が同じであればトリガーさせない if new_xp != *xp { *xp = new_xp; } } }