mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Fix observer unregistering unsetting archetype flags (#14963)
# Objective - Fixes https://github.com/bevyengine/bevy/issues/14961 ## Solution - Check that the archetypes don't contain any other observed components before unsetting their flags ## Testing - I added a regression test: `observer_despawn_archetype_flags`
This commit is contained in:
parent
e08497dc8f
commit
f2cf02408f
2 changed files with 32 additions and 2 deletions
|
@ -367,7 +367,7 @@ pub struct Archetype {
|
|||
edges: Edges,
|
||||
entities: Vec<ArchetypeEntity>,
|
||||
components: ImmutableSparseSet<ComponentId, ArchetypeComponentInfo>,
|
||||
flags: ArchetypeFlags,
|
||||
pub(crate) flags: ArchetypeFlags,
|
||||
}
|
||||
|
||||
impl Archetype {
|
||||
|
|
|
@ -429,7 +429,17 @@ impl World {
|
|||
if observers.map.is_empty() && observers.entity_map.is_empty() {
|
||||
cache.component_observers.remove(component);
|
||||
if let Some(flag) = Observers::is_archetype_cached(event_type) {
|
||||
archetypes.update_flags(*component, flag, false);
|
||||
for archetype in &mut archetypes.archetypes {
|
||||
if archetype.contains(*component) {
|
||||
let no_longer_observed = archetype
|
||||
.components()
|
||||
.all(|id| !cache.component_observers.contains_key(&id));
|
||||
|
||||
if no_longer_observed {
|
||||
archetype.flags.set(flag, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -656,6 +666,26 @@ mod tests {
|
|||
world.spawn(A).flush();
|
||||
}
|
||||
|
||||
// Regression test for https://github.com/bevyengine/bevy/issues/14961
|
||||
#[test]
|
||||
fn observer_despawn_archetype_flags() {
|
||||
let mut world = World::new();
|
||||
world.init_resource::<R>();
|
||||
|
||||
let entity = world.spawn((A, B)).flush();
|
||||
|
||||
world.observe(|_: Trigger<OnRemove, A>, mut res: ResMut<R>| res.0 += 1);
|
||||
|
||||
let observer = world
|
||||
.observe(|_: Trigger<OnRemove, B>| panic!("Observer triggered after being despawned."))
|
||||
.flush();
|
||||
world.despawn(observer);
|
||||
|
||||
world.despawn(entity);
|
||||
|
||||
assert_eq!(1, world.resource::<R>().0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn observer_multiple_matches() {
|
||||
let mut world = World::new();
|
||||
|
|
Loading…
Reference in a new issue