Minimal Space Invaders (Unity / C#)
The step-4 project in overview-arcade-classics-as-learning-projects. It is the first project in the route with multiple interacting systems, and it introduces the four skills the canon reference (see source-classic-games-canon) lists for Space Invaders: enemy formations, timers, projectile pooling, and state changes (plus lives).
Original project inspired by a recognisable pattern — not a clone.
Files
| Script | Responsibility | Key wiki concept |
|---|---|---|
IHittable.cs | One-method interface so a bullet can damage anything | csharp-interfaces |
ProjectilePool.cs | Reuses bullets instead of Instantiate/Destroy per shot | object-pool-pattern |
Projectile.cs | Pooled, transform-driven bullet; hits a target layer, returns itself | unity-collider2d-and-triggers |
PlayerShip.cs | Move + fire on a cooldown timer; takes a hit | unity-input |
Invader.cs | One formation member; dies on hit, reports to the formation | csharp-interfaces |
InvaderFormation.cs | Marches the grid, edge-drops, fires on a timer, speeds up per kill | csharp-collections |
SpaceInvadersGame.cs | Owns score, lives, and the State machine; wave/lose flow | unity-gamemanager-pattern, csharp-enums |
ArcadeHud.cs (in ../shared/) | Shared on-screen HUD: a status line plus a timed centre message, drawn with TextMeshPro | ui-design, game-interface-types |
What is new at this step
- Enemy formation. Every invader is a child of
InvaderFormation, so the whole grid marches by moving one transform. The formation reverses and drops a row when its edge reaches the screen, and it tracks survivors in aList. - Timers. Two independent timers drive the game: one steps the march, one
fires from a random survivor. The player’s fire rate is a third cooldown timer.
All are frame-rate independent (accumulating
Time.deltaTime). - Projectile pooling. Both sides share one
ProjectilePool, firing the same prefab parameterised by direction and target layer. This is the route’s first real use of object-pool-pattern. - State changes.
SpaceInvadersGameholds aStateenum and routes every event (invader killed, wave cleared, player hit, invaders landed) through it.
Scene setup (about 15 minutes)
- New 2D scene, Main Camera set to Orthographic.
- Add two user layers:
PlayerandInvaders(Edit → Project Settings → Tags and Layers). - Bullet prefab: a small thin square sprite, add a Box Collider 2D and the
Projectilescript. Make it a prefab; delete the scene copy. (It needs no layer of its own — it targets a layer.) - Pool: empty GameObject
BulletPool, addProjectilePool, assign the bullet prefab. - Player: a square sprite near the bottom, layer Player, with a Box
Collider 2D and the
PlayerShipscript. Assign Bullet Pool, and set Invader Mask to the Invaders layer. - Invader prefab: a square sprite, layer Invaders, with a Box Collider
2D and the
Invaderscript. Make it a prefab; delete the scene copy. - Formation: empty GameObject
Formation, addInvaderFormation, assign the invader prefab and the Bullet Pool, and set Player Mask to the Player layer. - Game: empty GameObject
Game, addSpaceInvadersGame, and drag in thePlayerandFormation. - HUD: copy
../shared/ArcadeHud.csinto the project as well. Add GameObject → UI → Text - TextMeshPro (click Import TMP Essentials the first time). Unity also creates a Canvas (leave it on Screen Space - Overlay) and an EventSystem. Name the textStatusTextand anchor it to the top-left; duplicate it asMessageText, anchor it to the centre, and set its alignment to centre. AddArcadeHudto the Canvas, drag both texts into its Status Text and Message Text fields, then drag the Canvas into the Hud field onGame. (Leave Hud empty and messages print to the Console instead.) - Press Play. Move with A/D or arrows, Space to fire. Clearing the wave starts a faster one; losing all lives restarts. Score, lives, and wave show on screen.
Why pooling here
A wave can put dozens of bullets on screen per second. Instantiating and
destroying each one churns memory and can cause GC hitches — exactly the case
object-pool-pattern is built for. Swapping the pool for plain
Instantiate/Destroy and watching the unity-profiler is a good exercise.
Extension ladder
These lead toward step 5 (Asteroids, vector movement and wrapping):
- Destructible shields — bunkers that erode from both bullet directions (reuses Breakout’s brick idea).
- Animation frames — alternate the invader sprite each march step for the classic shuffle; first touch of unity-animator-scripting.
- Dive attacks — occasionally peel an invader out of formation to swoop (the bridge to Galaga and to steering-behaviours).
- Audio and hit feedback — the rising march tempo is iconic game-feel; see unity-audiosource.