Of the two ways of thinking about Required Components as discussed here, I am using Required Components to "include" other components at insertion, not to constantly require them. This seems to be the intent from the docs as well:
Components can specify Required Components. If some Component A requires Component B, then when A is inserted, B will also be initialized and inserted (if it was not manually specified).
But I've found that the required Component B is also inserted when A is not being inserted. What I did is this:
- Insert
(A,B) as my_entity
- Remove
B from my_entity
- Perform
my_entity_commands.insert_if_new(A)
- Observe that, surprisingly, there is now a
B, although the A was not inserted.
Bevy version and features
Bevy version: 0.18.1, default features
# rustup -V
info: The currently active `rustc` version is `rustc 1.94.0-nightly (31010ca61 2025-12-16)`
What you did
I'll attach the repro project files with a minimal test. Run cargo test to see it fail.
Repro.zip
What went wrong
I was expecting insert_if_new to have no effect if the provided Component is not new. Something like "it checks whether the Component exists on that Entity. If yes, it does nothing. If no, it inserts it and triggers hooks and required components appropriately".
What it does instead is it enforces the required Components even if the Component itself was already present. This is a logic bug in my code, where I have a Marker Component that should initially be present (achieved by #[require(ing it) and eventually gets removed.
Possible Workaround
I suspect I could work around this bug by using Component Hooks to perform the check myself. I did not check, but I would be surprised if the insertion hook would also be called without any insertion happening. When/if I try this, I will update this post.
Reproduction Test Case
mod repro3 {
use bevy::prelude::*;
#[derive(Component, Reflect, Default)]
#[reflect(Component)]
pub struct RequiredMarkerComponent {}
#[derive(Reflect, Component, Default)]
#[reflect(Component)]
#[require(RequiredMarkerComponent)]
pub(crate) struct MainComponent {}
#[test]
fn simple_insert_if_new_test() {
// Create an empty world
let mut world = World::new();
// Spawn a new entity, with a Component and another, required, Component.
let mut my_entity = world.spawn(MainComponent::default());
// Remove the required Component.
my_entity.remove::<RequiredMarkerComponent>();
// Be very certain that we did remove the Marker Component
assert!(my_entity.get::<RequiredMarkerComponent>().is_none());
// Be very certain that we did not remove the other Component.
my_entity
.get::<MainComponent>()
.expect("This component should still exist...");
// Add the Component only if new (it's not new. this should do nothing.)
my_entity.insert_if_new(MainComponent::default());
match my_entity.get::<RequiredMarkerComponent>() {
None => {
// All good.
}
Some(_) => panic!(
"This RequiredMarkerComponent should not exist, because the MainComponent was not new."
),
}
}
}
Is It a Bug?
I am of the opinion that this behavior is very unexpected and not as documented, but I see the possibility for the viewpoint that it is working as-intended too... If the consensus is actually that this is fine, I think it should still be documented clearer in the docs of insert_if_new() and Required Components.
Of the two ways of thinking about Required Components as discussed here, I am using Required Components to "include" other components at insertion, not to constantly require them. This seems to be the intent from the docs as well:
But I've found that the required Component
Bis also inserted whenAis not being inserted. What I did is this:(A,B)asmy_entityBfrommy_entitymy_entity_commands.insert_if_new(A)B, although theAwas not inserted.Bevy version and features
Bevy version:
0.18.1, default featuresWhat you did
I'll attach the repro project files with a minimal test. Run
cargo testto see it fail.Repro.zip
What went wrong
I was expecting insert_if_new to have no effect if the provided Component is not new. Something like "it checks whether the Component exists on that Entity. If yes, it does nothing. If no, it inserts it and triggers hooks and required components appropriately".
What it does instead is it enforces the required Components even if the Component itself was already present. This is a logic bug in my code, where I have a Marker Component that should initially be present (achieved by
#[require(ing it) and eventually gets removed.Possible Workaround
I suspect I could work around this bug by using Component Hooks to perform the check myself. I did not check, but I would be surprised if the insertion hook would also be called without any insertion happening. When/if I try this, I will update this post.
Reproduction Test Case
Is It a Bug?
I am of the opinion that this behavior is very unexpected and not as documented, but I see the possibility for the viewpoint that it is working as-intended too... If the consensus is actually that this is fine, I think it should still be documented clearer in the docs of
insert_if_new()and Required Components.