From 185a6decdabc921c6fbd01938a25475b1621c31d Mon Sep 17 00:00:00 2001 From: Elliott Pierce Date: Fri, 20 Jun 2025 22:28:18 -0400 Subject: [PATCH] better construct/destruct vs spawn/despawn docs --- crates/bevy_ecs/src/world/entity_ref.rs | 7 ++++--- crates/bevy_ecs/src/world/mod.rs | 24 +++++++++++++++++++++++- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/crates/bevy_ecs/src/world/entity_ref.rs b/crates/bevy_ecs/src/world/entity_ref.rs index 917e737487..0949c7863c 100644 --- a/crates/bevy_ecs/src/world/entity_ref.rs +++ b/crates/bevy_ecs/src/world/entity_ref.rs @@ -2357,8 +2357,8 @@ impl<'w> EntityWorldMut<'w> { } /// Constructs the entity. - /// If the entity has not been constructed or has been destructed, the can construct it. - /// See [`World::construct`] for details. + /// If this entity has not yet been constructed or has been since destructed, this can construct it. + /// See [`World::construct`] for details and usage examples. #[track_caller] pub fn construct(&mut self, bundle: B) -> Result<&mut Self, ConstructionError> { let Self { @@ -2387,6 +2387,7 @@ impl<'w> EntityWorldMut<'w> { /// Destructs the entity, without releasing it. /// This may be later [`constructed`](Self::construct). /// Note that this still increases the generation to differentiate different constructions of the same row. + /// See [`World::destruct`] for details and usage examples. #[track_caller] pub fn destruct(&mut self) -> &mut Self { self.destruct_with_caller(MaybeLocation::caller()); @@ -2394,7 +2395,7 @@ impl<'w> EntityWorldMut<'w> { self } - /// Returns whether or not it really did need to destruct. + /// This destructs this entity if it is currently constructed, storing the new [`EntityGeneration`] in [`Self::entity`]. pub(crate) fn destruct_with_caller(&mut self, caller: MaybeLocation) { // setup let Some(location) = self.location else { diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index caf0dfc55d..d86c89960c 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1087,11 +1087,24 @@ impl World { /// /// If it succeeds, this declares the entity to have this bundle. /// - /// Note: It is possible to construct an `entity` that has not been allocated yet; + /// In general, you should prefer [`spawn`](Self::spawn). + /// Spawn internally calls this method, but it takes care of finding a suitable [`Entity`] for you. + /// This is made available for advanced use, of which some examples are listed later. + /// + /// # Risk + /// + /// It is possible to construct an `entity` that has not been allocated yet; /// however, doing so is currently a bad idea as the allocator may hand out this entity row in the future, assuming it to be not constructed. /// This would cause a panic. /// /// Manual construction is a powerful tool, but must be used carefully. + /// + /// # Example + /// + /// Currently, this is primarily used to construct entities that come from [`spawn_null`](Self::spawn_null). + /// See that for an example. + /// More generally, manually constructing and [`destruct`](Self::destruct)ing entities allows you to skip bevy's default entity allocator. + /// This is useful if you want to enforce properties about the [`EntityRow`](crate::entity::EntityRow)s of a group of entities, make a custom allocator, etc. #[track_caller] pub fn construct( &mut self, @@ -1519,6 +1532,7 @@ impl World { } /// Performs [`try_destruct`](Self::try_destruct), warning on errors. + /// See that method for more information. #[track_caller] #[inline] pub fn destruct(&mut self, entity: Entity) -> Option> { @@ -1535,6 +1549,7 @@ impl World { /// [`Components`](Component). /// The *only* difference between destructing and despawning an entity is that destructing does not release the `entity` to be reused. /// It is up to the caller to either re-construct or fully despawn the `entity`; otherwise, the [`EntityRow`](crate::entity::EntityRow) will not be able to be reused. + /// In general, [`despawn`](Self::despawn) should be used instead, which automatically allows the row to be reused. /// /// Returns an [`EntityDestructError`] if the entity does not exist. /// @@ -1542,6 +1557,13 @@ impl World { /// /// This will also *despawn* the entities in any [`RelationshipTarget`](crate::relationship::RelationshipTarget) that is configured /// to despawn descendants. For example, this will recursively despawn [`Children`](crate::hierarchy::Children). + /// + /// # Example + /// + /// There is no simple example in which this would be practical, but one use for this is a custom entity allocator. + /// Despawning internally calls this and frees the entity id to bevy's default entity allocator. + /// The same principal can be used to create custom allocators with additional properties. + /// For example, this could be used to make an allocator that yields groups of consecutive [`EntityRow`](crate::entity::EntityRow)s, etc. #[track_caller] #[inline] pub fn try_destruct(