Skip to main content

Stage 1: The Courtyard and the First Enemy

Course progressStage 1 of 10
~45 min
Build

the courtyard background and a slime that crawls toward your castle gate

Learn

how a Sprite Renderer shows art, and how transform.position with Time.deltaTime makes smooth motion

Ship

one enemy that walks across the courtyard at a speed you control

The big idea

Every Unity Scene is a kind of graph paper. Positions are measured in units from the center point (0, 0). X grows to the right, Y grows up. A sprite at x = 6 sits to the right; a sprite at x = -8 sits near the left edge, where our castle gate will live.

To put art on screen, a GameObject needs a Sprite Renderer — the component that says "draw this picture here." To make something move, we change its transform.position a little bit on every frame. A frame is one pass of the game loop; Unity runs Update() once per frame, many times per second.

There's a catch: different computers run at different frame rates. If we moved the slime a fixed amount each frame, it would crawl on a slow laptop and sprint on a fast one. The fix is Time.deltaTime — the seconds since the last frame. Multiply by it and movement becomes per second instead of per frame, so it looks the same everywhere.

New words
Unit
Unity's measure of distance. The camera shows about 16 units across by default.
Sprite Renderer
The component that draws a sprite on a GameObject.
Order in Layer
Which sprite draws on top when two overlap — higher number is in front.
Update()
A method Unity runs once every frame while the game plays.
Time.deltaTime
Seconds since the last frame. Multiply movement by it to make speed framerate-independent.
Before you start

Finish Setup — you need the project open and tilemap.png sliced into sprites.

Build it

Step 1 — Lay down the courtyard

Your game needs a board to read against before anything moves on it. Drag a grass tile sprite from your sliced tilemap into the Scene a few times to make a strip of ground, or drop one in as a simple background for now. Keep it behind everything else.

Build this GameObject

Courtyard

2D Sprite
Open recipe
Sprite
a grass/floor tile from your sliced tilemap
Position
(0, 0, 0)
Order in Layer
0 (behind everything)
Components to add
  • Sprite Renderer

A single tile is fine for now. Stage 3 turns the ground into a real clickable grid.

Press Play. Nothing moves yet, but you should see your courtyard centered in the Game view.

Step 2 — Drop in a slime

The slime is our first enemy. It's just a GameObject with the slime sprite, placed at the right edge so it has room to crawl left toward the gate.

Build this GameObject

Slime

2D Sprite
Open recipe
Sprite
the green slime from your sliced tilemap
Position
(7, 0, 0)
Order in Layer
2 (in front of the courtyard)
Components to add
  • Sprite Renderer
  • Enemy.cs (added in Step 3)

You should see the slime sitting near the right edge. It won't move until we give it a script.

Step 3 — Make the slime walk

Now we write Enemy.cs and attach it to the slime. We build it in three passes, and you press Play after each one so you always know it's working before adding more.

Pass 1 — prove the script runs. Select the Slime, click Add Component → New Script, name it Enemy, and write:

using UnityEngine;

public class Enemy : MonoBehaviour
{
public float speed = 1.5f;

void Update()
{
Debug.Log("walking");
}
}

Press Play. The Console prints walking over and over — that means Update() is running on the slime. Stop.

Pass 2 — actually move. Replace the Debug.Log line with a move:

void Update()
{
transform.position += Vector3.left * speed * Time.deltaTime;
}

Press Play. The slime now glides left across the courtyard. While it plays, change speed in the Inspector and watch it speed up or slow down — that field is public, so Unity shows it as an editable value.

Pass 3 — notice the gate. When the slime reaches the gate's x position, we want to know. Add a gateX and a check:

Script anatomy

The full script, line by line

The finished Stage 1 enemy: it walks left every frame and reports when it reaches the gate line.

using UnityEngine;

public class Enemy : MonoBehaviour
{
public float speed = 1.5f;
public float gateX = -8f;

void Update()
{
transform.position += Vector3.left * speed * Time.deltaTime;

if (transform.position.x <= gateX)
{
Debug.Log("An enemy reached the gate!");
}
}
}
  1. Lines 5–6Public fields = Inspector sliders

    speed and gateX are public, so you can tune them in the Inspector without touching code. gateX is where the castle gate will sit.

  2. Line 10Framerate-independent movement

    Vector3.left is (-1, 0, 0). Multiplying by speed and Time.deltaTime moves the slime 'speed' units per second, the same on any computer.

  3. Lines 12–15Reaching the gate

    Once the slime's x is at or past gateX, we log a message. In Stage 9 this is where the player loses a life instead.

Press Play and let the slime walk off the left edge — the Console prints the gate message. That message is a placeholder; later stages turn it into real consequences.

Understand it

Moving a sprite by editing transform.position in Update() is the simplest kind of motion in Unity, and it's the right choice here. We could add a Rigidbody2D and use physics, but our slime doesn't bounce, fall, or get pushed — it just marches. Plain position changes are cheaper and easier to reason about, and they keep the slime exactly on its lane.

The Time.deltaTime habit is the important takeaway. Almost every "move/rotate/grow over time" line you write in Unity is multiplied by Time.deltaTime. Forget it and your game's speed becomes a lottery based on the player's hardware.

Try this

Learning beat

Try this

Three short experiments. Predict before you run, then test your guess.

Predict first

Set speed to 5 in the Inspector. Before you press Play, decide: will the slime reach the gate noticeably faster, and will it still move smoothly? Run it and check.

Compare

Remove * Time.deltaTime from the move line and run it. The slime rockets across the screen. Put it back. That one term is the difference between "1.5 units per second" and "1.5 units per frame" (90+ per second).

Connect

Stage 2 spawns many slimes on different lanes. Look at how this one slime is just a GameObject with a sprite and a script — what would you need to make a hundred of them without placing each by hand?

Test your stage

  • The courtyard shows in the Game view and the slime starts at the right edge.
  • The slime glides left smoothly (no stutter, no teleporting).
  • Changing speed in the Inspector during Play changes how fast it moves.
  • The Console prints the gate message when the slime reaches the left side.
  • Design check. Watch the slime cross once. Does the speed feel like a threat the player has time to react to, or too fast/too slow to be fair? Pick a speed that feels right.

If it breaks

  • I can't see the slime. Two usual causes: its Order in Layer is below the courtyard (raise it to 2), or it's off-screen — check its Position is around (7, 0, 0) and that the Main Camera is centered on (0, 0).
  • The slime doesn't move. The Enemy script probably isn't attached, or you're not in Play mode. Select the slime and confirm Enemy (Script) shows in the Inspector.
  • The slime moves the wrong way. Vector3.left goes toward negative x (left). If yours goes right, you may have used Vector3.right.
  • It moves in huge jumps. You likely dropped Time.deltaTime. Movement must be speed * Time.deltaTime.
  • A red error in the Console. Read the first line — usually the class name doesn't match the file name, or a semicolon or brace is missing. Unity won't run any script while there's a compile error.