Minimal Breakout (Unity / C#)

The step-2 project in overview-arcade-classics-as-learning-projects. It builds directly on the Pong example and adds the skills the canon reference (see source-classic-games-canon) lists for Breakout: collision response, arrays/lists, level reset, and scoring.

As with Pong, this is an original project inspired by a recognisable pattern, not a clone of Atari’s Breakout.

Files

ScriptResponsibilityKey wiki concept
Ball2D.csMoves the ball; reflects off walls, paddle, and a brick layer; reports a misscollision response, unity-collider2d-and-triggers
Paddle2D.csHorizontal player input, clamped to screenunity-input, unity-transform
Brick.csOne destructible brick: takes hits, awards score, raises Destroyedobserver-pattern
BrickGrid.csBuilds the wall in a loop, tracks bricks in a List, detects clearancecsharp-collections, unity-prefabs-scripting
BreakoutGame.csOwns score and lives; serves; rebuilds on clear; game overunity-gamemanager-pattern

The ball still uses no Rigidbody — collision and reflection stay explicit. Bricks are found with Physics2D.OverlapBox against a layer, which keeps the ball decoupled from the grid.

Scene setup (about 10 minutes)

  1. New 2D scene, Main Camera set to Orthographic.
  2. Add a user layer called Bricks (Edit → Project Settings → Tags and Layers).
  3. Brick prefab: create a square sprite, add a Box Collider 2D, add the Brick script, set its layer to Bricks, then drag it into the Project window to make a prefab and delete the scene copy.
  4. Paddle: square sprite near the bottom, scaled wide (e.g. 2.5, 0.4, 1). Add a Box Collider 2D and the Paddle2D script.
  5. Ball: small square sprite at the origin. Add the Ball2D script, drag the paddle’s collider into Paddle, and set Brick Mask to the Bricks layer.
  6. Grid: empty GameObject BrickGrid, add the BrickGrid script, drag the brick prefab into Brick Prefab. Tune columns/rows in the Inspector.
  7. Game: empty GameObject Game, add BreakoutGame, and drag in the Ball and BrickGrid.
  8. Press Play. Move with A/D or the left/right arrows. Score and lives print to the Console; clearing the wall rebuilds it and re-serves.

How the brick bounce works

When the ball overlaps a brick, ReflectOffBox compares how far it has penetrated the brick on each axis and flips the axis of least penetration — that is the side it most recently crossed. This is the standard lightweight axis-aligned bounding box (AABB) resolution, and it is worth reading closely: the same idea reappears whenever you resolve a moving box against static boxes.

Extension ladder

These mirror the Breakout extension tasks in the canon reference and point toward step 3 (Snake, grid logic):

  1. On-screen score and lives — swap the Debug.Log calls for UI/TMP text.
  2. Brick types — give some bricks hitPoints = 2 (they already darken when weakened) or higher scoreValue; introduce an unbreakable brick.
  3. Power-ups — on brick death, occasionally drop a falling pickup (wider paddle, multi-ball, slow ball). First taste of spawning and pooling — see object-pool-pattern.
  4. Multiple levels — have BrickGrid read a layout from a 2D array or text asset instead of a uniform wall. This is the bridge to grid-based games.
  5. Particle and audio feedback on brick break — see unity-audiosource and game-feel.

Source files

5 items under this folder.