-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
enable same state transitions #19363
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
enable same state transitions #19363
Conversation
|
How does this approach interact with computed and sub states? |
|
Labeling as contentious given that all previous work in this regard was contested |
|
We might want a working group for My take on this particular feature though is that it's so basic and crucial that it's worth introducing technical debt to get it in even without a redesign (obviously since I've tried to do just that in 4 separate PRs). Just need to document how it interacts with computed and sub states. |
I think it doesn't, it's only enabled when actually calling the method on This is scoped as small as I think is viable, the only extra thing in this PR is making sure that if |
|
But what So whether this is just a naming thing, or a flaw in the design, I'm not sure, but I also wondered whether you'd do this at the place you actually change the state (as in this PR), or if you do it in the definition of your states (if it's technically possible). |
What do you think of
I think it's better to do it like in this pr. If we want to go for a breaking change, I would probably make this PR the default, and change the current |
What's your thinking? Is it because you specifically want per-call site control over this? The reason I mentioned it is that when coming up with a name and design for the per-call site version (this PR), it seems hard to come up with a concise and expressive design whereas when it's defined at the type level, it becomes easier to express. For example, maybe it looks something like this: #[derive(States)]
enum GameState {
#[default]
MainMenu,
SettingsMenu,
InGame,
}
// Default behavior: schedules skipped for identical states.
impl StateTransitionBehavior for GameState {
fn always_run_entry_exit_transitions() -> bool { false }
}
#[derive(States)]
enum ResettingState {
#[default]
Idle,
Active,
}
// Always run transitions, even for identical states.
impl StateTransitionBehavior for ResettingState {
fn always_run_entry_exit_transitions() -> bool { true }
}
fn set_game_state(mut next_game_state: ResMut<NextState<GameState>>) {
// Standard behavior: schedules skipped if state is unchanged.
next_game_state.set(GameState::InGame);
}
fn set_resetting_state(mut next_state: ResMut<NextState<ResettingState>>) {
// Schedules always run, even if state is unchanged.
next_state.set(ResettingState::Active);
}That aside, if we're trying to do this in the next_game_state.set(GameState::InGame).with_entry_exit_transitions().apply()But it raises questions of compatibility which we'd have to decide on. If I had to pick something on the next_game_state.set_with_entry_exit(GameState::InGame); // or:
next_game_state.set_with_entry_exit_transitions(GameState::InGame); (noting that I picked Or, if you want to change next_game_state.set_without_entry_exit(GameState::InGame); // or:
next_game_state.set_without_entry_exit_transitions(GameState::InGame);If you wanted a breaking change and you want per-call site control, I think a builder pattern could work here and would be the most expressive. |
|
Not blocking: as a follow up, updating the examples to include a usage would be neat :) |
alice-i-cecile
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs a migration guide but I am convinced that this is correct at this point. It's too useful for hotpatching, which solves my main objection of "is this actually widely useful behavior".
|
It looks like your PR is a breaking change, but you didn't provide a migration guide. Please review the instructions for writing migration guides, then expand or revise the content in the migration guides directory to reflect your changes. |
2cfcb58 to
8c70da3
Compare
|
@alice-i-cecile not sure what you want in a migration guide? Existing code would continue to work exactly the same. |
|
I would like a simple note that same-state transitions now work. Many users have asked for this, and likely have workarounds in place that they can now remove. Migration guides aren't simply about "things that must be changed": they're a good place to put updated best practices, especially for things that are too small for release notes. |
janhohenheim
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not happy about the naming at all, but I believe it's better to get this in now rather than bikeshed it too much. Can still improve it later.
I think it's worth considering giving this the neat set_next name and calling the other one set_next_different.
# Objective - #19363 finally allows self-state transitions - The naming is a bit meh (`set_forced`) - Many people expect this to work out of the box - That PR also missed a few spots where this distinction applies ## Solution - Expand on #19363 by making it the default - Rename `set` -> `set_if_neq` - Rename `set_forced` -> `set` - Add the two variants to - commands - reflection - computed states - make the transition logs a bit less chatty in the common case - add a test for the new behavior ## Testing - CI
Objective
Solution
set_forcedmethod onNextStatethat will triggerOnEnterandOnExitset_forcedhas been usedsetis called afterset_forcedwith the same state