bevy_ecs/bundle/mod.rs
1#![expect(
2 unsafe_op_in_unsafe_fn,
3 reason = "See #11590. To be removed once all applicable unsafe code has an unsafe block with a safety comment."
4)]
5
6//! Types for handling [`Bundle`]s.
7//!
8//! This module contains the [`Bundle`] trait and some other helper types.
9
10mod impls;
11mod info;
12mod insert;
13mod remove;
14mod spawner;
15#[cfg(test)]
16mod tests;
17mod writer;
18
19pub(crate) use insert::BundleInserter;
20pub(crate) use remove::BundleRemover;
21pub(crate) use spawner::BundleSpawner;
22
23use bevy_ptr::MovingPtr;
24use core::mem::MaybeUninit;
25pub use info::*;
26pub use writer::*;
27
28/// Derive the [`Bundle`] trait
29///
30/// You can apply this derive macro to structs that are
31/// composed of [`Component`](crate::component::Component)s or
32/// other [`Bundle`]s.
33///
34/// ## Attributes
35///
36/// Sometimes parts of the Bundle should not be inserted.
37/// Those can be marked with `#[bundle(ignore)]`, and they will be skipped.
38/// In that case, the field needs to implement [`Default`] unless you also ignore
39/// the [`BundleFromComponents`] implementation.
40///
41/// ```rust
42/// # use bevy_ecs::prelude::{Component, Bundle};
43/// # #[derive(Component)]
44/// # struct Hitpoint;
45/// #
46/// #[derive(Bundle)]
47/// struct HitpointMarker {
48/// hitpoints: Hitpoint,
49///
50/// #[bundle(ignore)]
51/// creator: Option<String>
52/// }
53/// ```
54///
55/// Some fields may be bundles that do not implement
56/// [`BundleFromComponents`]. This happens for bundles that cannot be extracted.
57/// For example with [`SpawnRelatedBundle`](bevy_ecs::spawn::SpawnRelatedBundle), see below for an
58/// example usage.
59/// In those cases you can either ignore it as above,
60/// or you can opt out the whole Struct by marking it as ignored with
61/// `#[bundle(ignore_from_components)]`.
62///
63/// ```rust
64/// # use bevy_ecs::prelude::{Component, Bundle, ChildOf, Spawn};
65/// # #[derive(Component)]
66/// # struct Hitpoint;
67/// # #[derive(Component)]
68/// # struct Marker;
69/// #
70/// use bevy_ecs::spawn::SpawnRelatedBundle;
71///
72/// #[derive(Bundle)]
73/// #[bundle(ignore_from_components)]
74/// struct HitpointMarker {
75/// hitpoints: Hitpoint,
76/// related_spawner: SpawnRelatedBundle<ChildOf, Spawn<Marker>>,
77/// }
78/// ```
79pub use bevy_ecs_macros::Bundle;
80
81use crate::{
82 component::{ComponentId, Components, ComponentsRegistrator, StorageType},
83 world::EntityWorldMut,
84};
85use bevy_ptr::OwningPtr;
86
87/// The `Bundle` trait enables insertion and removal of [`Component`]s from an entity.
88///
89/// Implementers of the `Bundle` trait are called 'bundles'.
90///
91/// Each bundle represents a static set of [`Component`] types.
92/// Currently, bundles can only contain one of each [`Component`], and will
93/// panic once initialized if this is not met.
94///
95/// ## Insertion
96///
97/// The primary use for bundles is to add a useful collection of components to an entity.
98///
99/// Adding a value of bundle to an entity will add the components from the set it
100/// represents to the entity.
101/// The values of these components are taken from the bundle.
102/// If an entity already had one of these components, the entity's original component value
103/// will be overwritten.
104///
105/// Importantly, bundles are only their constituent set of components.
106/// You **should not** use bundles as a unit of behavior.
107/// The behavior of your app can only be considered in terms of components, as systems,
108/// which drive the behavior of a `bevy` application, operate on combinations of
109/// components.
110///
111/// This rule is also important because multiple bundles may contain the same component type,
112/// calculated in different ways — adding both of these bundles to one entity
113/// would create incoherent behavior.
114/// This would be unexpected if bundles were treated as an abstraction boundary, as
115/// the abstraction would be unmaintainable for these cases.
116///
117/// For this reason, there is intentionally no [`Query`] to match whether an entity
118/// contains the components of a bundle.
119/// Queries should instead only select the components they logically operate on.
120///
121/// ## Removal
122///
123/// Bundles are also used when removing components from an entity.
124///
125/// Removing a bundle from an entity will remove any of its components attached
126/// to the entity from the entity.
127/// That is, if the entity does not have all the components of the bundle, those
128/// which are present will be removed.
129///
130/// # Implementers
131///
132/// Every type which implements [`Component`] also implements `Bundle`, since
133/// [`Component`] types can be added to or removed from an entity.
134///
135/// Additionally, [Tuples](`tuple`) of bundles are also [`Bundle`] (with up to 15 bundles).
136/// These bundles contain the items of the 'inner' bundles.
137/// This is a convenient shorthand which is primarily used when spawning entities.
138///
139/// [`unit`], otherwise known as [`()`](`unit`), is a [`Bundle`] containing no components (since it
140/// can also be considered as the empty tuple).
141/// This can be useful for spawning large numbers of empty entities using
142/// [`World::spawn_batch`](crate::world::World::spawn_batch).
143///
144/// Tuple bundles can be nested, which can be used to create an anonymous bundle with more than
145/// 15 items.
146/// However, in most cases where this is required, the derive macro [`derive@Bundle`] should be
147/// used instead.
148/// The derived `Bundle` implementation contains the items of its fields, which all must
149/// implement `Bundle`.
150/// As explained above, this includes any [`Component`] type, and other derived bundles.
151///
152/// If you want to add `PhantomData` to your `Bundle` you have to mark it with `#[bundle(ignore)]`.
153/// ```
154/// # use std::marker::PhantomData;
155/// use bevy_ecs::{component::Component, bundle::Bundle};
156///
157/// #[derive(Component)]
158/// struct XPosition(i32);
159/// #[derive(Component)]
160/// struct YPosition(i32);
161///
162/// #[derive(Bundle)]
163/// struct PositionBundle {
164/// // A bundle can contain components
165/// x: XPosition,
166/// y: YPosition,
167/// }
168///
169/// // You have to implement `Default` for ignored field types in bundle structs.
170/// #[derive(Default)]
171/// struct Other(f32);
172///
173/// #[derive(Bundle)]
174/// struct NamedPointBundle<T: Send + Sync + 'static> {
175/// // Or other bundles
176/// a: PositionBundle,
177/// // In addition to more components
178/// z: PointName,
179///
180/// // when you need to use `PhantomData` you have to mark it as ignored
181/// #[bundle(ignore)]
182/// _phantom_data: PhantomData<T>
183/// }
184///
185/// #[derive(Component)]
186/// struct PointName(String);
187/// ```
188///
189/// # Safety
190///
191/// Manual implementations of this trait are unsupported.
192/// That is, there is no safe way to implement this trait, and you must not do so.
193/// If you want a type to implement [`Bundle`], you must use [`derive@Bundle`](derive@Bundle).
194///
195/// [`Component`]: crate::component::Component
196/// [`Query`]: crate::system::Query
197// Some safety points:
198// - [`Bundle::component_ids`] must return the [`ComponentId`] for each component type in the
199// bundle, in the _exact_ order that [`DynamicBundle::get_components`] is called.
200// - [`Bundle::from_components`] must call `func` exactly once for each [`ComponentId`] returned by
201// [`Bundle::component_ids`].
202#[diagnostic::on_unimplemented(
203 message = "`{Self}` is not a `Bundle`",
204 label = "invalid `Bundle`",
205 note = "consider annotating `{Self}` with `#[derive(Component)]` or `#[derive(Bundle)]`"
206)]
207pub unsafe trait Bundle: DynamicBundle + Send + Sync + 'static {
208 /// Gets this [`Bundle`]'s component ids, in the order of this bundle's [`Component`]s
209 /// This will register the component if it doesn't exist.
210 #[doc(hidden)]
211 fn component_ids(
212 components: &mut ComponentsRegistrator,
213 ) -> impl Iterator<Item = ComponentId> + use<Self>;
214
215 /// Return a iterator over this [`Bundle`]'s component ids. This will be [`None`] if the component has not been registered.
216 fn get_component_ids(components: &Components) -> impl Iterator<Item = Option<ComponentId>>;
217}
218
219/// Creates a [`Bundle`] by taking it from internal storage.
220///
221/// # Safety
222///
223/// Manual implementations of this trait are unsupported.
224/// That is, there is no safe way to implement this trait, and you must not do so.
225/// If you want a type to implement [`Bundle`], you must use [`derive@Bundle`](derive@Bundle).
226///
227/// [`Query`]: crate::system::Query
228// Some safety points:
229// - [`Bundle::component_ids`] must return the [`ComponentId`] for each component type in the
230// bundle, in the _exact_ order that [`DynamicBundle::get_components`] is called.
231// - [`Bundle::from_components`] must call `func` exactly once for each [`ComponentId`] returned by
232// [`Bundle::component_ids`].
233pub unsafe trait BundleFromComponents {
234 /// Calls `func`, which should return data for each component in the bundle, in the order of
235 /// this bundle's [`Component`]s
236 ///
237 /// # Safety
238 /// Caller must return data for each component in the bundle, in the order of this bundle's
239 /// [`Component`]s
240 #[doc(hidden)]
241 unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self
242 where
243 // Ensure that the `OwningPtr` is used correctly
244 F: for<'a> FnMut(&'a mut T) -> OwningPtr<'a>,
245 Self: Sized;
246}
247
248/// The parts from [`Bundle`] that don't require statically knowing the components of the bundle.
249pub trait DynamicBundle: Sized {
250 /// An operation on the entity that happens _after_ inserting this bundle.
251 type Effect;
252
253 /// Moves the components out of the bundle.
254 ///
255 /// # Safety
256 /// For callers:
257 /// - Must be called exactly once before `apply_effect`
258 /// - The `StorageType` argument passed into `func` must be correct for the component being fetched.
259 /// - `apply_effect` must be called exactly once after this has been called if `Effect: !NoBundleEffect`
260 ///
261 /// For implementors:
262 /// - Implementors of this function must convert `ptr` into pointers to individual components stored within
263 /// `Self` and call `func` on each of them in exactly the same order as [`Bundle::get_component_ids`] and
264 /// [`BundleFromComponents::from_components`].
265 /// - If any part of `ptr` is to be accessed in `apply_effect`, it must *not* be dropped at any point in this
266 /// function. Calling [`bevy_ptr::deconstruct_moving_ptr`] in this function automatically ensures this.
267 ///
268 /// [`Component`]: crate::component::Component
269 // This function explicitly uses `MovingPtr` to avoid potentially large stack copies of the bundle
270 // when inserting into ECS storage. See https://github.com/bevyengine/bevy/issues/20571 for more
271 // information.
272 unsafe fn get_components(
273 ptr: MovingPtr<'_, Self>,
274 func: &mut impl FnMut(StorageType, OwningPtr<'_>),
275 );
276
277 /// Applies the after-effects of spawning this bundle.
278 ///
279 /// This is applied after all residual changes to the [`World`], including flushing the internal command
280 /// queue.
281 ///
282 /// # Safety
283 /// For callers:
284 /// - Must be called exactly once after `get_components` has been called.
285 /// - `ptr` must point to the instance of `Self` that `get_components` was called on,
286 /// all of fields that were moved out of in `get_components` will not be valid anymore.
287 ///
288 /// For implementors:
289 /// - If any part of `ptr` is to be accessed in this function, it must *not* be dropped at any point in
290 /// `get_components`. Calling [`bevy_ptr::deconstruct_moving_ptr`] in `get_components` automatically
291 /// ensures this is the case.
292 /// - Note that `entity` may already have been despawned by hooks or observers at this point,
293 /// so check [`EntityWorldMut::is_spawned`] before trusting it.
294 ///
295 /// [`World`]: crate::world::World
296 // This function explicitly uses `MovingPtr` to avoid potentially large stack copies of the bundle
297 // when inserting into ECS storage. See https://github.com/bevyengine/bevy/issues/20571 for more
298 // information.
299 unsafe fn apply_effect(ptr: MovingPtr<'_, MaybeUninit<Self>>, entity: &mut EntityWorldMut);
300}
301
302/// A trait implemented for [`DynamicBundle::Effect`] implementations that do nothing. This is used as a type constraint for
303/// [`Bundle`] APIs that do not / cannot run [`DynamicBundle::Effect`], such as "batch spawn" APIs.
304pub trait NoBundleEffect {}