bevyengine / bevyengine/bevy

Observers that can observe multiple different event types

Open
#14,649 9 comments 2 reactions 0 assignees View on GitHub
A-ECS C-Feature D-Complex D-Unsafe S-Ready-For-Implementation
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 22h
Merged PRs (30d)
161

Description

## What problem does this solve or what need does it fill?

Being able to trigger the same observer with multiple different event types would be useful for code reuse and centralizing related logic. This is different from `enum` Event types, which don't allow you to listen to individual variants for separate observers.

## What solution would you like?

```rust
#[derive(Event)]
struct FooEvent { foo: i32 }
#[derive(Event)]
struct BarEvent { bar: bool }

// I imagine `Or<(A, B)>` would deref into some `enum Or2 { A(A), B(B) }`
// `Or<(A, B, C)>` would deref into some `enum Or3 { A(A), B(B), C(C) }`
// etc
// Also, I imagine we'll need a separate `world.observe_any_of()`-style method to correctly handle the internal details
world.observe(|trigger: Trigger>| {
match trigger.event() {
Or2::A(FooEvent { foo }) => { /* do something with foo... */ },
Or2::B(BarEvent { bar }) => { /* do something with bar... */ },
}
});
```

## What alternative(s) have you considered?

Use an enum:
```rust
#[derive(Event)]
enum MyEvent {
Foo { foo: i32 },
Bar { bar: bool },
}

world.observe(|trigger: Trigger| {
match trigger.event() {
MyEvent::Foo { foo } => { /* ... */ },
MyEvent::Bar { bar } => { /* ... */ },
}
});
```

However, that prevents us from listening to only 1 of the event types, or a subset of them.

## Additional context

This was [mentioned on discord](https://discord.com/channels/691052431525675048/1237010014355456115/1270919774729277440) as currently possible, albeit with unsafe APIs, so we should introduce a safe wrapper:
> Diddykonga — Today at 8:41 PM
> Can observers 'observe' multiple events? if not, then the query would need to be split from the observer at some point.
> James 🦃 — Today at 9:02 PM
> Observers can absolutely observe multiple events
> (unsafely)
> nth — Today at 9:03 PM
> What does the trigger return for the event?
> James 🦃 — Today at 9:04 PM
> You have to use unsafe APIs
> So you can make the trigger return any type and you just have to promise it's safe
> The observer for a query should set the ObserverRunner manually to not pay for system overhead
> Diddykonga — Today at 9:06 PM
> Right since you cant carry that information via generics, unsafe is the only way (variadics when?)
> James 🦃 — Today at 9:06 PM
> And the ObserverRunner API just gets a pointer and deferred world
> (similar to a hook)
> doot — Today at 9:13 PM
> I wonder if you could wrap that safely in a Trigger> type api
> actually probably something like a Trigger>

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.