Exercise 9 — Curves & Locks

GAME 1303-001 · Unity 6.x · Week 13 — Tuesday, November 17
In class, 10:30 – 11:45 · 2 points · Submit by end of class
📘 Your Game Design Doc is due in Canvas tonight — see assignment-game-design-doc.md


The skill

Two ideas, one exercise, because they are the same idea.

Difficulty curve. Games get harder. How they get harder is a designed shape, not a side effect. Linear ramps are exhausting; a curve with peaks and recoveries is what keeps people playing.

Lock and key. A challenge the player can only pass by understanding something. Not a bigger enemy — a different problem, whose solution is knowledge.

The connection: difficulty should increase because the player is being asked to know more, not merely to react faster. A game that only speeds up eventually excludes everyone. A game that keeps teaching stays interesting.

By the end of the block you will have: health and score wired, a difficulty ramp you graphed before you tuned, and one puzzle whose solution is understanding.


What you need


Part 1 — Health and score (15 min)

1. Add Health to the player

Field Set to
maxHealth 3
invulnerabilityTime 0.5
destroyOnDeath ✘ (off for the player)

Hook the events in the Inspector:

invulnerabilityTime is not a nicety. At 0, standing inside a hazard drains three hearts in three frames and the player cannot tell what killed them. This is the single most common "my game is broken" bug in this course.

2. Wire hazards to it

On each hazard's TriggerZone, set On Enter () → Health.TakeOneDamage().

3. Add Score

Put a Score component on your GameManager. On any pickup's TriggerZone, wire On Enter () → Score.AddTen().

If you built the HUD in Ex 7, both now display live with no extra work.

✅ Checkpoint 1 — taking damage flashes, costs health, and eventually loses; pickups add score.


Part 2 — Graph the curve before you build it (15 min)

4. Draw it on paper

Horizontal axis: time, 0 to 5 minutes. Vertical: difficulty, 0 to 10.

Draw the shape you want. Then check it against these:

Shape What it does
Straight line up Feels relentless. Players quit at the point it passes their skill, and nothing invites them back
Staircase Steps up, then holds. The hold is where players get good at the new thing. Most commercial games
Sawtooth Rises, drops, rises higher. The drops feel like mastery — the same challenge is now easy
Flat Boring by minute two, regardless of how good the mechanic is

Draw a staircase or a sawtooth. Mark where the player recovers. Recovery beats are what make the peaks readable — the same principle as rest beats in Ex 5, applied to time instead of space.

Photograph it. The graph is part of your submission, and it must be drawn before you tune.

✅ Checkpoint 2 — a difficulty graph with marked peaks and recoveries.


Part 3 — Build the ramp (15 min)

5. Set up the spawner

Empty GameObject → add ObjectPool (assign your enemy/obstacle prefab, initialSize 20) and Spawner.

Field Set to
mode Continuous or Waves
spawnInterval 2.0
rampRate 0.02
minimumInterval 0.35
maxAlive 12

6. Understand what rampRate does

Each spawn shortens the next gap by that fraction. At 0.02, the interval halves after about 35 spawns — roughly a minute in. At 0.1, it bottoms out in fifteen seconds.

rampRate is your difficulty curve. It is not a technical setting. Change it and the entire feel of your game changes.

minimumInterval is the floor. Without it the ramp eventually spawns every frame and the game becomes unplayable rather than hard — which is a different thing, and never the goal.

7. Play for three minutes and compare

Play with a stopwatch. Note where you struggled. Plot the actual difficulty against your drawn curve.

Almost nobody matches their graph on the first attempt. The usual gaps:

What happens Fix
Fine for 90 seconds, then instantly impossible rampRate too high; try halving it
Never gets hard rampRate too low, or maxAlive capping it
Hard but shapeless You need Waves mode — continuous spawning has no recovery beats in it

Recovery is what Waves mode gives you. waveInterval is the gap between waves, and that gap is where the player breathes.

✅ Checkpoint 3 — ramp tuned to approximate your drawn curve.


Part 4 — One lock and key (15 min)

8. Build a challenge that requires knowing something

Not a bigger enemy. A different problem.

Type Example
Mechanical An enemy only vulnerable while dashing — the player must know dash grants invulnerability
Spatial A gap only crossable by dashing off a wall — knowledge of a property, not a stat
Sequential Three switches that must be hit in order, and the order is shown somewhere in the room
Resource A door that costs 50 score — the player chooses between spending and saving
Observational A safe path marked by a detail established earlier in the level

9. Teach it, then test it

Every good lock is taught before it is tested. The pattern is always:

  1. Teach — introduce the idea somewhere safe, where failing costs nothing
  2. Test — require it, where failing costs something
  3. Twist — require it combined with something else

Build at least steps 1 and 2. If you only build the test, players will call your puzzle unfair, and they will be right — an untaught lock is a guess.

10. Write your notes

Docs/Ex09_notes.txt:

Health: 3, invulnerability 0.5s, flash + sound on damage.
Score:  10 per crystal, combo window 2s.

Curve drawn: sawtooth — peaks at 0:45, 2:00, 3:30, recovery after each.
Curve achieved: rampRate 0.015, Waves mode, waveSize 5, waveInterval 7.

Difference from my graph: my first draft used rampRate 0.05 continuous.
It was flat-out impossible at 90 seconds and there was no recovery
anywhere, so the peaks didn't read as peaks — it was just a wall.
Switching to Waves gave me the drops, and the peaks suddenly landed.

Lock: the shielded enemy. Only takes damage while I'm dashing.
  Teach — one appears alone in a safe corridor at 0:30, no other
          threats, so you can experiment until you work it out.
  Test  — two appear at 2:10 with hazards between them, so you have
          to dash through the gap AND land the hit.

What I learned: I originally put the shielded enemy in the first wave.
Three testers all just ran past it and never learned the rule, so the
2:10 test felt unfair. Moving the teach beat to an empty corridor
fixed it completely.

✅ Checkpoint 4 — a lock with a teach beat and a test beat, notes comparing drawn curve to achieved curve.


Part 5 — Build and submit (5 min)

11. Build into MyGameName/PC_Builds/Ex09/, then submit

Zip as lastname_ex09.zip: the build, your difficulty graph photo, and Docs/Ex09_notes.txt.

Canvas → Assignments → Exercise 9.
📘 Game Design Doc due tonight, 11:59 PM, separately.


Rubric — 2 points

Criterion Pt Met when
Implementation 1 Build runs · health with invulnerability, damage feedback, and death · score wired · spawner ramps over time · one lock built with both a teach beat and a test beat · no console errors
Design decision 1 Difficulty graph drawn before tuning and submitted · notes compare drawn curve to achieved curve and explain the difference · the lock's solution is knowledge, not reflex

Troubleshooting

I die instantly touching anything.
invulnerabilityTime is 0. Set it to 0.5. This is the bug.

Health goes down but nothing shows.
OnDamaged isn't hooked to HitFlash.Flash(). Both an object and a function must be selected in the UnityEvent.

The game slows to a crawl after a minute.
You're instantiating instead of pooling. Assign the ObjectPool reference on the Spawner.

Enemies stop spawning entirely.
maxAlive is reached and nothing is dying — or Health.OnDeath isn't firing, so the alive count never drops.

The ramp does nothing.
rampRate is 0, or you're in Waves mode, which uses waveInterval rather than the continuous ramp.

Score resets when I restart.
That's correct — score is per-run. The high score persists in PlayerPrefs.

My puzzle is "too hard" according to everyone.
It's almost never too hard. It's untaught. Add the teach beat.


If you finish early


Before next week

Ex 10 — Test & Iterate is the last exercise. You will put your game in front of three real people and fix what breaks. Bring a build that runs — you cannot do next week's exercise without one.

Week 15 is the Game Build milestone, worth 25 points. Build early.