Welcome to your first Unity 2D tutorial. We're about to breathe life into a simple catch game, one step at a time. No Unity experience required—just install Unity 6.0 LTS (or any 2D-capable version will work) and jump in. Tinker with the settings, hit Play, and watch your creation move. Ready to dive in? Let’s go!
We’ll start Unity Hub and create a new 2D project using the Universal 2D Core template so you have a clean foundation.
Open Unity Hub → Projects tab → New Project. Select “Universal 2D
Core” template (it includes basic 2D render pipeline, shaders and
physics support out of the box. The Universal 2D Core Template might
slightly differ depending on Unity version — if unavailable, use '2D
(URP)' or base '2D'). In Project Name, enter
CatchGame
(or choose your own name and folder). Click
“Create project” and wait for Unity to initialize.
💡 Tip: Pick a clear name and location now—this saves time when your project grows.
With Unity Editor open, the panels we’ll focus on are:
For this game, we’ll need four visuals: the ground, the catcher, the good item, and the bad item.
You can download a single image I’ve drawn that includes all of them. It’s just a starting point — you can improve or replace it later.
To import the image into Unity: right-click in the Assets window, choose Import New Asset..., find the downloaded file, and click Import.
💡 Tip: You can also drag the image file directly into the
Assets window from your folder. Sometimes that’s even
quicker.
💡 Tip: Start simple — you can edit graphics later as the game grows.
After importing the image catchgame-img.png
, Unity
usually sets it to Sprite Mode: Multiple by default.
But it’s a good idea to check this manually.
Why "Multiple"? Our image is a sprite sheet — it contains several game elements in one file (the ground, catcher, items). By slicing it, we turn those parts into separate usable sprites you can drag into the scene.
Select the image in the Assets folder. In the
Inspector, make sure that Sprite Mode is set
to Multiple
. If it’s not, set it manually and click
Apply.
Now open the Sprite Editor from the Inspector. In the Sprite Editor window, click Slice in the top-left corner. Leave all the settings as they are, and click the Slice button. Then click Apply.
Unity will automatically detect and slice the image into separate sprites. In most cases, it does a good job right away. If needed, you can manually adjust the slice boundaries by dragging them in the Sprite Editor.
💡 Tip: Want to use your own images? You can import four separate images instead of using the combined one. Just right-click in the Assets window, choose Import New Asset..., select your files, and click Import.
💡 Tip: Import. Alternatively, you can simply drag and drop image files directly into the Assets window — Unity will import them automatically.
It’s time to add the ground to our scene. In the
Assets folder, find the ground sprite (e.g.
catchgame-img_3
) and drag it into the
Scene view.
Make sure the Rectangle Tool is selected, then use it to resize the ground so it stretches across the bottom of the scene. You can adjust the sides by dragging them with the left mouse button.
In the Hierarchy, right-click on the object (e.g.
catchgame-img_3
) and rename it to Ground
.
Then go to the Inspector and set
Order in Layer
to 100
. This makes sure it
renders in front of other objects — like placing it on a higher visual
layer in a stack.
-1
or -10
to push objects into the
background.
Click Play to test the scene. The ground should be visible at the bottom. Then click Play again to return to edit mode.
Right now, our ground appears in the scene — but it’s not “solid” yet. Other GameObjects will fall right through it, because it has no Collider.
To fix this, we’ll add a collider component. Select the Ground object in the Hierarchy. In the Inspector, click Add Component → Physics 2D → Box Collider 2D. This adds a physical shape to the ground so other objects can interact with it.
Let’s add the catcher — our player — into the scene. Most steps are similar to what we did with the ground.
XC-catchgame-img_2
) in
the Assets folder and drag it into the
Scene view.
Player
.
Player
selected, go to the
Inspector and click Add Component →
Physics 2D → Box Collider 2D.
Next, let’s make the player react to gravity and other physics by adding a Rigidbody component.
With Player
still selected, click
Add Component again and choose Rigidbody 2D.
Then in the Rigidbody settings, set Interpolate to
Interpolate
to make movement smoother.
Let’s also tag our player to make it easier to recognize in scripts and logic later.
In the Inspector, set the Tag to
Player
(you might need to create it first from the Tag
manager).
The Order in Layer
value can stay at 0
—
that’s fine for now.
Click Play to test the scene. The player should fall down and land on the ground. Then click Play again to return to edit mode.
Let’s make our player move! We’ll do this by creating a simple C# script that changes the velocity of the player's Rigidbody2D based on keyboard input.
In the Assets folder, right-click and choose
Create → MonoBehaviour Script. Name it PlayerMove
(with a capital P and M). Be
careful with the spelling — the file name must match the class name
exactly.
PlayerMove
) and click Create and Add.
Open the PlayerMove.cs
file. At first, you’ll see a
default script template. We’ll replace it with the following logic:
Start()
runs once at the beginning.
Update()
runs every frame (not needed here).
FixedUpdate()
runs at a fixed time step (default: 0.02
sec) and is used for physics.
"Horizontal"
. Holding left or A gives a value close to
-1, right or D gives 1, and no key gives 0. These values are used to
calculate movement.
Vector2
(or Vector3
in 3D)
that defines speed and direction. Changing the velocity of a
Rigidbody2D makes an object move.
using UnityEngine;
public class PlayerMove : MonoBehaviour
{
// How fast the player moves (set this in Inspector)
public float speed = 5f;
// Link to the Rigidbody2D component
private Rigidbody2D rb;
// Value from left/right keys (A/D or arrows)
private float x;
// The movement we want to apply
private Vector2 move;
// Called once at the start
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
// Runs every physics frame (used for movement)
void FixedUpdate()
{
// Get input from keyboard (left/right)
x = Input.GetAxis("Horizontal");
// Move left or right, keep falling speed
move = new Vector2(x * speed, rb.linearVelocity.y);
// Apply movement to the player
rb.linearVelocity = move;
}
}
Now go back to Unity. Select the Player object in the Hierarchy. In the Inspector, click Add Component → Scripts → PlayerMove.
PlayerMove
script from the
Assets folder directly into the Inspector while the Player is
selected.
Set the Speed field in the script to something like
5
in the Inspector.
Click Play and try moving the player left and right using the A/D or arrow keys. Then click Play again to return to the Scene view.
Now let’s add something to catch! We'll start by creating a single falling object — a fish — that we’ll later use as a template for spawning more.
Fish
.
Good
. If the tag doesn’t exist yet, click
Untagged → Add Tag, create one called
Good
, then go back and assign it to the fish object.
5
so the fish
appears above the player catcher.
0.1
and
Interpolate to Interpolate
for
smoother motion.
Let’s also make sure our fish doesn’t stay in the scene forever if it’s missed. We’ll create a script to destroy it after a few seconds.
Right-click in the Assets window →
Create → MonoBehaviour Script. Name it TimeDestroyer
.
using UnityEngine;
public class TimeDestroyer : MonoBehaviour
{
// How long the object stays in the scene
public float aliveTimer = 5f;
// Called once when the script starts
void Start()
{
Destroy(gameObject, aliveTimer);
}
}
Attach this script to the Fish object (Add Component
→ Scripts → TimeDestroyer). Set
Alive Timer to 5
in the Inspector.
Finally, let’s make this fish into a Prefab so we can easily clone it later.
To create a prefab, drag the Fish
object from the
Hierarchy into the Assets folder.
Unity will generate a blue prefab icon.
Now that we have a good item (Fish), let’s create a bad one — a Bomb — that the player should avoid. We’ll reuse the Fish prefab and make a few changes.
Fish
in the Hierarchy and rename it
to Bomb
.
Bad
.
Bad
tag doesn't exist:
Bad
Bomb
from the Hierarchy into
the Assets folder to create a new prefab.
Bomb
from the scene — we’ll spawn
it later from the prefab.
Bad
, and saved as a prefab.
Let’s add some movement from above. In this step, we’ll create a simple item spawner: it will drop random objects (like a fish or a bomb) from above the screen.
We’ll start by placing two invisible GameObjects to define the spawn area. One on the left, one on the right — they’ll mark where items can appear.
In the Hierarchy, right-click and choose
Create Empty. Make sure no objects are selected before, or
Unity might parent it by accident. Rename this object to
Spawner
, and move it above the camera view on the left.
Duplicate this object (right-click → Duplicate), move the
copy to the right side, and rename it RightSide
. These
two will define our spawn zone.
Select the Spawner
and check in the
Inspector that its Z-position is 0
. This
makes sure it’s visible in the game view. You can also assign a small
icon to each object to see them better in the scene.
Now let’s write the script. In the Assets window,
right-click →
Create → MonoBehaviour Script and name it
ItemSpawn
. Then attach it to the
Spawner
object.
This script will spawn a random item (Fish or Bomb) between the X
positions of Spawner
and RightSide
. The
spawn Y-position will match Spawner
's Y, and Z will stay
at 0.
💡 Tip: Unity’s 2D view still uses 3D space. The default camera is at Z = -10, so objects must be at Z = 0 or higher to appear.
using UnityEngine;
public class ItemSpawn : MonoBehaviour
{
// Right edge of the spawn zone
public GameObject RightSide;
// List of item prefabs to spawn (e.g. fish, bomb)
public GameObject[] items;
// Delay before first item and time between spawns
public float startDelay, repeatRate;
void Start()
{
// Call Spawn() repeatedly after a delay
InvokeRepeating("Spawn", startDelay, repeatRate);
}
void Spawn()
{
// Pick a random position between Spawner and RightSide
Vector3 pos = new Vector3(
Random.Range(transform.position.x, RightSide.transform.position.x),
transform.position.y,
0
);
// Spawn a random item from the list at that position
Instantiate(items[Random.Range(0, items.Length)], pos, transform.rotation);
}
}
After attaching the script, drag the RightSide
object
into the script field in the Inspector. Then expand
the Items
array and drag in the Fish
and
Bomb
prefabs. Set both Start Delay
and
Repeat Rate
to 2
for now (you can tweak this
later).
That’s it! Press Play and see how the items begin to fall. You now have a dynamic spawner — a small step that brings the game to life.
Now let’s make the basket actually “catch” things. Unity has built-in
2D physics, and since our objects have
Collider2D
components, we can use trigger-based collision
to react when items touch the player.
We’ll write a script that checks whether a falling object is “good” or “bad” using its tag. If it’s good, we’ll increase the score — if bad, we’ll decrease it. In both cases, the item disappears after touching the player.
Right-click in the Assets window →
Create → MonoBehaviour Script. Name it
ItemChecker
and open the file.
This script uses OnTriggerEnter2D()
— Unity will
automatically call this method when something with a
Collider2D
touches our object’s trigger area.
using UnityEngine;
public class ItemChecker : MonoBehaviour
{
// Player's score
public int score;
// Runs when something touches the player's trigger area
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.tag == "Good")
{
score += 10;
Destroy(other.gameObject);
}
if (other.gameObject.tag == "Bad")
{
score -= 10;
Destroy(other.gameObject);
}
}
}
Now attach the ItemChecker
script to your player object
(the basket).
Unity will now detect collisions with the trigger and update the score accordingly. You can even see the score change live in the Inspector while the game runs.
That’s it! You’ve built the core of a 2D catch game — items fall, the player moves, collisions are detected, and the score updates. A small prototype — but full of potential.