bevy/release-content/migration-guides
urben1680 546711b807
Split EntityClonerBuilder in OptOut and OptIn variants (#19649)
# Objective

Further tests after #19326 showed that configuring `EntityCloner` with
required components is bug prone and the current design has several
weaknesses in it's API:

- Mixing `EntityClonerBuilder::allow` and `EntityClonerBuilder::deny`
requires extra care how to support that which has an impact on
surrounding code that has to keep edge cases in mind. This is especially
true for attempts to fix the following issues. There is no use-case
known (to me) why someone would mix those.
- A builder with `EntityClonerBuilder::allow_all` configuration tries to
support required components like `EntityClonerBuilder::deny_all` does,
but the meaning of that is conflicting with how you'd expect things to
work:
- If all components should be cloned except component `A`, do you also
want to exclude required components of `A` too? Or are these also valid
without `A` at the target entity?
- If `EntityClonerBuilder::allow_all` should ignore required components
and not add them to be filtered away, which purpose has
`EntityClonerBuilder::without_required_components` for this cloner?
- Other bugs found with the linked PR are:
- Denying `A` also denies required components of `A` even when `A` does
not exist at the source entity
- Allowing `A` also allows required components of `A` even when `A` does
not exist at the source entity
- Adding `allow_if_new` filters to the cloner faces the same issues and
require a common solution to dealing with source-archetype sensitive
cloning

Alternative to #19632 and #19635.

# Solution

`EntityClonerBuilder` is made generic and split into
`EntityClonerBuilder<OptOut>` and `EntityClonerBuilder<OptIn>`

For an overview of the changes, see the migration guide. It is generally
a good idea to start a review of that.

## Algorithm

The generic of `EntityClonerBuilder` contains the filter data that is
needed to build and clone the entity components.

As the filter needs to be borrowed mutably for the duration of the
clone, the borrow checker forced me to separate the filter value and all
other fields in `EntityCloner`. The latter are now in the
`EntityClonerConfig` struct. This caused many changed LOC, sorry.

To make reviewing easier:

1. Check the migration guide
2. Many methods of `EntityCloner` now just call identitcal
`EntityClonerConfig` methods with a mutable borrow of the filter
3. Check `EntityClonerConfig::clone_entity_internal` which changed a bit
regarding the filter usage that is now trait powered (`CloneByFilter`)
to support `OptOut`, `OptIn` and `EntityClonerFilter` (an enum combining
the first two)
4. Check `OptOut` type that no longer tracks required components but has
a `insert_mode` field
5. Check `OptIn` type that has the most logic changes

# Testing

I added a bunch of tests that cover the new logic parts and the fixed
issues.

Benchmarks are in a comment a bit below which shows ~4% to 9%
regressions, but it varied wildly for me. For example at one run the
reflection-based clonings were on-par with main while the other are not,
and redoing that swapped the situation for both.

It would be really cool if I could get some hints how to get better
benchmark results or if you could run them on your machine too.

Just be aware this is not a Performance PR but a Bugfix PR, even if I
smuggled in some more functionalities. So doing changes to
`EntityClonerBuilder` is kind of required here which might make us bite
the bullet.

---------

Co-authored-by: eugineerd <70062110+eugineerd@users.noreply.github.com>
2025-06-24 00:12:08 +00:00
..
.gitkeep
anchor_is_removed_from_sprite.md Fix Anchor component inconsistancies (#18393) 2025-05-21 15:32:04 +00:00
camera_restructure.md Split Camera.hdr out into a new component (#18873) 2025-05-26 19:24:45 +00:00
check_change_ticks.md System::check_change_tick and similar methods take CheckChangeTicks (#19600) 2025-06-13 19:24:27 +00:00
component_entry.md Rename bevy_ecs::world::Entry to ComponentEntry (#19517) 2025-06-10 01:12:40 +00:00
component-lifecycle-module.md Rename Trigger to On (#19596) 2025-06-12 18:22:33 +00:00
dragenter_includes_dragged_entity.md don't filter dragged entity out of DragEnter events (#19179) 2025-05-26 17:56:54 +00:00
entities_apis.md Remove invalid entity locations (#19433) 2025-05-31 16:34:33 +00:00
entity_cloner_builder_split.md Split EntityClonerBuilder in OptOut and OptIn variants (#19649) 2025-06-24 00:12:08 +00:00
entity_representation.md Fix new typos (#19562) 2025-06-09 22:55:14 +00:00
event_split.md Event Split: Event, EntityEvent, and BufferedEvent (#19647) 2025-06-15 16:46:34 +00:00
fullscreen_shader_resource.md Replace FULLSCREEN_SHADER_HANDLE with a FullscreenShader resource. (#19426) 2025-06-24 00:02:23 +00:00
generic-option-parameter.md Generic SystemParam impls for Option and Result (#18766) 2025-05-07 18:20:08 +00:00
interned-labels-cleanup.md Remove upcasting methods + Cleanup interned label code (#18984) 2025-05-26 15:38:12 +00:00
labeled_asset_scope_errors.md Allow returning an error from labeled_asset_scope. (#19449) 2025-06-04 00:00:32 +00:00
log-diagnostics-hash-set.md Expose LogDiagnosticsState (#19323) 2025-05-23 20:56:36 +00:00
merge_observerState_observer_single_component.md Merge ObserverState and Observer into single component (#18728) 2025-05-06 00:12:27 +00:00
observer_triggers.md Rename Trigger to On (#19596) 2025-06-12 18:22:33 +00:00
observers_may_not_be_exclusive.md Prevent exclusive systems from being used as observers (#19033) 2025-05-05 17:46:25 +00:00
overflowclipbox_default_is_now_paddingbox.md Change the default visual box for OverflowClipMargin to PaddingBox (#18935) 2025-04-30 21:00:42 +00:00
per-world-error-handler.md Per world error handler (#18810) 2025-05-19 01:35:07 +00:00
picking_location_not_component.md fix(picking): Location is not a Component anymore. (#19306) 2025-05-22 01:33:01 +00:00
pointer_target.md Provide access to the original target of entity-events in observers (#19663) 2025-06-15 20:53:25 +00:00
query_items_borrow_from_query_state.md Remove 's lifetime from WorldQuery::Fetch (#19720) 2025-06-19 00:58:21 +00:00
reflect_asset_asset_ids.md Replace UntypedHandle from ReflectAsset with impl Into<UntypedAssetId>. (#19606) 2025-06-15 16:42:54 +00:00
relationship_set_risky.md EntityWorldMut methods do not automatically overwrite Relationship components (#19601) 2025-06-22 00:22:05 +00:00
relative_cursor_position_is_object_centered.md Fix some typos (#19788) 2025-06-23 22:32:46 +00:00
remove_archetype_component_id.md Remove ArchetypeComponentId and archetype_component_access (#19143) 2025-05-27 19:04:32 +00:00
remove_archetypecomponentid.md Stop using ArchetypeComponentId in the executor (#16885) 2025-05-05 22:52:44 +00:00
remove_cosmic_text_reexports.md Remove re-exports of cosmic_text types (#19516) 2025-06-06 21:49:02 +00:00
remove_deprecated_batch_spawning.md Fix new typos (#19562) 2025-06-09 22:55:14 +00:00
remove_the_add_sub_impls_on_volume.md fix: Ensure linear volume subtraction does not go below zero (#19423) 2025-06-05 03:59:20 +00:00
rename_condition.md Rename Condition to SystemCondition` (#19328) 2025-05-22 15:50:19 +00:00
rename_pointer_events.md Rename some pointer events and components (#19574) 2025-06-10 21:57:28 +00:00
rename_spawn_gltf_material_name.md Add GltfMeshName component and Deref implementations (#19331) 2025-05-23 20:56:48 +00:00
rename_state_scoped.md Refactor state scoped events to match entities. (#19435) 2025-05-31 20:14:14 +00:00
rename_timer_paused_and_finished.md Rename Timer::finished and Timer::paused to is_finished and is_paused (#19386) 2025-05-27 22:24:18 +00:00
rename_transform_compute_matrix.md rename Transform::compute_matrix to to_matrix (#19646) 2025-06-18 05:37:25 +00:00
rename-justifytext.md Rename JustifyText to Justify (#19522) 2025-06-09 19:59:48 +00:00
replace_non_send_resources.md Make GILRS and WINIT_WINDOWS public (#19575) 2025-06-12 20:05:00 +00:00
scalar-field-on-vector-space.md Improve Bevy's double-precision story for third-party crates (#19194) 2025-06-08 02:02:47 +00:00
separate-border-colors.md separate border colors (#18682) 2025-05-26 16:57:13 +00:00
simple_executor_going_away.md deprecate SimpleExecutor (#18753) 2025-05-06 00:21:57 +00:00
specialized_ui_transform.md Specialized UI transform (#16615) 2025-06-09 19:05:49 +00:00
split-window.md Split CursorOptions off of Window (#19668) 2025-06-17 20:20:13 +00:00
state_scoped_entities_by_default.md Enable state scoped entities by default (#19354) 2025-05-26 20:26:41 +00:00
stop_storing_system_access.md Stop storing access for all systems (#19477) 2025-06-13 17:56:09 +00:00
sync_cell_utils.md refactor(utils): move SyncCell and SyncUnsafeCell to bevy_platform (#19305) 2025-05-27 04:57:26 +00:00
system_set_naming_convention.md Adopt consistent FooSystems naming convention for system sets (#18900) 2025-05-06 15:18:03 +00:00
taa_non_experimental.md Make TAA non-experimental, fixes (#18349) 2025-06-02 16:04:08 +00:00
unified_system_state_flag.md Unify system state (#19506) 2025-06-08 18:18:43 +00:00