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] - Spawn specific entities: spawn or insert operations, refactor spawn internals, world clearing #2673

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions crates/bevy_ecs/src/system/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ impl<'w, 's> Commands<'w, 's> {
}
}

/// Returns an [EntityCommands] for the given `entity` (if it exists) or spawns one if it doesn't exist.
/// This will return [None] if the `entity` exists with a different generation.
///
/// # Note
cart marked this conversation as resolved.
Show resolved Hide resolved
/// Spawning a specific `entity` value is rarely the right choice. Most apps should favor [`Commands::spawn`].
/// This method should generally only be used for sharing entities across apps, and only when they have a
/// scheme worked out to share an ID space (which doesn't happen by default).
pub fn get_or_spawn<'a>(&'a mut self, entity: Entity) -> EntityCommands<'w, 's, 'a> {
self.add(GetOrSpawn { entity });
EntityCommands {
Expand All @@ -66,6 +73,8 @@ impl<'w, 's> Commands<'w, 's> {
}
}

/// Spawns a [Bundle] without pre-allocating an [Entity]. The [Entity] will be allocated when
/// this [Command] is applied.
pub fn spawn_and_forget(&mut self, bundle: impl Bundle) {
self.queue.push(Spawn { bundle })
}
Expand Down Expand Up @@ -152,8 +161,14 @@ impl<'w, 's> Commands<'w, 's> {
self.queue.push(SpawnBatch { bundles_iter });
}

/// For an iterator of (Entity, Bundle) pairs, inserts the Bundle into the Entity,
/// if the entity exists, and spawns the entity with the Bundle if it does not exist.
/// For a given batch of ([Entity], [Bundle]) pairs, either spawns each [Entity] with the given
/// bundle (if the entity does not exist), or inserts the [Bundle] (if the entity already exists).
/// This is faster than doing equivalent operations one-by-one.
///
/// # Note
/// Spawning a specific `entity` value is rarely the right choice. Most apps should use [`Commands::spawn_batch`].
/// This method should generally only be used for sharing entities across apps, and only when they have a scheme
/// worked out to share an ID space (which doesn't happen by default).
pub fn insert_or_spawn_batch<I, B>(&mut self, bundles_iter: I)
where
I: IntoIterator + Send + Sync + 'static,
Expand Down
31 changes: 29 additions & 2 deletions crates/bevy_ecs/src/world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,13 @@ impl World {
self.get_entity_mut(entity).expect("Entity does not exist")
}

/// Returns an EntityMut for an existing entity or creates one if it doesn't exist.
/// This will return `None` if the entity exists with a different generation.
/// Returns an [EntityMut] for the given `entity` (if it exists) or spawns one if it doesn't exist.
/// This will return [None] if the `entity` exists with a different generation.
///
/// # Note
/// Spawning a specific `entity` value is rarely the right choice. Most apps should favor [`World::spawn`].
/// This method should generally only be used for sharing entities across apps, and only when they have a
/// scheme worked out to share an ID space (which doesn't happen by default).
#[inline]
pub fn get_or_spawn(&mut self, entity: Entity) -> Option<EntityMut> {
self.flush();
Expand Down Expand Up @@ -698,6 +703,28 @@ impl World {
self.get_non_send_unchecked_mut_with_id(component_id)
}

/// For a given batch of ([Entity], [Bundle]) pairs, either spawns each [Entity] with the given
/// bundle (if the entity does not exist), or inserts the [Bundle] (if the entity already exists).
/// This is faster than doing equivalent operations one-by-one.
///
/// # Note
/// Spawning a specific `entity` value is rarely the right choice. Most apps should use [`World::spawn_batch`].
/// This method should generally only be used for sharing entities across apps, and only when they have a scheme
/// worked out to share an ID space (which doesn't happen by default).
///
/// ```
/// use bevy_ecs::{entity::Entity, world::World};
///
/// let mut world = World::new();
/// let e0 = world.spawn().id();
/// let e1 = world.spawn().id();
/// world.insert_or_spawn_batch(vec![
/// (e0, ("a", 0.0)), // the first entity
/// (e1, ("b", 1.0)), // the second entity
/// ]);
///
/// assert_eq!(world.get::<f64>(e0), Some(&0.0));
/// ```
pub fn insert_or_spawn_batch<I, B>(&mut self, iter: I)
where
I: IntoIterator,
Expand Down