I'm currently implementing States manually because I want my states to have substates (i.e. you can be in the main menu or in game, and either option may have further substates). I'm curious why the states trait needs the variant iterator and what it is expected to return when the states contains enum variants with fields. The documentation doesn't make it clear.
#Why must States have a variant iterator?
6 messages · Page 1 of 1 (latest)
Because it needs to be able to cycle through all the possible states to know how to reflect it
You can see it in action here: https://github.com/bevyengine/bevy/blob/80db794e3c9d161b2a81587c9e2e4b2177c2b24c/crates/bevy_reflect/bevy_reflect_derive/src/enum_utility.rs#L27
cycle through all the possible states
So what happens when I manually implement States for an enum with variants that have fields? It's obviously not going through "all possible states", even if it is iterating through all the top-level variants. Here's my code btw:
use bevy::prelude::*;
/// All the different states the game can be in.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub(crate) enum AppState {
/// The main menu, which is displayed on startup and when quitting other states.
Menu(MenuState),
/// Actually playing the game.
InGame(GameState),
}
impl Default for AppState {
fn default() -> Self {
Self::Menu(MenuState::default())
}
}
impl States for AppState {
type Iter = AppStateIter;
fn variants() -> Self::Iter {
AppStateIter::default()
}
}
/// An iterator through all the (top-level) game states.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub(crate) struct AppStateIter(Option<AppState>);
impl Iterator for AppStateIter {
type Item = AppState;
fn next(&mut self) -> Option<Self::Item> {
let state = self.0;
self.0 = match self.0 {
Some(AppState::Menu(_)) => Some(AppState::InGame(GameState::default())),
Some(AppState::InGame(_)) => None,
None => None,
};
state
}
}
/// All the states the menu can be in.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub(crate) enum MenuState {
/// The main menu.
#[default]
Main,
/// The settings menu.
Settings,
}
/// All the states the game can be in.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub(crate) enum GameState {
/// Game is running.
#[default]
Running,
/// Game is paused.
Paused,
}
It seems to work fine for me so I'm not sure if this is somehow subtly breaking something
Also if it needs to go through the variants, why isn't Reflect just a super-trait of States? I don't understand why States specifically needs variant iteration when that seems to be provided by reflect already.