Game Events

In short

GameEvents is a static class of C# events with one RaiseX method each. Gameplay raises; UI, audio and effects subscribe in OnEnable and unsubscribe in OnDisable. Add a reaction by subscribing, never by editing the code that raises.

How it works

  1. A system calls GameEvents.RaiseX(payload).
  2. Every subscriber runs at once, on the main thread, in subscription order.
  3. On boot GameBootstrap.ResetStatics calls GameEvents.ClearAll(), so Play mode without a domain reload never keeps old subscribers.

The at-bat raises the same events when it replays another player’s at-bat in co-op (AtBatController.Spectate), so the HUD, crowd, sounds and scoreboard react to a teammate’s swing exactly as to your own (Live Spectating).

Every event

EventPayloadRaised byListened to by
StateChangedGameStateGameRoot.SetStateGameAudio (organ on menus, off at bat, in CoopWatch and in the Intro / Outro cutscenes), AtBatController, BattingCage (clears IsActive), ScreenFade, CustomizeView.OnStateChanged (via UIRoot)
PitchThrownPitchDataAtBatController.PitchRoutine, AtBatController.SpectatePitchGameAudio (whir, glove pop, special-ball cue), TimingIndicator, HudView, FlyingHat (hat flies back on), CoopRun.OnMyPitch (during your turn)
SwingStartednoneAtBatController (swing press), spectate replayGameAudio (whoosh), CoopRun.OnMySwing (during your turn)
SwingResolvedSwingResultAtBatController, spectate replayGameAudio (crack, ping, green cheer, ooh), HudView, GreenFeedback (camera shake), StadiumCrowd
HitLandedHitOutcomeAtBatController.ResolvePlay (when the ball first lands)GameAudio, HudView, Scoreboard (HOME RUN! flash), StadiumCrowd, BeanBatter and HumanBatter (knock the hat off on a long home run)
PlayEndedPlayReport (headline, color, pitch, swing, hit)AtBatController.ReportPlayHudView, CoopRun.OnMyPlay (sends the play feed), SwingLog (one line in swings.csv, Swing Log)
CountChangedCountState (balls, strikes, outs, outsAllowed)CountTracker.NotifyGameAudio (wood block, strikeout groan)
Feedbackstring, ColorAtBatController (“Now facing …” except on the walk-up after the match intro, “INNING n CLEARED!”, “ROUND CLEARED!”, “TURN OVER”, “Out of outs…”, ”$$$ BALL! +n COINS”), spectate replay (“Now facing …”), CoopRun (“INNING n CLEARED!”, “OUT OF OUTS…“)HudView
RoundFinishedRoundResultAtBatController when a round or co-op turn endsGameAudio (cheer or groan), HudView
RunEndedRunSummaryRunManager.EndRun, CoopRun.EndRun, both from ShowResults (after the MAP BEATEN / GAME OVER cutscene when one plays)GameAudio (win cheer, new-best chime)
CosmeticsChangednoneMetaProgression.Equip, MetaProgression.UnequipAtBatController.RefreshCosmetics
ScoreboardHitHitOutcomeAtBatController.BallInPlay (when the ball reaches the board), ScoreboardSmashTest.SmashNow (Editor)Scoreboard (smash), GameAudio (smash sound)

Numbers

WhatValueWhere to tune
Events on the bus12Scripts/Core/GameEvents.cs

In the code

FileWhat it does
Scripts/Core/GameEvents.csThe events, RaiseX methods and ClearAll.
Scripts/Batting/AtBatController.csRaises most gameplay events.
Scripts/Batting/CountTracker.csRaises CountChanged.
Scripts/Audio/GameAudio.csThe biggest listener: every sound comes from an event.
Scripts/UI/HudView.csSubscribe / Unsubscribe called by UIRoot.OnEnable / OnDisable.

Gotchas

  • Adding an event means three edits in GameEvents.cs: the event, the RaiseX method and a line in ClearAll. Forgetting ClearAll leaks subscribers between Play sessions with domain reload off.
  • Not everything is on the bus. AtBatController.BeginRound takes a finish callback, AtBatController.SwingCompleted is its own event (used by CoopRun), and NetRuntime / NetSession have their own events (Lobby and Session).
  • HitLanded fires when the ball first touches down, not when it stops rolling. ScoreboardHit fires during the flight, when the playback reaches the smash (or at once if the player skips).
  • CoopRun only listens to PlayEnded, PitchThrown and SwingStarted while it is your turn (UnhookMyTurn removes them).
  • No event was added between e7dba51 and 45a2167. The cutscenes and the hit show are driven directly, not through the bus: MatchIntroDirector, OutroDirector, Fireworks and HitCounter call GameAudio statics (Whoosh, Impact, Fanfare, FireworkBang, CounterTick, Gone…) and the StadiumCrowd / Scoreboard methods (Celebrate, Slump, ShowMessage) themselves (Cutscenes, Hit Show).
  • RunEnded now fires after the end-of-game cutscene, but the run is recorded and saved before it starts, so quitting mid-cutscene loses nothing.
  • SwingLog skips spectated pitches: in co-op they are logged on the batter’s own machine.