The game shows one screen per GameState. UIRoot.OnGUI switches on the state and calls that screen’s view, an
IMGUI class with a Draw(GameRoot game) method. A new screen = a GameState value + a view class + a case in
UIRoot + something that calls GameRoot.SetState. A popup over an existing screen does not need a state.
Steps
State. Add a value at the end of enum GameState in Assets/_Project/Scripts/Core/GameState.cs, with a
comment. The last three added were Intro, Outro (#40) and Index (#43):
Index // the master list of everything in the game (UI/IndexView), a lobby screen like Customize
View. Create Assets/_Project/Scripts/UI/MyView.cs in namespace HomeRunDerby.UI, shaped like the others
(RunMapView, MapSelectView): a plain class with public void Draw(GameRoot game) that draws with UIDraw and
UITheme (see UI System). Unity creates the .meta file when the Editor imports it; commit it.
Register it in Assets/_Project/Scripts/UI/UIRoot.cs: a field and a case in OnGUI:
readonly IndexView _index = new IndexView();...case GameState.Index: _index.Draw(_game); break;
If the view needs GameEvents, subscribe in UIRoot.OnEnable and unsubscribe in OnDisable, as _hud and
_customize do.
Enter it. Add a method on GameRoot (like OpenMapSelect, EnterCustomize, EnterIndex) that sets up the
field and camera and calls SetState(GameState.X). SetState raises GameEvents.StateChanged, which other systems
listen to.
A lobby screen under the top bar (like CUSTOMIZE and INDEX): add a value to enum LobbyTab and a tab in
LobbyNav.DrawBar that calls your GameRoot method, then call _nav.DrawBar(game, LobbyTab.X, w) from your view.
Also add the state to ScreenFade.HasTopBar so the bar doesn’t fade between lobby screens.
Check the other state switches and decide what your screen should do there:
Audio/GameAudio.OnState: the organ plays on every state except AtBat, CoopWatch, Intro and Outro.
Batting/AtBatController (around line 161): the preview batter is aborted on any state except MainMenu,
Customize, Lobby, CoopWatch, Intro and Outro.
UI/ScreenFade: HasTopBar is MainMenu, Customize and Index; OnState skips the fade from Intro to
AtBat / CoopWatch and from AtBat / CoopWatch to Outro (the cutscenes carry the shot over).
UI/UIRoot.OnGUI draws IntroOverlayView.DrawTransition and OutroOverlayView.DrawTransition after every screen,
so a cutscene’s walk-up or wipe sits over whatever comes next. See Cutscenes.
UI/UIRoot.Update: Esc pauses and the cursor is confined only in AtBat.
UI/DevMenu: the RUN tools only work in RunMap, Shop and AtBat.
Check it works
No self-test covers screens. Press Play, reach the screen, and check: Esc behaviour, music on or off, the batter
preview, and that leaving returns cleanly (GameRoot.GoToMainMenu). Check it at a couple of window sizes; views lay
out from UITheme.Width / Height.
Gotchas
UIRoot draws nothing until GameRoot.IsReady.
Pausing only exists in AtBat; a new gameplay screen that needs pause must add it to UIRoot.Update.
If co-op players can be on the screen, the co-op run (Run/CoopRun) also changes states and must know when to go
there. Changing what co-op peers expect is a protocol change (Protocol Versions).
In the top bar (UI/LobbyNav), PLAY, CUSTOMIZE and INDEX switch states (MainMenu, Customize, Index); PERKS,
BATTING CAGE and the settings behind the menu icon are popups, not states.