Skip to content

Improve On Terminology#20648

Merged
cart merged 2 commits intobevyengine:mainfrom
cart:observer_naming
Aug 21, 2025
Merged

Improve On Terminology#20648
cart merged 2 commits intobevyengine:mainfrom
cart:observer_naming

Conversation

@cart
Copy link
Member

@cart cart commented Aug 19, 2025

Objective

Fixes #19263 (and expands on it)

Within Observers, we have started to distance ourselves from the "trigger" terminology. Specifically, we have renamed Trigger to On. I think this was a very good move, but we're currently in an awkward middle ground state. Users interact with On as if it were an event: On<E> exposes the event and derefs directly to it. I think we should embrace this mindset fully, in the interest of clarity.

Solution

  • Rename all trigger: On<SomeEvent> cases to event: On<SomeEvent>.
  • Rename On::target to On::entity. This reads much better when writing query.get(event.entity()) and pairs more effectively with the EntityEvent terminology.
  • Rename On::original_target to On::original_entity, for the same reasons.
  • Take advantage of the Deref behavior where appropriate
// Before
entity.observe(|trigger: On<Explode>| {
  println!("{} exploded!", trigger.target());
})

// After
entity.observe(|event: On<Explode>| {
  println!("{} exploded!", event.entity());
})

@cart cart added this to the 0.17 milestone Aug 19, 2025
@cart cart added A-ECS Entities, components, systems, and events C-Code-Quality A section of code that is hard to understand or change C-Usability A targeted quality-of-life change that makes Bevy easier to use labels Aug 19, 2025
@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 S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Aug 19, 2025
Copy link
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.

I particularly like the event: On<> naming convention changes. Those help a lot!

I would generally stick this PR in the list of observers overhaul PRs for the release note, and add you as a co-author of the work because of your design input here. You can make the editorial call there yourself though :)

/// If the event was not targeted at a specific entity, this will return [`Entity::PLACEHOLDER`].
pub fn target(&self) -> Entity {
self.trigger.current_target.unwrap_or(Entity::PLACEHOLDER)
pub fn entity(&self) -> Entity {
Copy link
Contributor

Choose a reason for hiding this comment

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

This PR essentially reverts @aevyrie's #16716 right? Are the arguments from that PR no longer valid?

The field entity: Entity encodes no semantic information about what the entity is used for, you can already tell that it's an Entity by the type signature!

Stands out to be the biggest argument to keep it as is.

Copy link
Member Author

Choose a reason for hiding this comment

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

I never signed off on that one. I think the arguments are reasonable, but not enough to sway me:

The question users will be asking is: "what Entity was this Event triggered for?". The natural way to ask that question in code is event.entity(). This is especially true in light of the EntityEvent naming. I'm of the opinion that "event entity-ness" in this context is significantly more relevant and useful than "event target-ness".

I believe that particular change was motivated by a desire to disambiguate between "observer entity", "target entity", and "original target entity". When considering those things as an internals developer, I can see the desire to treat them all as equals here. But in practice the "observer entity" is deeply niche. We don't need to disambiguate that for 99.99% of users, who just want to know what entity their EntityEvent was triggered on. event.entity() is the clearest, most direct way to handle that case. I'm content with developers who want the "observer entity" to need to understand the event.entity() vs event.observer() distinction ... but I don't think those developers will be confused either.

Copy link
Member Author

Choose a reason for hiding this comment

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

I do think that the churn is regrettable. But not so regrettable that I think we should hold back (what I consider to be) real clarity improvements.

Copy link
Member Author

Choose a reason for hiding this comment

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

#16716 was also back when we were using trigger: Trigger<Explode> terminology, where Trigger was more of its own "thing". Now that we are embracing "eventness" with event: On<Explode>, I think that further improves the clarity of event.entity().

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah the churn is mildly amusing for me since I am porting to 0.16 literally right now, and I just did the trigger.entity() -> trigger.target() thing, but it's an easy migration either way so I agree you should pick the "right" API here rather than worry about the churn.

Copy link
Member

Choose a reason for hiding this comment

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

The question users will be asking is: "what Entity was this Event triggered for?".

@cart what is this hypothesis based on? The change happened because people were getting confused about what entity that was.

Copy link
Member

Choose a reason for hiding this comment

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

It's pretty natural to want both the target and the listener, that happens all the time in UI/reactive code. Calling this entity removes any semantic information about the kind of entity this is - it's already trivially obvious that you have an Entity.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm of the opinion that "event entity-ness" in this context is significantly more relevant and useful than "event target-ness

When people discuss "what entity was this event triggered on", the answer is the event target, not the "event entity". Calling it an event target is some very standard terminology IME, and using the name .entity() removes all the semantics about the kind of entity it is, like aevyrie mentioned.

For me, it's not even about disambiguating between .entity() and .observer(), it's about what the .entity() is and what name makes sense for it in that context. It is the target entity of the event. As for API consistency, the name of the method that even triggers the event is .trigger_targets(). It is strange to me that "target" is then stripped away from the actual Event API.

To me, .entity() is not at all a clarity improvement. I would not be too surprised to see it renamed back to .target() yet again next cycle if this is released, so it just feels like a lot of churn to make this change at the end of the cycle when there doesn't seem to be broad consensus on it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Was this discussion ever resolved? I see the PR was merged, but I also think people raise valid concerns that haven't gotten a response here (perhaps somewhere else?). Given that 0.16 changed it to target, I feel like, if there's still something to discuss here, we still have time to keep that name scheme, before 0.17 ships, if we want to?

Copy link
Member Author

Choose a reason for hiding this comment

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

I consider this to be resolved by #20731, which solves this in a variety of ways:

  1. Entity events now include the entity target inside the event, and can give it whatever name makes the most sense for the event. As a pattern, we encourage developers to directly use the field to access the target entity.
  2. Because the field is used directly, this also allows event authors to directly document the field, allowing more specific context.
  3. This is less common, but if using the EntityEvent trait to access the target entity, it now uses EntityEvent::event_target to be less ambiguous.

@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 Aug 19, 2025
@alice-i-cecile alice-i-cecile added this pull request to the merge queue Aug 19, 2025
@alice-i-cecile alice-i-cecile removed this pull request from the merge queue due to a manual request Aug 19, 2025
@cart cart added this pull request to the merge queue Aug 21, 2025
Merged via the queue into bevyengine:main with commit 5058f8a Aug 21, 2025
45 checks passed
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-Code-Quality A section of code that is hard to understand or change C-Usability A targeted quality-of-life change that makes Bevy easier to use M-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rename observer entity methods and fields

7 participants