-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Suggestion: A variant of ChangeTrackers that also allows access to the component #7066
Description
What problem does this solve or what need does it fill?
Suppose you have a system that you want to run if any of components A, B, and C are changed, but you want to know which of the three specifically changed when the system has run. Bevy currently presents you with two different ways to do this:
fn some_system(q: Query<(&A, &B, &C, ChangeTrackers<A>, ChangeTrackers<B>, ChangeTrackers<C>)>) {
for (a, b, c, t1, t2, t3) in q.iter() {
if (t1.is_changed()) {
// ...
}
if (t2.is_changed()) {
// ...
}
if (t3.is_changed()) {
// ...
}
}
}fn some_system(mut q: Query<(&mut A, &mut B, &mut C)>) {
for (&mut a, &mut b, &mut c) in q.iter_mut() {
if (a.is_changed()) {
// ...
}
if (b.is_changed()) {
// ...
}
if (c.is_changed()) {
// ...
}
}
}Neither of these are ideal. The former is pretty verbose and makes query grow at double their normal rate. The second forces you to be overly pessimistic when locking components and prevents potential system-level parallelism on component bands even when you don't want to mutably access them.
What solution would you like?
Some Query decorator that provides an is_changed() and is_added() accessor to a component reference, while also allowing immutable access to the component itself, without the pessimistic lock of mutable access.
What alternative(s) have you considered?
The above two options work for now. The first one is functional and meets the requirements of the task without harming parallelism (to my knowledge), but it isn't very ergonomic.
Additional context
We discussed this on Discord here: https://discord.com/channels/691052431525675048/1058204047791898684
One thing that came up is that keeping ChangeTrackers separate from the component reference may be good for data locality reasons (creating a SoA instead of AoS setup in interation). However, some back-of-the-envelope benchmarks indicated that the &mut approach was faster. I don't know enough about the internals to really say which might be more performant, but it is a valid consideration.