Exercise 3 — Rules & States
GAME 1303-001 · Unity 6.x · Week 4 — Tuesday, September 15
In class, 10:30 – 11:45 · 2 points · Submit by end of class
📄 Your One Sheet is due in Canvas tonight — see assignment-one-sheet.md
The skill
Last week you built a verb. A verb alone is a toy. What turns a toy into a game is stakes: something you're trying to do, something that can stop you, and a defined moment when either happens.
That's what rules are. Not "the controls" — the answer to three questions:
- What am I trying to do? → the goal
- What can stop me? → the failure
- What happens then? → the consequence
The third question is the design question. Super Meat Boy and Dark Souls both kill you constantly, but the consequence is a half-second respawn in one and a long walk back in the other, and that single difference produces two entirely different games from the same failure rate.
By the end of the block you will have: your Ex 2 course with a goal, a hazard, a win state, a lose state, and a consequence you chose deliberately.
With Ex 2, this feeds Milestone 2 — Core Game Mechanic (Week 5), next week.
What you need
- Your Ex 2 project, with the verb and three-obstacle course
HelperScripts.unitypackageimported
Part 1 — Draw the state diagram (10 min)
Before you build anything. On paper, or in any drawing tool, five minutes maximum.
Draw a box for each state your game can be in, and an arrow for each thing that moves between them. The minimum:
┌──────────┐
┌───▶│ PLAYING │───── reach goal ────▶ ┌─────┐
│ └──────────┘ │ WON │
│ │ └─────┘
│ │ touch hazard │
│ ▼ │
│ ┌─────────┐ │
│ │ LOST │ │
│ └─────────┘ │
│ │ │
└─────────┴───── press R ──────────────────-┘
Then add your states. A game with checkpoints has a respawn arrow. A game with lives has a counter and two different lose arrows. A puzzle game might have no lose state at all — and if so, draw that, because "you cannot fail" is a real and deliberate design position.
Photograph or export it. This drawing is part of your submission.
Five minutes with a pen here prevents an hour of confused wiring later. Every state bug you will hit this semester is a state you didn't draw.
✅ Checkpoint 1 — a state diagram exists, photographed, with at least one state beyond the default four.
Part 2 — Wire the goal (15 min)
1. Set up the manager
Your GameManager object from Ex 2 already has GameStateManager. On it, check:
| Field | Set to |
|---|---|
restartKey | R |
showDebugState | ✔ (draws the current state on screen — your temporary UI until Week 10) |
restartDelay | 0 for now; you'll tune this in Part 4 |
2. Make the goal
At the end of your course, make an empty GameObject named Goal:
- Box Collider 2D, size it to a doorway, Is Trigger ✔
- Sprite Renderer with a plain square, tinted green, so you can see it
- Add the
TriggerZonehelper
3. Hook it up
On TriggerZone:
requiredTag→PlayertriggerOnce✔- Under On Enter (), click + → drag your
GameManagerobject into the slot → choose GameStateManager → Win ()
No code. That dropdown is the wiring. This is the same pattern you'll use for every trigger in your game for the rest of the semester — doors, checkpoints, cutscenes, music changes.
4. Test it
Play. Walk into the goal. The debug text should read WON.
✅ Checkpoint 2 — touching the goal produces a win state on screen.
Part 3 — Wire the failure (15 min)
5. Make a hazard
Duplicate the Goal object. Rename it Hazard, tint it red, and place it where the player will actually hit it — under a gap, in the path of the second obstacle.
On its TriggerZone, change On Enter () to GameStateManager → Lose (), and uncheck triggerOnce.
6. Add a fall-out-of-the-world hazard
Make a very wide, thin Hazard copy well below your floor. Every game needs this, and forgetting it is the single most common soft-lock in student builds — the player falls forever and has to close the application.
7. Test both
Play. Touch the hazard → LOST. Fall off the edge → LOST. Press R → PLAYING.
✅ Checkpoint 3 — both failure routes work, and R returns you to a playable state.
Part 4 — Choose your consequence (15 min)
This is the graded design decision. Pick one and implement it:
| Consequence | How | Feels like |
|---|---|---|
| Instant restart | restartDelay = 0.2, restart the whole course | Super Meat Boy — fast, punishing, low-stakes |
| Checkpoint respawn | Add the Checkpoint helper to a mid-course trigger; GameStateManager.respawnAtCheckpoint ✔ | Celeste — forgiving, keeps momentum |
| Lives | GameStateManager.lives = 3; lose only when it hits 0 | Arcade — makes each attempt matter |
| Resource loss | Player keeps going but loses something on failure | Souls-like — failure has weight without stopping play |
| No failure | Remove the hazards; the goal is the only state change | Puzzle, narrative, walking sim — pressure comes from the problem, not from death |
"No failure" is a legitimate choice and scores full marks if you argue it. Puzzle and narrative tracks should think hard about it — a puzzle game that kills you is usually two games fighting each other.
8. Tune the timing
Whichever you chose, tune the delay. How long between failing and playing again?
Try 0, then 0.5, then 2.0 seconds. Notice that a delay under about 0.3s feels responsive and blameless, while anything over about 1.5s makes you dread failing. Both are usable. Choose which one your game wants.
9. Write your notes
Docs/Ex03_notes.txt:
States: Playing, Won, Lost, Respawning (diagram attached)
Goal: reach the green door at the end of the course
Failure: touching a red hazard, or falling below the floor
Consequence chosen: CHECKPOINT RESPAWN
restartDelay: 0.35
Checkpoint placed after obstacle 2
Why: my dash is a commitment with no mid-air correction, so players
fail a lot while learning it. At full-course restart the third gap felt
unfair — I'd lose 20 seconds of correct play for one mistake. With a
checkpoint after obstacle 2 and a 0.35s delay, failure costs about
two seconds, so I kept trying the hard gap instead of getting annoyed.
I want a game you fail at cheerfully, like Celeste, not one you fear.
Three sentences minimum, naming what the consequence does to the player's behaviour. That's the point.
✅ Checkpoint 4 — a consequence implemented and tuned, notes written naming its effect on play.
Part 5 — Build and submit (5 min)
10. Build
File → Build Profiles → Windows → Build into MyGameName/PC_Builds/Ex03/.
11. Record
20–40 seconds: win once, fail once, and show the consequence playing out.
12. Submit
Zip as lastname_ex03.zip:
PC_Builds/Ex03/- Your recording
- Your state diagram image
Docs/Ex03_notes.txt
Canvas → Assignments → Exercise 3. Due before you leave.
📄 One Sheet due tonight, 11:59 PM, separately.
Rubric — 2 points
| Criterion | Pt | Met when |
|---|---|---|
| Implementation | 1 | Build runs · goal produces a win · hazard produces a lose · falling out of the world is handled · restart works · no console errors |
| Design decision | 1 | State diagram submitted with at least one state beyond the default · a consequence deliberately chosen from the list and tuned · notes name its effect on player behaviour |
Troubleshooting
Nothing happens when I touch the goal.
Four things, in order: the collider is Is Trigger ✔ · the player has a Rigidbody2D (triggers need one on at least one object) · requiredTag matches the player's actual tag · the On Enter () slot has both an object and a function selected — a half-filled UnityEvent silently does nothing.
The win fires immediately on Play.
Your trigger overlaps the player's start position. Move it.
It fires repeatedly.
triggerOnce ✔ on the goal. Hazards usually want it off.
"MissingReferenceException" after restart.
Something is holding a reference across the scene reload. Assign references in Start(), not in the Inspector, for anything that persists — or simpler, let GameStateManager own it.
R doesn't restart.
The restart key is read through the Input System. Confirm GameStateManager has a PlayerInput component or its restartAction assigned, and that your scene is in File → Build Profiles → Scene List. SceneManager.LoadScene fails silently on scenes that aren't in the build list.
The debug state text doesn't show.
showDebugState ✔, and check it isn't drawing behind your background sprite — set the sprite's Order in Layer lower.
If you finish early
- Add a second, different failure — a timer, a fall limit — and decide whether two failure types make the game better or just noisier.
- Try the opposite consequence to the one you chose. Play both for two minutes. Note which you'd rather keep, and why.
- Add a win condition that requires the goal and something else — collect three things, then reach the door. Notice how that changes the level's shape.
Before next week
Week 5 is Milestone 2 — Core Game Mechanic, worth 5 points, demoed live. It is your Ex 2 verb plus this week's rules, applied to your own game rather than a test course. Read milestone-2-core-game-mechanic.md and check the ③ Core Mechanic tab of the course checklist before you arrive.
Build it before class. Do not build it during class.