Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Replace RemovedComponents<T> backing with Events<Entity> #5680

Closed
wants to merge 6 commits into from

Conversation

Aceeri
Copy link
Member

@Aceeri Aceeri commented Aug 14, 2022

Objective

Removal events are unwieldy and require some knowledge of when to put systems that need to catch events for them, it is very easy to end up missing one and end up with memory leak-ish issues where you don't clean up after yourself.

Solution

Consolidate removals with the benefits of Events<...> (such as double buffering and per system ticks for reading the events) and reduce the special casing of it, ideally I was hoping to move the removals to a Resource in the world, but that seems a bit more rough to implement/maintain because of double mutable borrowing issues.

This doesn't go the full length of change detection esque removal detection a la bevyengine/rfcs#44.
Just tries to make the current workflow a bit more user friendly so detecting removals isn't such a scheduling nightmare.


Changelog

  • RemovedComponents is now backed by an Events<Entity> for the benefits of double buffering.

Migration Guide

  • Add a mut for removed: RemovedComponents<T> since we are now modifying an event reader internally.
  • Iterating over removed components now requires &mut removed_components or removed_components.iter() instead of &removed_components.

@alice-i-cecile alice-i-cecile added A-ECS Entities, components, systems, and events C-Usability A simple quality-of-life change that makes Bevy easier to use labels Aug 14, 2022
@Aceeri
Copy link
Member Author

Aceeri commented Aug 15, 2022

I think re-thinking this I might just store the events in a RemovedComponents(SparseSet<ComponentId, Events<Entity>>);

Where RemovedComponent<T> would be a system param that would automatically fetch the RemovedComponents and component ids. This would make the api exactly the same as it is currently but with the benefits of unifying to the Events api and all that comes with that.

@Aceeri Aceeri marked this pull request as ready for review August 16, 2022 20:19
@Aceeri Aceeri changed the title Replace RemovedComponents with an Event<RemovedComponent<T>> Replace RemovedComponents<T> backing with Events<Entity> Aug 17, 2022
@Aceeri Aceeri force-pushed the removed-components-as-events branch from 82e2672 to 1561a1d Compare August 31, 2022 19:49
@Aceeri Aceeri force-pushed the removed-components-as-events branch 3 times, most recently from 235770c to 39d7af6 Compare December 22, 2022 21:29
@Aceeri
Copy link
Member Author

Aceeri commented Dec 22, 2022

Reworked this a good bit to be less invasive of the ECS stuff, I would like #5735 to get merged before this because right now it isn't really possible for me to return empty iterators of components that haven't been removed yet.

@JoJoJet
Copy link
Member

JoJoJet commented Dec 22, 2022

  • Replace RemovedComponent<T> with EventReader<RemovedComponent<T>> and iters will need to deref into the Entity since it will be a RemovedComponent<T> event instead of an Entity.

Why did you change course on this? This seems like a cleaner API, and I think I remember cart saying he preferred it.

Edit: it was Alice, not Cart.

@Aceeri
Copy link
Member Author

Aceeri commented Dec 23, 2022

Summary of why:
I can't name the Events<RemovedComponent<T>> type to send events on since I have to use a ComponentId to fetch it, which will only give me a type erased PtrMut. I could try registering closures or do something to make a proxy Events<Entity> in a resource, but those seem rather hacky.

Copy link
Member

@JoJoJet JoJoJet left a comment

Choose a reason for hiding this comment

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

I think I'm on board with these changes. Having to add mut on the SystemParam is unfortunate, but IMO it's worth it for the consistency brought by double buffering.

crates/bevy_ecs/src/removal_detection.rs Outdated Show resolved Hide resolved
crates/bevy_ecs/src/event.rs Outdated Show resolved Hide resolved
crates/bevy_ecs/src/component.rs Show resolved Hide resolved
@Aceeri Aceeri force-pushed the removed-components-as-events branch from 1ae0b76 to e71ada6 Compare December 25, 2022 02:46
@Aceeri Aceeri force-pushed the removed-components-as-events branch 3 times, most recently from 91cc714 to df404c2 Compare January 5, 2023 21:54
@alice-i-cecile alice-i-cecile added C-Code-Quality A section of code that is hard to understand or change C-Breaking-Change A breaking change to Bevy's public API that needs to be noted in a migration guide labels Jan 30, 2023
@alice-i-cecile alice-i-cecile added this to the 0.10 milestone Jan 30, 2023
@Aceeri Aceeri force-pushed the removed-components-as-events branch from 11a3ca7 to 95e5212 Compare January 30, 2023 20:52
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.

Thoughts:

  1. ComponentIdFor is very interesting. @jakobhellermann may find it useful for working with dynamically typed APIs.
  2. Oh right: Events used to live in bevy_ecs. That's a good explanation of why we didn't just use them originally.
    3.I really like removing the "one frame" footgun, and reducing the tech debt of just using events.

@alice-i-cecile alice-i-cecile added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Jan 30, 2023
Formatting

Fix some docs

Unnecessary imports

impl From rather than Into for ToComponentId

Try to fix CI errors

Fix up test to expect double buffering

Fix linnk in docs

Simplify component id initializing/fetching

Remove from system params

Move component id for to component file

Move ComponentIdFor to component.rs

Deref and don't allow modifying the component id

IntoIterator for RemovedComponents

Formatting

Example for ComponentIdFor

Improve documentation

MaybeIter inbetween

Remove unnecessary type for iterator

Improve safety comment, don't box unnecessarily

formatting
@Aceeri Aceeri force-pushed the removed-components-as-events branch from 95e5212 to 4d63994 Compare January 30, 2023 21:09
@alice-i-cecile
Copy link
Member

bors r+

@bors
Copy link
Contributor

bors bot commented Feb 4, 2023

Merge conflict.

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.

bors r+

bors bot pushed a commit that referenced this pull request Feb 4, 2023
# Objective
Removal events are unwieldy and require some knowledge of when to put systems that need to catch events for them, it is very easy to end up missing one and end up with memory leak-ish issues where you don't clean up after yourself.

## Solution
Consolidate removals with the benefits of `Events<...>` (such as double buffering and per system ticks for reading the events) and reduce the special casing of it, ideally I was hoping to move the removals to a `Resource` in the world, but that seems a bit more rough to implement/maintain because of double mutable borrowing issues.

This doesn't go the full length of change detection esque removal detection a la bevyengine/rfcs#44.
Just tries to make the current workflow a bit more user friendly so detecting removals isn't such a scheduling nightmare.

---

## Changelog
- RemovedComponents<T> is now backed by an `Events<Entity>` for the benefits of double buffering.

## Migration Guide
- Add a `mut` for `removed: RemovedComponents<T>` since we are now modifying an event reader internally.
- Iterating over removed components now requires `&mut removed_components` or `removed_components.iter()` instead of `&removed_components`.
@bors bors bot changed the title Replace RemovedComponents<T> backing with Events<Entity> [Merged by Bors] - Replace RemovedComponents<T> backing with Events<Entity> Feb 4, 2023
@bors bors bot closed this Feb 4, 2023
@Aceeri Aceeri deleted the removed-components-as-events branch February 4, 2023 21:20
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-Breaking-Change A breaking change to Bevy's public API that needs to be noted in a migration guide C-Code-Quality A section of code that is hard to understand or change C-Usability A simple quality-of-life change that makes Bevy easier to use 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.

4 participants