Source file unity-csharp/arcade-classics/space-invaders/SpaceInvadersGame.cs from the GDnD code examples. Download raw file
// 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();
}
}
}