|
1 | 1 | <!-- Entity cloning -->
|
2 | 2 | <!-- https://github.com/bevyengine/bevy/pull/16132 -->
|
| 3 | +Bevy now has first-class support for cloning entities. While it was possible to do this before using reflection and `ReflectComponent` functionality, the common implementation was slow and required registering all cloneable components. With Bevy 0.16, entity cloning is supported natively and is as simple as adding `#[derive(Clone)]` to a component to make it cloneable. |
3 | 4 |
|
4 |
| -<!-- TODO --> |
| 5 | +```rust |
| 6 | +#[derive(Component, Clone)] |
| 7 | +#[require(MagicalIngredient)] |
| 8 | +struct Potion; |
| 9 | + |
| 10 | +#[derive(Component, Default, Clone)] |
| 11 | +struct MagicalIngredient { |
| 12 | + amount: f32, |
| 13 | +} |
| 14 | + |
| 15 | +fn process_potions( |
| 16 | + input: Res<ButtonInput<KeyCode>>, |
| 17 | + mut commands: Commands, |
| 18 | + mut potions: Query<(Entity, &mut MagicalIngredient), With<Potion>>, |
| 19 | +) { |
| 20 | + // Create a new potion |
| 21 | + if input.just_pressed(KeyCode::KeyS) { |
| 22 | + commands.spawn( |
| 23 | + (Name::new("Simple Potion"), Potion) |
| 24 | + ); |
| 25 | + } |
| 26 | + // Add as much magic as we want |
| 27 | + else if input.just_pressed(KeyCode::KeyM) { |
| 28 | + for (_, mut ingredient) in potions.iter_mut() { |
| 29 | + ingredient.amount += 1.0 |
| 30 | + } |
| 31 | + } |
| 32 | + // And then duplicate all the potions! |
| 33 | + else if input.just_pressed(KeyCode::KeyD) { |
| 34 | + for (potion, _) in potions.iter() { |
| 35 | + commands.entity(potion).clone_and_spawn(); |
| 36 | + } |
| 37 | + } |
| 38 | +} |
| 39 | + |
| 40 | +``` |
| 41 | + |
| 42 | +`clone_and_spawn` spawns a new entity with all cloneable components, skipping those that can't be cloned. If your use case requires different behavior, there are more specialized methods: |
| 43 | + |
| 44 | +- `clone_components` clones components from the source entity to a specified target entity instead of spawning a new one. |
| 45 | +- `move_components` removes components from the source entity after cloning them to the target entity. |
| 46 | +- `clone_and_spawn_with` and `clone_with` allow customization of the cloning behavior by providing access to `EntityClonerBuilder` before performing the clone. |
| 47 | + |
| 48 | +`EntityClonerBuilder` can be used to configure how cloning is performed - for example, by filtering which components should be cloned, modifying how `required` components are cloned, or controlling whether entities linked by relationships should be cloned recursively. |
| 49 | + |
| 50 | +An important note: components with generic type parameters will not be cloneable by default. For these cases, you should add `#[derive(Reflect)]` and `#[reflect(Component)]` to the component and register it for the entity cloning functionality to work properly. |
| 51 | + |
| 52 | +```rust |
| 53 | +#[derive(Component, Reflect, Clone)] |
| 54 | +#[reflect(Component)] |
| 55 | +struct GenericComponent<T> { |
| 56 | + // ... |
| 57 | +} |
| 58 | + |
| 59 | +fn main(){ |
| 60 | + // ... |
| 61 | + app.register_type::<GenericComponent<i32>>; |
| 62 | + // ... |
| 63 | +} |
| 64 | +``` |
| 65 | + |
| 66 | +See documentation for `EntityCloner` if you're planing on implementing custom clone behaviors for components or need further explanation on how this works. |
0 commit comments