Commit 2297753
authored
Observer run conditions (#22602)
# Objective
Allow observers to use run conditions, enabling conditional execution
based on world state - the same pattern that systems use with .run_if().
Fixes #14195
Fixes #21442
## Solution
Add a run_if() method to observer systems via the ObserverSystemExt
trait. Conditions are stored in Observer and checked before execution in
the runner.
Key implementation details:
- ObserverWithCondition<E,B,M,S> wrapper preserves event type info for
compile-time EntityEvent enforcement on entity observers
- Conditions are ReadOnlySystem (enforced by SystemCondition trait),
matching system run conditions
- Multiple conditions chain with AND semantics, short-circuiting on
first false
It's a bit more involved than mentioned
[here](#21442 (comment))
since we need the full system‑style API: chained run_ifs, entity
observers with compile‑time EntityEvent checks, and use with
add_observer/observe.
That forces a typed wrapper + marker types +
IntoObserver/IntoEntityObserver, and conditions must be initialized at
spawn time (so the hook has to take/init/restore). The runner also needs
a safety‑documented precheck before running the observer.
## Testing
- Added 7 new tests covering:
- Condition preventing/allowing execution
- Multiple conditions (all true / one false)
- Entity observers with conditions
- Resource-based conditions
- Builder pattern on Observer::new()
- All existing tests pass (cargo test -p bevy_ecs)
- Updated observers.rs example with Space key toggle
---
## Showcase
```rust
#[derive(Resource)]
struct GameActive(bool);
// Global observer - only runs when game is active
app.add_observer(
on_damage.run_if(|state: Res<GameActive>| state.0)
);
// Chained conditions (AND semantics)
app.add_observer(
on_damage
.run_if(|state: Res<GameActive>| state.0)
.run_if(|player: Query<&Health, With<Player>>| player.single().is_ok())
);
// Entity observer
commands.spawn(Enemy).observe(
on_hit.run_if(|game: Res<GameActive>| game.0)
);
// Builder pattern
world.spawn(
Observer::new(on_event)
.with_entity(target)
.run_if(some_condition)
);
```
<details>
<summary>Example from observers.rs</summary>
```rust
#[derive(Resource, Default)]
struct ExplosionsEnabled(bool);
fn toggle_explosions(mut enabled: ResMut<ExplosionsEnabled>, input: Res<ButtonInput<KeyCode>>) {
if input.just_pressed(KeyCode::Space) {
enabled.0 = !enabled.0;
info!("Explosions {}", if enabled.0 { "enabled" } else { "disabled" });
}
}
fn setup(app: &mut App) {
app.add_observer(
explode_mine.run_if(|enabled: Res<ExplosionsEnabled>| enabled.0)
);
}
```
</details>1 parent 4cc92a0 commit 2297753
File tree
11 files changed
+558
-63
lines changed- crates
- bevy_app/src
- bevy_ecs/src
- observer
- system/commands
- world/entity_access
- examples/ecs
- release-content/release-notes
11 files changed
+558
-63
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
14 | | - | |
15 | 14 | | |
16 | 15 | | |
| 16 | + | |
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
22 | | - | |
| 22 | + | |
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| |||
1392 | 1392 | | |
1393 | 1393 | | |
1394 | 1394 | | |
1395 | | - | |
1396 | | - | |
1397 | | - | |
1398 | | - | |
| 1395 | + | |
1399 | 1396 | | |
1400 | 1397 | | |
1401 | 1398 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
80 | 80 | | |
81 | 81 | | |
82 | 82 | | |
83 | | - | |
| 83 | + | |
84 | 84 | | |
85 | 85 | | |
86 | 86 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| 14 | + | |
| 15 | + | |
14 | 16 | | |
15 | 17 | | |
16 | | - | |
17 | 18 | | |
18 | | - | |
| 19 | + | |
19 | 20 | | |
20 | | - | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
21 | 25 | | |
22 | 26 | | |
23 | 27 | | |
| |||
208 | 212 | | |
209 | 213 | | |
210 | 214 | | |
| 215 | + | |
211 | 216 | | |
212 | 217 | | |
213 | 218 | | |
| |||
234 | 239 | | |
235 | 240 | | |
236 | 241 | | |
| 242 | + | |
237 | 243 | | |
238 | 244 | | |
239 | 245 | | |
| |||
246 | 252 | | |
247 | 253 | | |
248 | 254 | | |
249 | | - | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
250 | 259 | | |
251 | 260 | | |
252 | 261 | | |
253 | 262 | | |
254 | 263 | | |
255 | 264 | | |
256 | | - | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
257 | 269 | | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
258 | 274 | | |
259 | 275 | | |
260 | 276 | | |
261 | 277 | | |
262 | 278 | | |
263 | 279 | | |
| 280 | + | |
264 | 281 | | |
265 | 282 | | |
266 | 283 | | |
| |||
326 | 343 | | |
327 | 344 | | |
328 | 345 | | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
329 | 355 | | |
330 | 356 | | |
331 | 357 | | |
| |||
435 | 461 | | |
436 | 462 | | |
437 | 463 | | |
438 | | - | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
439 | 468 | | |
440 | 469 | | |
441 | 470 | | |
442 | 471 | | |
443 | | - | |
444 | | - | |
445 | | - | |
446 | | - | |
447 | | - | |
448 | | - | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
449 | 489 | | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
450 | 496 | | |
451 | 497 | | |
452 | 498 | | |
| |||
510 | 556 | | |
511 | 557 | | |
512 | 558 | | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
0 commit comments