Skip to content

Commit 20f6262

Browse files
set spawn_despawn on the correct entity when despawning (#21364)
# Objective Fixes #21293 Fixes #17314 to ensure that this is tested correctly. ## Solution when despawning an entity, previously the swapped in (archetype) or moved in entity (table) (which both require extra bookkeeping to update archetype or table rows) were marked as `spawned_or_despawned` by the location and tick that the to-be-removed entity was meant to be marked, while the to-be-removed entity wasn't marked. As pointed out by @akimakinai in [#19047](#19047), I've re-added the correct `mark_spawn_despawn` call to `despawn_with_caller`. ## Testing I've added a test `spawned_after_swap_remove` that ensures that despawning an entity by swapping doesn't effect other entities `spawned_or_despawned` location, and that it does effect the despawned entity's index's `spawned_or_despawned` location. Co-Authored By: [email protected] --------- Co-authored-by: WaterWhisperer <[email protected]>
1 parent cd44b30 commit 20f6262

File tree

2 files changed

+32
-7
lines changed

2 files changed

+32
-7
lines changed

crates/bevy_ecs/src/world/entity_ref.rs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2670,9 +2670,6 @@ impl<'w> EntityWorldMut<'w> {
26702670
table_row: swapped_location.table_row,
26712671
}),
26722672
);
2673-
world
2674-
.entities
2675-
.mark_spawn_despawn(swapped_entity.index(), caller, change_tick);
26762673
}
26772674
}
26782675
table_row = remove_result.table_row;
@@ -2702,14 +2699,18 @@ impl<'w> EntityWorldMut<'w> {
27022699
table_row,
27032700
}),
27042701
);
2705-
world
2706-
.entities
2707-
.mark_spawn_despawn(moved_entity.index(), caller, change_tick);
27082702
}
27092703
world.archetypes[moved_location.archetype_id]
27102704
.set_entity_table_row(moved_location.archetype_row, table_row);
27112705
}
27122706
world.flush();
2707+
2708+
// SAFETY: `self.entity` is a valid entity index
2709+
unsafe {
2710+
world
2711+
.entities
2712+
.mark_spawn_despawn(self.entity.index(), caller, change_tick);
2713+
}
27132714
}
27142715

27152716
/// Ensures any commands triggered by the actions of Self are applied, equivalent to [`World::flush`]
@@ -6740,4 +6741,28 @@ mod tests {
67406741
}
67416742
);
67426743
}
6744+
6745+
#[test]
6746+
fn spawned_after_swap_remove() {
6747+
#[derive(Component)]
6748+
struct Marker;
6749+
6750+
let mut world = World::new();
6751+
let id1 = world.spawn(Marker).id();
6752+
let _id2 = world.spawn(Marker).id();
6753+
let id3 = world.spawn(Marker).id();
6754+
6755+
#[cfg(feature = "track_location")]
6756+
let e1_spawned = world.entity(id1).spawned_by();
6757+
6758+
let spawn = world.entity(id3).spawned_by();
6759+
world.entity_mut(id1).despawn();
6760+
#[cfg(feature = "track_location")]
6761+
let e1_despawned = world.entities().entity_get_spawned_or_despawned_by(id1);
6762+
#[cfg(feature = "track_location")]
6763+
assert_ne!(e1_spawned.map(Some), e1_despawned);
6764+
6765+
let spawn_after = world.entity(id3).spawned_by();
6766+
assert_eq!(spawn, spawn_after);
6767+
}
67436768
}

tools/ci/src/commands/test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ impl Prepare for TestCommand {
2020
PreparedCommand::new::<Self>(
2121
cmd!(
2222
sh,
23-
"cargo test --workspace --lib --bins --tests {no_fail_fast...} {jobs_ref...} -- {test_threads_ref...}"
23+
"cargo test --workspace --lib --bins --tests --features bevy_ecs/track_location {no_fail_fast...} {jobs_ref...} -- {test_threads_ref...}"
2424
),
2525
"Please fix failing tests in output above.",
2626
),

0 commit comments

Comments
 (0)