Skip to content

EntityCloner has no concept of required components after configuration which may have surprising effects depending on the target archetype #19324

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

Open
urben1680 opened this issue May 21, 2025 · 0 comments · May be fixed by #19326
Labels
C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled

Comments

@urben1680
Copy link
Contributor

urben1680 commented May 21, 2025

Bevy version

0.16

What you did

#[derive(Component, PartialEq, Debug, Default, Copy, Clone)]
#[require(Required)]
struct Explicit(u8);

#[derive(Component, PartialEq, Debug, Default, Copy, Clone)]
struct Required(u8);

let mut world = World::new();
let target = world.spawn(Required(10)).id();
world.spawn((Explicit(20), Required(20))).clone_components::<Explicit>(target);
assert_eq!(world.get(target), Some(&Required(10)));

What went wrong

The assertion fails, the target now contains Required(20).
This is surprising, since I did not explicitly ask for that to be cloned and it should not happen if the target already contains it.

The issue here is that EntityCloner has no information of the target entity at the time of configuration. You can either tell it to move Explicit with or without Required, the latter by using EntityCloner::without_required_components. This is not comfortable because you would have to check the target archetype first to pick the correct configuration. There is no automatism.

To make the issue more clear, these are the possible scenarios if I wanted to clone Explicit with or without Required:

use without_required_components target before target after
no Explicit(10), Required(10) Explicit(20), Required(20)
no Required(10) Explicit(20), Required(20)
no Explicit(20), Required(20)
yes Explicit(10), Required(10) Explicit(20), Required(10)
yes Required(10) Explicit(20), Required(10)
yes Explicit(20), Required(0)

As you can see, if you only want to clone Required if it does not exist at the target yet, like insert behaves where it only constructs a default Required when needed, you need to check the target archetype first and pick the correct cloner configuration based on that.

This makes this API uncomfortable.

A proper fix, if we want to keep EntityCloner agnostic to the target archetype (since it may be used on multiple source/target pairs as I saw in the code), it should at least know which ComponentId were given as explicit or implicit.

@urben1680 urben1680 added C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled labels May 21, 2025
@urben1680 urben1680 changed the title EntityCloner has no concept of required components which may have surprising effects EntityCloner has no concept of required components after configuration which may have surprising effects depending on the target archetype May 21, 2025
@eugineerd eugineerd linked a pull request May 21, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant