// GDnD wiki example // Demonstrates: a small game state machine owning score and lives, with wave/win/lose transitions // Related pages: [[overview-arcade-classics-as-learning-projects]], [[unity-gamemanager-pattern]], [[csharp-enums]] using UnityEngine; // Central controller. It owns score, lives, and the game State, and reacts to the // three things that change that state: an invader killed (score), the wave cleared // (next wave), and the player hit or invaders reaching the line (lose a life / // game over). The State enum is the step-4 "state changes" learning target. public class SpaceInvadersGame : MonoBehaviour { public enum State { Playing, GameOver } [SerializeField] private PlayerShip player; [SerializeField] private InvaderFormation formation; [SerializeField] private int startingLives = 3; public State CurrentState { get; private set; } public int Score { get; private set; } public int Lives { get; private set; } public int Wave { get; private set; } private void Start() { player.Bind(this); formation.Bind(this, player.transform.position.y); StartGame(); } private void StartGame() { Score = 0; Lives = startingLives; Wave = 1; CurrentState = State.Playing; formation.BuildWave(); Debug.Log($"Wave {Wave} — Lives {Lives}, Score {Score}"); } public void AddScore(int value) { Score += value; } public void OnWaveCleared() { Wave++; Debug.Log($"Wave cleared! Starting wave {Wave}. Score {Score}"); formation.BuildWave(); } public void OnPlayerHit() { LoseLife("Player hit"); } public void OnInvadersReachedPlayer() { // Invaders landing is an instant loss of the run. Debug.Log("Invaders reached the line!"); Lives = 0; EndOrContinue(); } private void LoseLife(string reason) { if (CurrentState != State.Playing) { return; } Lives--; Debug.Log($"{reason}. Lives remaining: {Lives}"); EndOrContinue(); } private void EndOrContinue() { if (Lives <= 0) { CurrentState = State.GameOver; Debug.Log($"Game over. Final score: {Score}"); StartGame(); } } }