Guide 2 — Weenie(dog) Maze

Jax Keenan


What you're building

A dachshund navigates a maze eating treats. Every treat makes the dog longer. Run into your own body and it's over. Snake, but with a wiener dog and walls.

Yours is the smallest complete game in the class — twelve scripts, three prefabs — and it's the one that proves the kit isn't only for platformers. You'll finish the core loop faster than anyone, which means you have room to make the feel good rather than just functional.

Time: about ninety minutes to a playable game.


1. Before you start


2. Scripts you'll use

Movement & snake
GridMover · SnakeBody · TreatSpawner · MazeLoader · WrapAround (optional)

Collectibles
ItemType · Collectible · CollectionTracker

Managers
GameManager · SceneLoader · AudioManager · HUDController

You will not need: PlayerController2D, Health, Checkpoint, RespawnManager, or anything with gravity. Your dog doesn't fall and doesn't take damage — hitting yourself ends the run outright.


3. Build the dog's head

The head is the only thing the player controls. The body follows it.

  1. GameObject → Create Empty, name it DogHead.
  2. Tag → Player.
  3. Add a Sprite Renderer with your dog's head sprite (a coloured square is fine to start).
  4. Add:
Component Settings
Rigidbody2D Gravity Scale 0 · Body Type Kinematic · Freeze Rotation Z ✓
Box Collider 2D Is Trigger ✓ · size about 0.8 × 0.8
Player Input Actions → your input asset · Default Map Player · Behavior: Send Messages
GridMover see below
SnakeBody see section 5

GridMover settings — this is where the feel lives

Field Value What it does
Mode Continuous keeps moving forever; input only changes direction. This is Snake
Cell Size 1 must match your maze grid
Step Time 0.15 seconds per cell. Lower = faster
Speed Up Per Step 0.002 each treat makes it slightly quicker
Min Step Time 0.06 the speed cap
Blocking Layers Ground your walls
Snap On Start ✓
Prevent Reversal ✓ can't turn 180° into yourself
Flip Sprite ✓

Step Time is your difficulty dial. 0.15 is brisk. Try 0.2 for a gentler game, 0.12 if you want it tense. Change one thing and play it — don't tune three numbers at once.

Speed Up Per Step is optional but it's what makes a Snake game build tension. At 0.002, a hundred steps shaves 0.2 seconds off — noticeable but not sudden.

Why Kinematic?

The dog doesn't need physics — GridMover moves it by hand, cell by cell. A Dynamic rigidbody would fight that.


4. Build the body segment and the treat

Body segment prefab

  1. Empty GameObject BodySegment.
  2. Sprite Renderer — a slightly different sprite from the head. (Your dog is long. This is the joke. Lean into it: a stretched middle section reads better than a repeated circle.)
  3. Box Collider 2D, Is Trigger ✓, about 0.8 × 0.8.
  4. Layer → SnakeBody.
  5. No script. The segments are moved by SnakeBody on the head.
  6. Drag into Assets/MyGame/Prefabs/.

Optionally make a TailSegment prefab too — same thing with a tail sprite. SnakeBody will keep it at the end automatically.

The treat

  1. Right-click in Project → Create → GAME1303 → Item Type. Name it Treat.
    • Display Name: Treat
    • Score Value: 10
    • Pickup Sound: a crunch, if you have one
  2. Empty GameObject Treat in the scene.
  3. Sprite Renderer with your treat sprite.
  4. Circle Collider 2D, Is Trigger ✓, radius ~0.4.
  5. Collectible component:
    • Item Type → drag your Treat asset in
    • Amount: 1
    • Bob: ✓ (a gentle float makes it read as collectable)
  6. Drag into Prefabs.

5. Set up SnakeBody

Back on DogHead, fill in the SnakeBody component:

Field Value Note
Body Segment Prefab your BodySegment
Tail Prefab your TailSegment (or leave empty)
Starting Length 3 traditional
Segments Per Grow 1 2 if you want it to grow fast
Grace Segments 1 see below
Max Length 0 0 = unlimited
Self Collision Kills ✓ this is your fail condition
Hit Tolerance 0.5

Grace Segments — don't set this to 0

The segment immediately behind the head can't kill you. That sounds like cheating; it isn't. Without it, tight turns kill you in ways that feel like a bug rather than a mistake, because the head briefly overlaps the segment it just left.

If your playtesters say "that death wasn't fair," raise it to 2.

How it actually works

Worth understanding, because it's the clever part of your game: the head records the cell it leaves on every step. Segment 1 moves to where the head was, segment 2 to where segment 1 was, and so on down the line. It's a queue of positions, not a hundred little scripts — which is why it stays fast no matter how long the dog gets.


6. Build the maze

You have two options. Try the text one first — it's much faster to iterate on.

  1. Make a wall prefab: empty GameObject Wall, Sprite Renderer, Box Collider 2D (solid, not a trigger), Layer → Ground. Size 1 × 1.
  2. Empty GameObject in the scene called Maze, at position (0, 0, 0).
  3. Add MazeLoader:
Field Value
Layout Text paste the maze below
Cell Size 1
Centre On This Object ✓
Wall Prefab your Wall
Wall Char #
Player Char P
Move Player To Start ✓
Build On Start ✓
  1. Paste this into Layout Text to start:
#####################
#...................#
#.###.#####.#####.#.#
#.#...#...#.....#.#.#
#.#.###.#.#####.#.#.#
#.......#.......#...#
#.#####.#####.#####.#
#.....#...P...#.....#
#.###.#.#####.#.###.#
#...................#
#####################

# is a wall, . is empty, P is where the dog starts. Any other letter can be mapped to a prefab in the Marker Prefabs list.

  1. Press Play. The maze builds itself.

This is why it's worth doing: changing your maze is now editing a block of text, not dragging forty wall tiles. You can redesign the whole layout in thirty seconds, or paste one in from a spreadsheet.

Option B: draw it with a Tilemap

GameObject → 2D Object → Tilemap → Rectangular, paint your walls, add a Tilemap Collider 2D, set the Layer to Ground. Works fine — just slower to change.


7. Set up the treat spawner

  1. Empty GameObject TreatSpawner at the centre of your maze.
  2. Add a Box Collider 2D, Is Trigger ✓, sized to cover the whole play area.
  3. Add TreatSpawner:
Field Value
Treat Prefab your Treat prefab
Max Active 1
Respawn Delay 0
Spawn Area drag this object's own Box Collider 2D in
Snap To Grid ✓
Cell Size 1
Blocking Layers Ground and SnakeBody
Min Distance From Player 2
Attempts 40

Blocking Layers must include SnakeBody or treats will spawn underneath your own dog, which looks broken even though it technically works.

The win condition, free

When the spawner tries forty times and can't find an empty cell, it fires OnSpawnFailed. In Snake, that means the board is full — the player has won. Wire it to GameManager.LevelComplete and you have a victory state for zero extra work.


8. Camera and managers

Camera

Your whole maze fits on one screen, so you want a static camera — no Cinemachine needed.

  1. Select Main Camera.
  2. Set Projection → Orthographic.
  3. Set Size so the maze fits with a little margin. For the 21×11 maze above, try 6.5.
  4. Position it at (0, 0, −10).

That's it. Don't add CameraTargetAssigner — a camera that follows a snake is nauseating.

Managers

Empty GameObjects with one component each: GameManager, AudioManager, SceneLoader, CollectionTracker.

On CollectionTracker, leave Persist Across Scenes unticked — a single-scene game doesn't need it.


9. The HUD

  1. GameObject → UI → Canvas.
  2. Right-click Canvas → UI → Text - TextMeshPro. Name it ScoreText, top-left.
  3. Another one called LengthText, below it.
  4. Empty child of the Canvas called HUD with the HUDController component.
  5. Drag ScoreText into Score Text. Set Score Format to Score: {0}.
  6. For the length, add an Item Counter entry: Item Type → Treat, Text → LengthText, Format → Length: {0}.

Optionally add a GameOverPanel (a UI Panel with a Text and a Restart Button) and drag it into GameManager's Game Over Panel field. Wire the button's OnClick to GameManager.RestartLevel.


10. Wire it up

Five connections:

On this object Event Drag in Choose
Treat prefab → Collectible On Collected DogHead SnakeBody.Grow
DogHead → SnakeBody On Self Collision GameManager GameManager.GameOver
DogHead → SnakeBody On Self Collision AudioManager AudioManager.PlaySFX (string) → death
DogHead → GridMover On Blocked GameManager GameManager.GameOver
TreatSpawner On Spawn Failed GameManager GameManager.LevelComplete
CollectionTracker On Count Changed HUD HUDController.UpdateItemCount (Dynamic)

A design decision in row 4

GridMover.OnBlocked fires when the dog hits a wall. You have two choices:

Your pitch says "navigate a maze without running into yourself" — which suggests walls stop you and only yourself kills you. I'd start unwired and see how it plays. It's one connection either way.


11. First playtest

  1. The dog moves on its own the moment you press Play. If it doesn't, check Mode = Continuous and that Step Time isn't 0.
  2. Arrow keys change direction. If not: is Player Input on the head with Behavior = Send Messages?
  3. It can't reverse into itself. Prevent Reversal ✓.
  4. Three body segments follow the head. If they pile up in one spot, check Body Segment Prefab is assigned.
  5. A treat appears somewhere valid — not in a wall, not under the dog.
  6. Eating a treat makes the dog longer and the counter goes up.
  7. Running into your own body ends the game. Grow to about eight segments and deliberately turn into yourself.
  8. Walls stop you (or kill you, depending on your choice in section 10).

If segments lag oddly behind the head, that's normal for the first step or two while the path queue fills.


12. Then add

  1. Sound. Crunch on eat, a yelp on death. Named Sounds on AudioManager.
  2. Animation. Your dog is a sausage that turns corners — even two frames of leg movement sells it. Guide B §B6, but you only need Speed.
  3. A second maze. Duplicate the scene, paste a different layout into MazeLoader. Add both to Build Settings and wire GameManager.NextLevel.
  4. WrapAround — if you want open edges instead of walls on the outside. Add it to DogHead, set the area to your maze bounds.
  5. Multiple treats at once. Raise Max Active to 3 for a busier board.
  6. A high score. CollectionTracker.Score is already counting; save it with PlayerPrefs or ask your instructor about LevelProgress.

13. Design notes for your game specifically

Your maze design is your game design. With Snake, the walls decide everything: how much room the player has to escape their own tail, whether there are dead ends that become death traps as the dog grows, whether the centre is safer than the edges. Build three very different mazes and play them — you'll learn more in twenty minutes than from any amount of tuning numbers.

A maze changes Snake fundamentally. In classic Snake the danger is entirely self-inflicted and the space is open. Add walls and you get a route-planning game — the player has to think a few moves ahead about where the tail will be. That's a genuinely different and more interesting problem, and it's the reason your twist is a good one.

Watch out for the unwinnable state. Long dog plus narrow corridors equals no legal move. Some Snake games treat that as a fair loss; some avoid it with wider passages. Decide which you want, because your maze layout determines it.

The dachshund is doing real work. A long dog is funnier than a snake and it makes growth readable at a glance. Keep the proportions exaggerated.


14. Common problems

What you see What's wrong
Dog doesn't move at all Mode is Stepped, not Continuous
Dog moves but input does nothing Player Input missing, or Behavior isn't Send Messages
Presses get ignored during a turn That's the queue working — one input is remembered per step. Turn earlier
Segments all sit on top of each other Body Segment Prefab not assigned, or Starting Length is 0
Dies instantly on the first turn Grace Segments is 0. Set it to 1
Treats spawn inside walls Blocking Layers doesn't include Ground
Treats spawn under the dog Blocking Layers doesn't include SnakeBody, or the segment prefab isn't on that layer
Dog passes straight through walls Wall colliders are triggers, or walls aren't on Ground, or Blocking Layers isn't set on GridMover
Maze builds in the wrong place Centre On This Object unticked, or the Maze object isn't at (0,0,0)
Maze doesn't build Layout Text empty, or Wall Prefab not assigned
Dog moves half a cell off-grid Cell Size doesn't match between GridMover, MazeLoader and TreatSpawner. All three must agree

15. Checklist