Guide 1 — Conquer the Cutthroat Course
Nicholas Murley
What you're building
A single trap-filled obstacle course. No timer, three lives, and traps that get nastier as you go: saw blades, fire, an acid pit, spikes, crushers, and electricity along the ceiling that shocks you if you jump too high. When you burn through all three lives, a suitably undignified sound plays.
Your game uses no enemies, no collectibles, and no dialogue — which makes it the cleanest build in the class. Everything you need is the core kit plus hazards.
Heads up for everyone else: this guide builds the player prefab, respawn loop and camera that eleven other games use. If your guide says "build the player as in Guide 1," sections 3 and 4 are what it means.
Time: about two hours for a playable first course.
1. Before you start
- Finish Guide 0. Your Console should be error-free and
Verify Setupshould be happy. - No extra packages beyond the standard three.
- Have Guide B open in another tab — you'll bounce off it a few times.
2. Scripts you'll use
Core (Tier 1) — the eleven you can't skip
PlayerController2D · PlayerAnimatorBridge · Health · DamageOnContact · Checkpoint · RespawnManager · CameraTargetAssigner · SceneLoader · GameManager · AudioManager · HUDController · MovingPlatform · ParallaxBackground
Hazards (Tier 4) — your actual game
SpinningSaw · SpikeTrap · Crusher · CyclingHazard · ElectricZone · KillZone · LevelExit
You will not need: anything from Tiers 2, 3, 5, 6, 7 or 8. If you find yourself adding an enemy script, you've wandered off your own game.
3. Build the player
Follow Guide B §B1 exactly, then come back. Short version:
- Empty GameObject
Player, Tag → Player - Sprite Renderer, Rigidbody2D (Gravity 3, Freeze Rotation Z, Continuous), Capsule Collider 2D
- Player Input (Behavior: Send Messages)
PlayerController2D,Health(Max Health 1), Animator,PlayerAnimatorBridge- Child
GroundCheckat the feet, dragged into the controller - Ground Layer →
Ground - Save as a prefab
One change from the default: Max Health 1
Your traps kill instantly. There's no health bar in a course game — you touch a saw, you die, you go back to the checkpoint. Setting Max Health to 1 and using Instant Kill on your hazards makes that immediate and readable.
4. Build the level and camera
The floor
- GameObject → 2D Object → Tilemap → Rectangular (or just use stretched sprites while prototyping — you can replace them later).
- Select the Tilemap or your ground sprites and set Layer →
Ground. - Ground pieces need a Tilemap Collider 2D (or a Box Collider 2D on each sprite).
Prototype with grey boxes. Build the whole course out of plain rectangles first and get it feeling right. Art last. It's much easier to move a grey box than to redraw a background.
The camera
Guide B §B3 — 2D Cinemachine camera + CameraTargetAssigner. Since your course is one long level, add the CinemachineConfiner2D and a CameraBounds polygon so the camera stops at the ends.
The managers
Guide B §B2. You need: GameManager, RespawnManager, AudioManager, SceneLoader. You do not need CollectionTracker or ChoiceFlagManager.
5. Set up lives and respawning
This is the heart of your game, so it's worth doing carefully.
On RespawnManager
| Field | Value |
|---|---|
| Player | leave empty — it finds the tag |
| Respawn Delay | 1 |
| Use Lives | ✓ ticked |
| Starting Lives | 3 |
Checkpoints
- GameObject → Create Empty, name it
Checkpoint. - Add a Box Collider 2D, tick Is Trigger, size it about two units wide and three tall.
- Add the Checkpoint component.
- Optional: add a Sprite Renderer (a flag, a lamp) and assign Inactive Sprite and Active Sprite so it visibly lights up.
- Save it as a prefab and place one at the start of each difficulty section.
Your first checkpoint is free — RespawnManager uses the player's starting position until you touch one.
How many checkpoints?
Your pitch says the course gets harder in sections. One checkpoint per section is the right instinct. Too few and a death costs five minutes; too many and there's no tension. Start with four or five and adjust after someone else plays it.
6. Build your hazards
Each one is a prefab you'll place many times. Build them all now, then decorate the course.
6a. Spike (the simplest — start here)
- Empty GameObject
Spike, add a Sprite Renderer. - Box Collider 2D, Is Trigger ✓.
- DamageOnContact with:
| Field | Value |
|---|---|
| Target Tag | Player |
| Instant Kill | ✓ |
| Knockback Force | 0 |
- Save as prefab.
That's a working hazard — no hazard script needed. This is the pattern for everything below: trigger collider + DamageOnContact + something that turns it on and off.
6b. Saw blade
Same as the spike, plus:
- CircleCollider 2D instead of Box, radius slightly smaller than the art (players forgive a near miss; they don't forgive a hit that looked like a miss)
- SpinningSaw component, Spin Speed 360
To make it patrol, add MovingPlatform on the same object with two waypoints, and set its Rider Tag to something unused like Untagged so it doesn't try to carry the player.
Waypoints: create two empty GameObjects, position them at each end of the travel, then drag them out of the saw in the Hierarchy so they don't move with it. Drag both into the Waypoints list.
6c. Fire jet (on and off on a timer)
- Empty GameObject
FireJet+ Sprite Renderer (or a Particle System). - Trigger collider +
DamageOnContact(Instant Kill ✓). - CyclingHazard:
| Field | Value | Note |
|---|---|---|
| Always On | ✗ | |
| Start On | ✗ | |
| On Time | 1 | how long the flame burns |
| Off Time | 1.5 | the safe window |
| Warning Time | 0.3 | |
| Sprite | drag the Sprite Renderer in | hidden while off |
| Warning Renderer | a small "sparks" sprite | shown just before it fires |
Start Delay is how you make a row of jets fire in sequence — give them 0, 0.4, 0.8, 1.2 and the player has to run the rhythm.
6d. Acid pit
Empty GameObject with a wide Box Collider 2D (Is Trigger ✓) and a KillZone component. That's it — no DamageOnContact needed, KillZone handles it and also tidies up anything else that falls in.
Put one of these under your whole course as a safety net, so falling off the bottom kills you instead of dropping you into the void forever.
6e. Pop-up spikes
Slightly fiddlier because it has a child.
- Empty GameObject
SpikeTrap— this is the parent, and it sits where the spikes will be when extended. - Right-click → Create Empty child, name it
Spikes. Add a Sprite Renderer, a trigger Box Collider 2D, and DamageOnContact (Instant Kill ✓). - Select the parent, add SpikeTrap:
| Field | Value |
|---|---|
| Mode | Timed |
| Spikes | drag the Spikes child in |
| Hidden Offset | X 0, Y −0.6 (tune so they vanish into the floor) |
| Move Speed | 12 |
| Out Time | 1.5 |
| In Time | 1.5 |
| Warning Time | 0.3 |
| Shake Amount | 0.05 |
The shake before they pop is the fairness. Don't remove it.
Triggered mode is the other good option: set Mode to Triggered, add a second empty child with a big trigger collider, and drag it into Trigger Zone. Now they spring when the player gets close.
6f. Crusher
- Empty GameObject
Crusherat the top of the shaft. - Child
Headwith the block sprite, a Box Collider 2D with Is Trigger ✓, andDamageOnContact(Instant Kill ✓). - On the parent, Crusher:
| Field | Value |
|---|---|
| Head | drag the child in |
| Auto Distance | ✓ |
| Ground Layer | Ground |
| Wait At Top | 1.5 |
| Warning Time | 0.4 |
| Slam Speed | 25 |
| Hold At Bottom | 0.6 |
| Rise Speed | 3 |
Auto Distance raycasts down and works out how far to fall, so you can drop the same prefab into shafts of different depths and it just fits.
The rise is slow on purpose — that's the window the player runs through.
6g. Ceiling electricity — your signature trap
Your pitch: "Jump too high and the electricity shocks you."
- Empty GameObject
CeilingShock. - Box Collider 2D, Is Trigger ✓, stretched wide and thin along the ceiling of that section.
DamageOnContact(Instant Kill ✓).- ElectricZone:
| Field | Value |
|---|---|
| Always On | ✓ |
| Stun Duration | 0.5 |
| Flicker | ✓ |
| Flicker Rate | 20 |
| Sprite | your arc sprite, if you have one |
Position it so a normal jump is safe and a jump from a raised platform isn't. Playtest this one specifically — it's the trap most likely to feel unfair, because the player can't always see how high they're about to go.
7. The finish line
- Empty GameObject
LevelExit+ trigger collider. - LevelExit component:
| Field | Value |
|---|---|
| Requirement | None |
| Destination | Next In Build (or Stay Here while testing) |
| Delay | 1 |
| Complete Sfx | level_complete |
- File → Build Settings and add your scenes in order, or
LoadNexthas nothing to load.
8. The HUD
- GameObject → UI → Canvas.
- Right-click Canvas → UI → Text - TextMeshPro. Name it
LivesText, put it top-left, typeLives: 3. - Add an empty child of the Canvas called
HUDwith the HUDController component. - Drag
LivesTextinto Lives Text. Leave everything else empty — you don't need a health bar, a score, or item counters.
9. Wire it up
Four connections. Select the object in the On this object column, find the event, click +, drag in the target, choose the function.
| On this object | Event | Drag in | Choose |
|---|---|---|---|
Player → Health | On Died | RespawnManager | RespawnManager.OnPlayerDied |
RespawnManager | On Lives Changed | HUD | HUDController.UpdateLives (Dynamic) |
RespawnManager | On Game Over | GameManager | GameManager.GameOver |
RespawnManager | On Game Over | AudioManager | AudioManager.PlaySFX (string) → type funny_death |
That last one is your funny death sound. It fires once, when the third life is gone — not on every death, which would get old fast.
If a function appears twice in the dropdown, once under Static Parameters and once under Dynamic, pick Dynamic for
UpdateLives.
10. First playtest
Build a short test course — twenty seconds of running — with one of each hazard. Then press Play and check, in order:
- You can walk and jump. If not: is the Rigidbody2D there? Is
GroundCheckassigned? Is Ground Layer ticked? - You land on the floor rather than falling through. If not: does the ground have a collider and the
Groundlayer? - A spike kills you and you reappear. If you die but never come back, the
Health.OnDied → RespawnManager.OnPlayerDiedwiring is missing. - The lives counter goes 3 → 2 → 1. If it doesn't move, check the
OnLivesChangedwiring and that you picked the Dynamic version. - The third death triggers game over and your sound plays.
- A checkpoint changes where you respawn.
- The camera follows and stops at the level edges.
Get all seven working on a tiny course before you build the real one. Debugging a twenty-second level is far easier than debugging a five-minute one.
11. Then add
Once the loop works, in roughly this order:
- More hazards, arranged in difficulty sections — this is your actual game, and it's level design rather than setup.
MovingPlatformfor platforms that carry you between hazard sections.ParallaxBackground— a few sprite layers with Depth 0.2 / 0.5 / 0.8 gives you a sense of speed for almost no effort.- An Animator for the player (Guide B §B6). Two states and one parameter is enough.
- Sound. Jump, land, death, and the big one at the end. Add clips to
AudioManager's Named Sounds list. - A second level — duplicate the scene, rearrange, add both to Build Settings.
12. Design notes for your game specifically
Every trap needs a tell. Every timed hazard in the kit has a Warning Time with a shake or a warning sprite. That isn't decoration — a trap the player couldn't have anticipated isn't difficulty, it's a coin flip. Your whole game is traps, so this matters more for you than for anyone else in the class.
Three lives with no timer is a strong choice. It means the player can stop and study a section. Lean into that — traps with visible rhythms that reward watching before moving are more interesting than traps that are just fast.
Escalate one variable at a time. Section one: spikes. Section two: spikes plus fire. Section three: those plus a crusher. If everything arrives at once, the player can't learn any of it.
The death sound is a real design element. It's the thing players will quote at each other. Make sure it plays clearly, and consider making it slightly too long — the comic beat is in the pause afterward.
13. Common problems
| What you see | What's wrong |
|---|---|
| Player falls through the floor | Ground has no collider, or the collider is a trigger |
| Player never jumps | GroundCheck not assigned, or positioned inside the body instead of at the feet |
| Player jumps infinitely | GroundCheck overlapping the player's own collider — move it lower, or make sure Ground Layer only has Ground ticked |
| Retracted spikes still kill | An outdated DamageOnContact. The package version is correct — if you edited it, re-import |
| Crusher falls forever | Auto Distance unticked and Slam Distance too big, or Ground Layer not set |
| Fire never turns on | Always On is ticked, or Start Delay is enormous |
| Nothing happens when you die | The OnDied event isn't wired |
| Lives counter stuck at 3 | OnLivesChanged wired to the static version — redo it and pick Dynamic |
| Ceiling shock hits you when standing | The collider is too tall. Make it thinner and raise it |
| Camera shows outside the level | No CinemachineConfiner2D, or no bounding shape assigned |