Skip to content

Observer EventPatterns#24013

Open
ItsDoot wants to merge 15 commits into
bevyengine:mainfrom
ItsDoot:ecs/nomoreb
Open

Observer EventPatterns#24013
ItsDoot wants to merge 15 commits into
bevyengine:mainfrom
ItsDoot:ecs/nomoreb

Conversation

@ItsDoot
Copy link
Copy Markdown
Contributor

@ItsDoot ItsDoot commented Apr 28, 2026

Objective

On<E, B>'s B type parameter is the single most commonly confusing construct in bevy_ecs. The predominate use case is for filtering lifecycle event observers:

world.add_observer(|on: On<Add, A>| {
    // gets fired whenever component `A` is added to an entity
});

For most other use cases, like picking or custom user events, this type parameter is wholly unnecessary.

Therefore, it should be hidden away for the cases where it is not needed.

Solution

Introduce a thin layer above Event called EventPattern, and update On's bounds:

pub trait EventPattern: 'static {
    type Event: Event;
    type Components: Bundle;
}

pub struct On<'w, 't, E: EventPattern> {
    observer: Entity,
    event: &'w mut E::Event,
    trigger: &'w mut EventPatternTrigger<'t, E>,
    trigger_context: &'w TriggerContext,
}

This allows us to lift the B type parameter in On<E, B> into the E type parameter. To ensure other events like picking continue to work, we introduce a blanket implementation for all Events:

// All events are implicitly EventPatterns, with no additional components.
impl<E: Event> EventPattern for E {
    type Event = Self;
    type Components = ();
}

To facilitate lifecycle events, we first rename them as follows:

  • Add -> AddEvent
  • Insert -> InsertEvent
  • Discard -> DiscardEvent
  • Remove -> RemoveEvent
  • Despawn -> DespawnEvent

Then, we introduce new generic types in place of those old identifiers that are EventPatterns:

pub struct Add<B: Bundle>(PhantomData<B>);

impl<B: Bundle> EventPattern for Add<B> {
    type Event = AddEvent;
    type Components = B;
}

pub struct Insert<B: Bundle>(PhantomData<B>);

impl<B: Bundle> EventPattern for Insert<B> {
    type Event = InsertEvent;
    type Components = B;
}

pub struct Discard<B: Bundle>(PhantomData<B>);

impl<B: Bundle> EventPattern for Discard<B> {
    type Event = DiscardEvent;
    type Components = B;
}

pub struct Remove<B: Bundle>(PhantomData<B>);

impl<B: Bundle> EventPattern for Remove<B> {
    type Event = RemoveEvent;
    type Components = B;
}

pub struct Despawn<B: Bundle>(PhantomData<B>);

impl<B: Bundle> EventPattern for Despawn<B> {
    type Event = DespawnEvent;
    type Components = B;
}

This results in a slightly modified observer setup:

world.add_observer(|on: On<Add<A>>| {
    // gets fired whenever component `A` is added to an entity
});

Testing

No new tests have been added, we have decent coverage of observer tests as is.

@ItsDoot ItsDoot added A-ECS Entities, components, systems, and events C-Usability A targeted quality-of-life change that makes Bevy easier to use D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Apr 28, 2026
@ItsDoot ItsDoot added this to the 0.20 milestone Apr 28, 2026
@alice-i-cecile alice-i-cecile added M-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide X-Blessed Has a large architectural impact or tradeoffs, but the design has been endorsed by decision makers X-Needs-SME This type of work requires an SME to approve it. and removed X-Blessed Has a large architectural impact or tradeoffs, but the design has been endorsed by decision makers labels Apr 28, 2026
@github-project-automation github-project-automation Bot moved this to Needs SME Triage in ECS Apr 28, 2026
Comment thread _release-content/migration-guides/observer_event_matching.md
Copy link
Copy Markdown
Contributor

@james-j-obrien james-j-obrien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool approach! Looks good.

Comment thread crates/bevy_ecs/src/lifecycle.rs Outdated
Copy link
Copy Markdown
Contributor

@Diddykonga Diddykonga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Abstracts the E: Event and B: Bundle from On<E, B> into On<E> where E: EventMatcher
This allows the syntax to be like Add<C>, while the actual semantics use the Event and Components associated types on the EventMatcher. Similiar-ish to an custom WorldQuery.

@ItsDoot ItsDoot requested a review from chescock April 28, 2026 07:32
Copy link
Copy Markdown
Contributor

@chescock chescock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this is an elegant way to solve this! I like how a bunch of B generics disappeared from places that don't care about them.

Comment thread crates/bevy_ecs/src/observer/system_param.rs Outdated
Comment thread crates/bevy_ecs/src/lifecycle.rs
Comment thread crates/bevy_ui_widgets/src/observe.rs Outdated
Comment thread crates/bevy_ecs/src/event/mod.rs Outdated
Comment thread _release-content/migration-guides/observer_event_matching.md
Comment thread crates/bevy_ecs/src/event/mod.rs
Comment thread crates/bevy_ecs/src/lifecycle.rs
@alice-i-cecile alice-i-cecile added S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Apr 29, 2026
@alice-i-cecile
Copy link
Copy Markdown
Member

I'm curious about the answers to @chescock's questions :)

FYI, I'm planning to hold off merging this until after we cut the 0.19-rc, so we can land this together with a F: QueryFilter generic in 0.20.

@ItsDoot ItsDoot changed the title Observer EventMatchers Observer EventPatterns May 1, 2026
@cart cart closed this May 5, 2026
@github-project-automation github-project-automation Bot moved this from Needs SME Triage to Done in ECS May 5, 2026
@cart cart reopened this May 5, 2026
@github-project-automation github-project-automation Bot moved this from Done to Needs SME Triage in ECS May 5, 2026
@alice-i-cecile alice-i-cecile added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels May 5, 2026
@mockersf mockersf added S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged and removed S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it labels May 22, 2026
@mockersf
Copy link
Copy Markdown
Member

@ItsDoot this has some conflicts, could you resolve them?

@alice-i-cecile alice-i-cecile added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels May 22, 2026
@mockersf mockersf added S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged and removed S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it labels May 22, 2026
@mockersf
Copy link
Copy Markdown
Member

needs a few fixes for CI

@ItsDoot ItsDoot added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels May 29, 2026
@cart cart moved this to Candidate in @cart's attention May 29, 2026
Comment thread _release-content/migration-guides/observer_event_matching.md Outdated
Copy link
Copy Markdown
Member

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my merge train notes:

Oh ho-ho: a beefy one! Getting rid of the bundle generic in observers is something I've wanted to do for years now.
Moving it to the lifecycle events makes perfect sense, and it's great to see that we could actually get something that compiles here.

Let's pull this down for a more complete review: this is literally my job as an SME-ECS.
Okay, I see: we're extending the class of things that can be used in observers to EventPattern, as a superset of Events.
Makes sense.
EventPattern is not my favorite name, but I can live with it since I don't have a better suggestion.

Solid docs for some genuinely complex machinery. The cross-links are incredibly important for putting together an understanding of what's going on.

Migration guide is good, and has the added benefit of verifying that the dynamic component case was not lost.

This has my approval.
@cart self-requested a review a few days ago though.
I'm going to ping him before merging this; there's no immediate rush, as badly as I want this.

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
@alice-i-cecile alice-i-cecile added S-Waiting-on-SME This is currently waiting for an SME to resolve something controversial and removed S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it labels Jun 2, 2026
@alice-i-cecile
Copy link
Copy Markdown
Member

I do. I consider myself a primary keeper of the "observer context" in terms of the current implementation, its limitations, and the desired future path. Historically, changes to observers have been fraught and I'd like to keep things on the rails. Happy to give this some time after 0.19 is ready

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-ECS Entities, components, systems, and events C-Usability A targeted quality-of-life change that makes Bevy easier to use D-Straightforward Simple bug fixes and API improvements, docs, test and examples M-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide S-Waiting-on-SME This is currently waiting for an SME to resolve something controversial X-Needs-SME This type of work requires an SME to approve it.

Projects

Status: Candidate
Status: Needs SME Triage

Development

Successfully merging this pull request may close these issues.

8 participants