Skip to content

More state driven entity disabling components#24351

Open
izarma wants to merge 15 commits into
bevyengine:mainfrom
izarma:main
Open

More state driven entity disabling components#24351
izarma wants to merge 15 commits into
bevyengine:mainfrom
izarma:main

Conversation

@izarma

@izarma izarma commented May 19, 2026

Copy link
Copy Markdown

Objective

Solution

For each new state driven disabling component

  • Systems that read StateTransitionEvent<S> Message and update the Entity on state transitions.
  • Observers On<Insert, Component> to sync when component is inserted. So user does not have to manually supply the Disabled component when the Entity spawns Disabled.
  • Observer On<Remove, Component> to remove DisabledControl
  • new propagation functions. Disable component removal stops at any child carrying DisabledControl and its addition only stops at DisabledControl::Independent.
  • require DisabledControl::Independent so their children are independent.

The children entities that only want Disabling to propagate can use DisabledControl::InheritDisable

Testing

  • Did you test these changes? If so, how? - unit tests with cargo test

  • Are there any parts that need more testing? Combining more than one of these components on a single entity.

  • How can other people (reviewers) test your changes? Is there anything specific they need to know?
    Insert any of the new components to an entity, the Disabled Component can be added or removed based on the current state at insertion and then any further state changes(specifically on state enters) - which can be enabled for querying by using Allow<Disabled>
    Also can try spawning children entities to test propagation of Disabling

  • If relevant, what platforms did you test these changes on, and are there any important ones you can't test? - Windows11


@github-actions

Copy link
Copy Markdown
Contributor

Welcome, new contributor!

Please make sure you've read our contributing guide, as well as our policy regarding AI usage, and we look forward to reviewing your pull request shortly ✨

@izarma izarma marked this pull request as draft May 19, 2026 11:55
@alice-i-cecile alice-i-cecile added C-Feature A new feature, making something new possible S-Needs-Review Needs reviewer attention (from anyone!) to move forward A-States App-level states machines labels May 21, 2026

@ncthbrt ncthbrt left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The recursive removal of Disable on children makes me uneasy. I'm not super read up on how the Disabled state is normally propagated to children but it feels like a child should be able to remain disabled if it was already disabled prior to entering or leaving the state (depending on what was specified).

Comment thread crates/bevy_state/src/state_scoped.rs Outdated
if transition.entered.as_ref() == Some(&enabled_in.0) {
commands
.entity(entity)
.remove_recursive::<Children, Disabled>();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing Disabled from Children feels a little iffy. Is it not possible to have an enabled parent but a disabled child?

@izarma izarma Jul 2, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it alright to mark this as resolved?

@amtep

amtep commented May 22, 2026

Copy link
Copy Markdown
Contributor

Perhaps define the logic such that a child with its own DisabledIf / DisabledIn kind of component is skipped?

Might get unintuitive though.

We might have to add a ManuallyDisabed component or something, to cover all cases.

@izarma izarma changed the title More state driven entity disabling components (WIP) More state driven entity disabling components Jun 11, 2026
@izarma izarma changed the title (WIP) More state driven entity disabling components More state driven entity disabling components Jun 21, 2026
@izarma izarma requested a review from ncthbrt June 21, 2026 15:15
@izarma

izarma commented Jun 21, 2026

Copy link
Copy Markdown
Author

The recursive removal of Disable on children makes me uneasy. I'm not super read up on how the Disabled state is normally propagated to children but it feels like a child should be able to remain disabled if it was already disabled prior to entering or leaving the state (depending on what was specified).

I have added a new OwnsDisabled component that can be used to shield the Disable propagation. Would love to know if this is alright?

@ncthbrt

ncthbrt commented Jun 21, 2026

Copy link
Copy Markdown

Hmmmm... I'm wondering if the design needs a rethink.

The behaviour isn't quite what I'd expect.

I wanted children to be disabled when their parent was disabled, as this still makes a lot of sense but crucially, when the parent is re-enabled, it shouldn't automatically remove disabled from entities that were disabled through other means.

One potential design, though might be a bit contentious, would be a component that tracks how many times children have been disabled through the mechanism of their parents being disabled.

An alternative design would perhaps be a DisabledSelf component that would shield itself and its children from being re-enabled when the parent is reactivated. This is very similar to your current implementation, however it would still allow the Disabled state to correctly propagate to all children.

@izarma

izarma commented Jun 28, 2026

Copy link
Copy Markdown
Author

Hmmmm... I'm wondering if the design needs a rethink.

The behaviour isn't quite what I'd expect.

I wanted children to be disabled when their parent was disabled, as this still makes a lot of sense but crucially, when the parent is re-enabled, it shouldn't automatically remove disabled from entities that were disabled through other means.

One potential design, though might be a bit contentious, would be a component that tracks how many times children have been disabled through the mechanism of their parents being disabled.

An alternative design would perhaps be a DisabledSelf component that would shield itself and its children from being re-enabled when the parent is reactivated. This is very similar to your current implementation, however it would still allow the Disabled state to correctly propagate to all children.

I went with DisabledSelf here. Would love a re-review :)

@izarma izarma marked this pull request as ready for review June 28, 2026 18:08
@ncthbrt

ncthbrt commented Jun 29, 2026

Copy link
Copy Markdown

If you're not going to rename it to disabled self, I'd suggest that you call it OwnsEnabled as that is more accurate to the behaviour of what the component does. Otherwise if you choose to rename it to DisabledSelf or similar, you will probably need to add an observer that adds the disabled state when the DisabledSelf component is added

@copygirl

Copy link
Copy Markdown
Contributor

Are there similarities to InheritedVisibility? Perhaps a similar approach, functionality and name would help not confuse users. (If you understand one, you understand the other.)

@izarma

izarma commented Jun 30, 2026

Copy link
Copy Markdown
Author

Are there similarities to InheritedVisibility? Perhaps a similar approach, functionality and name would help not confuse users. (If you understand one, you understand the other.)

the functionality we have is kinda different - since there is a case where we want only to propagate the insertion of Disabled and not its removal. However - I went with a similar enum for our case here.

pub enum DisabledControl {
    #[default]
    Independent,
    InheritDisable,
}

Also this should be better naming for what we have right? @ncthbrt

I'd love any more feedback in this regard as well I had tried exploring to use PropagateStop + PropagateOver for a similar functionality to DisabledControl::Independent but since it comes from bevy_app that is an optional dependency of bevy_states i didn't.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-States App-level states machines C-Feature A new feature, making something new possible S-Needs-Review Needs reviewer attention (from anyone!) to move forward

Projects

None yet

Development

Successfully merging this pull request may close these issues.

More state driven entity disabling components

5 participants