Home

Unity 2D Tutorial for Beginners: Create a Space Shooter Game

Welcome to this step-by-step Unity 2D tutorial for beginners! In this guide, we’ll build a simple but exciting game — a classic space shooter. You’ll learn how to move the ship, shoot at enemies, and use Unity’s built-in 2D physics.

No prior experience needed — this tutorial is designed for complete beginners. Just install Unity 6.0 LTS (or any recent version with 2D support) and follow along.

We’ll go through each step calmly and clearly, with explanations and examples. If you’re starting your journey into Unity game development, this tutorial is perfect for you.

Step 1. Project Setup

Let’s start by creating a new Unity 2D project using the 2D (Built-in Core) template. This will give us a clean scene with built-in support for sprites, colliders, and 2D physics.

💡Tip: You can name your project SpaceShooter or pick something fun — the name is yours.

Step 2. Importing the Sprite Sheet

Let’s bring our art into Unity.

Download the image file called space-sprites.png — it contains all the graphics we’ll need: enemies, player ship, projectile, and more.

Preview of the space shooter sprite sheet
Click the image to download it.

Open your Unity project and import the file:

Once imported, select space-sprites.png in the Assets window. In the Inspector panel, make sure:

💡Tip: “Multiple” means the image contains more than one sprite — like a sheet with multiple characters.

Unity should automatically slice the image when imported. If not, click on Open Sprite Editor, then use the Slice button with Type: Automatic selected. Then click Apply.

💡Tip: If automatic slicing fails, you can switch to grid-based slicing or adjust slices manually. Just be sure to click Apply before closing the editor.

Unity interface showing the imported and sliced space sprites
Sprites are automatically sliced and now appear as separate assets. You can always open the Sprite Editor to adjust or slice manually if needed.

Step 3. Create and Move the Player Ship

Let’s build the ship we’ll be flying. In this game, we won’t use keyboard controls — we’ll use the mouse. The ship should fly toward the point we click.

Start by dragging the blue ship sprite into the scene. Unity will create a new GameObject. Rename it to Player, and set its tag to Player.

Adjust the size of the ship using the Rect Tool directly in the scene or change the Scale values in the Inspector to make it look just right.

Now we’ll add physics. With Player selected, click Add Component and add:

In the Rigidbody 2D settings:

Next, create a new script called PlayerMove and attach it to the Player object.

Tip: Right-click inside the Assets folder → Create → C# Script, name it PlayerMove, then double-click the script to open it in Visual Studio or your preferred editor.

In this script, we detect where the player clicked with the mouse, convert that point from screen coordinates to world (scene) coordinates, and then move the ship toward that point. Simple — the ship always flies to wherever you click.


using UnityEngine;

public class PlayerMove : MonoBehaviour
{
    // The point where the ship should move (clicked by the player)
    Vector3 clickPos;

    // The vector direction towards the target point
    Vector3 move;

    // Ship movement speed
    public float speed = 1f;

    // Reference to Rigidbody2D
    Rigidbody2D rb;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        // At the start of the game, set the target to current position
        // so the ship doesn't fly off immediately
        clickPos = transform.position;
    }

    void Update()
    {
        // Each frame, check if the left mouse button is pressed,
        // then update the target point
        if (Input.GetMouseButton(0))
        {
            // Convert mouse position from screen to world coordinates
            clickPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        }

        // Calculate the direction vector from current to target position
        move = clickPos - transform.position;
    }

    void FixedUpdate()
    {
        // Each physics frame, set the velocity to move toward the target
        rb.linearVelocity = new Vector2(move.x, move.y) * speed;
    }
}

Save the script and return to Unity. In the Inspector, set Speed to 1. Press Play and test it — the ship should now move to wherever you click.

💡Tip: The mouse position is given in screen coordinates — in pixels. To convert it into a usable position in the scene, use Camera.ScreenToWorldPoint. It returns a point in the world, but note: the Z-value will match the camera’s Z-position. Since we’re working in 2D, this is usually fine — we only care about X and Y.

Player object with Rigidbody2D, Circle Collider 2D, and PlayerMove script
The ship is set up with physics and movement script. Now it follows mouse clicks smoothly.

Step 4. Add the Laser

Now we’ll give our ship something to shoot. Let’s add a laser.

Drag the orange laser sprite into the scene. Unity will create a new GameObject. Rename it to Laser. In the Inspector, set its Order in Layer to -10 so it's drawn behind the ship. Resize it if needed — just make sure it looks small and clean.

Add the following components and settings to the Laser object:

Now create a new MonoBehaviour script named LaserShot. This script will push the laser upward right after it’s spawned and destroy it once it leaves the screen.


using UnityEngine;

public class LaserShot : MonoBehaviour
{
    // Reference to Rigidbody2D to apply force
    Rigidbody2D rb;

    // The force that will push the laser upward
    public float force = 5f;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        
        // Create a vector pointing up (Y) with the given force
        Vector3 direction = new Vector3(0, force, 0);

        // Instantly apply an impulse to make the laser fly upward
        rb.AddForce(direction, ForceMode2D.Impulse);
    }

    void OnBecameInvisible()
    {
        // When the laser leaves the camera view, destroy it
        Destroy(gameObject);
    }
}

Attach this script to the Laser object and set the Force value to something like 5.

Finally, drag the Laser GameObject into the Assets window to create a prefab. Unity will generate it automatically. You can now delete the laser from the scene — we’ll spawn it later by script.

Laser object in Unity with components and prefab
The laser is ready — with physics, a movement script, and saved as a prefab.

Step 5. Add Shooting to the Player

The laser can fly — now let’s make the ship shoot it.

We’ll use a new script to spawn a laser whenever the player presses the right mouse button. To prevent too many lasers spawning at once, we’ll add a short delay between shots using a coroutine.

Create a new MonoBehaviour script named PlayerShoot. It will look like this:


using UnityEngine;
using System.Collections;

public class PlayerShoot : MonoBehaviour
{
    // The laser prefab that we'll spawn when shooting
    public GameObject laser;

    // Delay between shots (reload time)
    public float delayTime = 0.5f;

    // Flag: can we shoot right now?
    bool canShoot = true;

    void Update()
    {
        // Every frame check: if the right mouse button is pressed
        // and we are allowed to shoot (reload is done)
        if (canShoot && Input.GetMouseButton(1))
        {
            // Block shooting until the cooldown finishes
            canShoot = false;

            // Instantiate (clone) the laser prefab at the player's position
            Instantiate(laser, transform.position, transform.rotation);

            // Start the reload timer
            StartCoroutine(NoFire());
        }
    }

    // Coroutine — waits for delayTime seconds, then allows shooting again
    IEnumerator NoFire()
    {
        yield return new WaitForSeconds(delayTime);
        canShoot = true;
    }
}

Attach the PlayerShoot script to the player object. Drag the Laser prefab into the script's Laser field. Set Delay Time to 0.5.

Press Play and try it — your ship should now fire a laser when you right-click!

Unity editor showing the PlayerShoot script with laser prefab and delay time
The PlayerShoot script is set up with a laser prefab and shooting delay.

Step 6. Add Moving Enemy Mines

Now let’s add some danger. We’ll use a small enemy mine that floats downward toward the player.

Drag the mine sprite into the scene. Unity will create a new GameObject — rename it to Mine. Set its Order in Layer to -5 (between the ship and laser). Resize it if needed.

Add the following components and settings to the mine:

Create a new tag named Enemy and assign it to the mine.

Now create a new MonoBehaviour script called MineMove. It will move the mine downward, destroy it when it leaves the screen, and restart the scene if it collides with the player.


using UnityEngine;
using System.Collections;
// This library is needed to manage (reload) scenes
using UnityEngine.SceneManagement;

public class MineMove : MonoBehaviour
{
    // Speed of the mine's movement
    public float speed = 1f;
    Rigidbody2D rb;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        // Create a vector pointing downward (along Y)
        Vector3 move = new Vector3(0, -1, 0);
        // Set the Rigidbody's linear velocity to move the mine downward
        rb.linearVelocity = move * speed;
    }

    void OnBecameInvisible()
    {
        // Destroy the mine if it goes off screen
        Destroy(gameObject);
    }

    void OnCollisionEnter2D(Collision2D collision)
    {
        // Check if the mine collided with something tagged "Player"
        if (collision.gameObject.tag == "Player")
        {
            // Reload the current scene
            SceneManager.LoadScene(SceneManager.GetActiveScene().name);
        }
    }
}

Attach the script to the Mine object. Set Speed to 1. Then drag the mine into the Assets window to create a prefab. You can now delete it from the scene — we’ll spawn it later.

Enemy mine prefab setup in Unity with Rigidbody and movement script
The enemy mine prefab is ready with physics, tag, and movement logic.

Step 7. Spawning Mines Automatically

Now let’s automate the enemy waves. We’ll set up a spawner that creates new mines at random positions.

Go to GameObject → Create Empty. Unity will create a new GameObject in the scene. Rename it to MineSpawner. You can assign it a custom icon to make it easier to see in the Scene view.

Move the MineSpawner to the top-left of the visible screen area. Make sure its Z position is 0, since this is a 2D game.

With MineSpawner selected, press Ctrl + D (or right-click → Duplicate). Rename the new object to RightPosition and make it a child of MineSpawner. Move it to the top-right of the screen. Set its Z position to 0 as well.

Now create a new MonoBehaviour-script and name it ObjectSpawner. It will randomly pick an X-position between the two points and spawn mines there on a delay.


using UnityEngine;
using System.Collections;

public class ObjectSpawner : MonoBehaviour
{
    // Rightmost point used to calculate random X position
    public Transform RightPosition;

    // Delay between spawns
    public float spawnDelay = 5f;

    // The object to spawn
    public GameObject Item;

    void Start()
    {
        // Call the spawn function repeatedly
        InvokeRepeating("Spawn", spawnDelay, spawnDelay);
    }

    void Spawn()
    {
        // Choose a random X position between spawner and right edge
        Vector3 spawnPos = new Vector3(
            Random.Range(transform.position.x, RightPosition.position.x),
            transform.position.y,
            0);

        // Spawn the object at the calculated position
        Instantiate(Item, spawnPos, transform.rotation);
    }
}

Attach this script to the MineSpawner object. Drag RightPosition into the Right Position field, and drag the Mine prefab into the Item field. Set Spawn Delay to 5.

Press Play — mines will now appear at random positions from the top of the screen.

MineSpawner object in Unity with spawner script and spawn fields filled
The MineSpawner will now generate mines between two points on the top edge of the screen.

Step 8. Adding Health and Damage

Right now, lasers fly through the mines without any effect. Let’s fix that by giving mines health points and making lasers deal damage.

Create a new MonoBehaviour script and name it HpController. This script holds a health value and removes the object when it reaches zero.


using UnityEngine;

public class HpController : MonoBehaviour
{
    // Amount of health points (HP)
    public int hp = 3;

    // Method that reduces health by the amount of damage taken
    void MakeDamage(int damage)
    {
        // Subtract the incoming damage from the current health
        hp -= damage;

        // If health drops to zero or below — destroy this object
        if (hp <= 0)
        {
            Destroy(gameObject);
        }
    }
}

Select the Mine prefab in the Assets window and add the HpController script to it. Set hp to 3.

Now open the LaserShot script. We’ll check for collisions and send damage to the enemy.


using UnityEngine;

public class LaserShot : MonoBehaviour
{
    // Reference to Rigidbody2D to apply force
    Rigidbody2D rb;

    // The force that pushes the laser upward
    public float force = 10f;

    // Amount of damage the laser deals to enemies
    public int damage = 1;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        // Create a vector pointing upward with the given force
        Vector3 direction = new Vector3(0, force, 0);

        // Apply an immediate impulse so the laser flies up
        rb.AddForce(direction, ForceMode2D.Impulse);
    }

    void OnBecameInvisible()
    {
        // Destroy the laser when it leaves the screen
        Destroy(gameObject);
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        // Check if the laser hit an object tagged "Enemy"
        if (other.gameObject.tag == "Enemy")
        {
            // Send a "MakeDamage" message to the enemy, passing in the damage value.
            // If the object doesn't have that method, no error will occur.
            other.gameObject.SendMessage("MakeDamage", damage, SendMessageOptions.DontRequireReceiver);

            // Destroy the laser after it hits
            Destroy(gameObject);
        }
    }
}

Select the Laser prefab and set the Damage value in the Inspector to 1.

Press Play and test the scene. Mines should now take 3 hits to be destroyed.

Mine prefab with HpController script and damage handling
The Mine prefab now has health and can be destroyed by laser shots.

Step 9. Creating an Enemy Ship and Its Rocket

Let’s add an enemy that will be able to shoot back.

Drag the enemy ship sprite into the scene. Unity will automatically create a new object. Rename it to Enemy-1. Change its tag to Enemy. Set Order in Layer to -5 so the enemy appears above the lasers. Adjust its size if needed.

Add the following components and settings to the object:

Now add the HpController script to the enemy ship and set its HP to 1. Then add the MineMove script to the same object and set its speed to 1 (or any other value you like) so the saucer moves smoothly downward.

Then drag Enemy-1 into the Assets window to create a new enemy prefab. After creating the prefab, you can delete Enemy-1 from the scene — it will stay saved in your project as a prefab.

Enemy prefab with Rigidbody 2D, Circle Collider 2D
Enemy prefab with Rigidbody 2D, Circle Collider 2D, and the HpController, MineMove script.

Now let’s give this enemy a rocket. Drag the rocket sprite into the scene and rename it to Rocket. Set its Order in Layer to -10. Add a Box Collider 2D and enable Is Trigger. Add a Rigidbody2D with Gravity Scale = 0 and Interpolate = Interpolate.


using UnityEngine;

public class EnemyBullet : MonoBehaviour
{
    // Reference to the player object
    GameObject player;

    // Reference to Rigidbody2D for applying force
    Rigidbody2D rb;

    // The impulse force that will push the missile
    public float force = 3f;

    // The amount of damage the missile deals on hit
    public int damage = 1;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        // Find the player in the scene by its "Player" tag
        player = GameObject.FindWithTag("Player");

        if (player != null)
        {
            // Calculate direction vector from missile to player
            Vector3 dir = player.transform.position - transform.position;

            // Rotate the missile to face the player
            transform.up = dir;

            // Apply an impulse in the missile's local "up" direction
            rb.AddRelativeForce(transform.up * force, ForceMode2D.Impulse);
        }
        else
        {
            // If there is no player, destroy the missile
            Destroy(gameObject);
        }
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        // Check if the missile collided with the player
        if (other.gameObject.tag == "Player")
        {
            // Tell the player to take damage
            other.gameObject.SendMessage("MakeDamage", damage, SendMessageOptions.DontRequireReceiver);

            // Destroy the missile after hitting the player
            Destroy(gameObject);
        }
    }

    void OnBecameInvisible()
    {
        // Destroy the missile if it goes off screen
        Destroy(gameObject);
    }
}

Add the EnemyBullet script to the Rocket. Set Force to 3 and Damage to 1. Create a prefab by dragging it into the Assets window. Then delete the rocket from the scene.

Rocket prefab with EnemyBullet script and physics components
The enemy rocket prefab is ready — it will find the player, rotate, and fly forward.

Step 10. Making the Enemy Shoot

Now it’s time to give the enemy ship some firepower. We’ll add a shooting script that periodically spawns a rocket and lets the rocket handle the rest.

Create a new MonoBehaviour script and name it EnemyShoot. This is a simple script that will periodically spawn missiles, as long as there is a player in the scene.


using UnityEngine;
using System.Collections;

public class EnemyShoot : MonoBehaviour
{
    // The bullet prefab to spawn
    public GameObject bullet;

    // Delay between shots (seconds)
    public float fireDelay = 2f;

    // Reference to the player in the scene
    GameObject player;

    // Flag: can the enemy shoot right now?
    bool canShoot = true;

    void Start()
    {
        // Find the player by tag "Player"
        player = GameObject.FindWithTag("Player");
    }

    void Update()
    {
        // If allowed to shoot and the player exists
        if (canShoot && player != null)
        {
            // Block shooting until after the delay
            canShoot = false;

            // Create a bullet at the enemy's position
            Instantiate(bullet, transform.position, Quaternion.identity);

            // Start the coroutine to wait before next shot
            StartCoroutine(firePause());
        }
    }

    IEnumerator firePause()
    {
        // Wait for fireDelay seconds
        yield return new WaitForSeconds(fireDelay);

        // Allow shooting again
        canShoot = true;
    }
}

Select the Enemy-1 prefab in the Assets window. Add the EnemyShoot script to it. In the Bullet field, drag the Rocket prefab. Set Fire Delay to 2.

Enemy-1 prefab with EnemyShoot script and Rocket assigned
The Enemy-1 prefab is now armed and ready to shoot rockets toward the player.

Step 11. Spawning Enemies Alongside Mines

Our Enemy-1 prefab is ready. Now let’s make them appear in the scene just like the mines. Instead of creating a second spawner, we’ll improve the existing one and allow it to choose randomly between multiple objects.

Open the ObjectSpawner script and update it to use an array of prefabs:


using UnityEngine;

public class ObjectSpawner : MonoBehaviour
{
    // Right boundary for spawning (left is the object with this script)
    public Transform RightPosition;

    // Delay between spawns (seconds)
    public float spawnDelay;

    // Array of prefabs to randomly pick from
    public GameObject[] Item;

    void Start()
    {
        // Repeatedly call the Spawn function with the given delay
        InvokeRepeating("Spawn", spawnDelay, spawnDelay);
    }

    void Spawn()
    {
        // Pick a random point between our position and the right boundary on the X axis
        Vector3 spawnPos = new Vector3(
            Random.Range(transform.position.x, RightPosition.position.x),
            transform.position.y,
            0
        );

        // Randomly select one prefab from the array
        int i = Random.Range(0, Item.Length);

        // Create the selected object at the calculated position
        Instantiate(Item[i], spawnPos, transform.rotation);
    }
}

In the MineSpawner object (in the scene), look at the updated Item list. Add the Mine and Enemy-1 prefabs to the array. Unity will handle the size of the list automatically.

MineSpawner object with updated spawn list containing Mine and Enemy-1
The spawner now picks randomly between Mine and Enemy-1 prefabs. Let the chaos begin.

Step 12. Creating a Health Bar

Our player still has no visible health. Let's add a simple UI to show the current health on screen. We’ll create a horizontal health bar using Unity’s built-in UI system.

Go to GameObject → UI → Image. This will create a new Canvas with an Image object inside it. Rename the Image to HealthBar.

Select the Canvas. In the Inspector, under the Canvas Scaler component, set: UI Scale Mode to Scale With Screen Size.

Now double-click on the Canvas in Hierarchy — the scene view will zoom out and show the UI area. Select the HealthBar and use the Rect Tool to stretch it into a bar shape. You can place it wherever it fits your layout.

With HealthBar selected:

Note: Fill Method and Origin might be set automatically when you choose Filled. You can experiment with them later, but leave them as they are for now.

Canvas with HealthBar UI Image configured as a horizontal filled bar
The HealthBar is now part of the Canvas. We’ll control its fill value in the next step.

Step 13. Controlling Player Health

Now let's link the health indicator to the gameplay. We'll write a script that tracks the player's damage and updates the health bar. The Image component on the HealthBar object has a fillAmount property, which controls how full the sprite appears. By calculating the percentage of remaining health, we'll adjust fillAmount to visually represent the current HP on our health bar.

Create a new MonoBehaviour script and name it PlayerHp:


using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class PlayerHp : MonoBehaviour
{
    // Reference to the health bar UI object (an Image)
    public GameObject HealthBar;
    // Reference to the Image component to change fillAmount
    Image img;

    // Current health
    public int hp;
    // Maximum health (for normalizing the bar)
    float maxHp;

    void Start()
    {
        // Get the Image component from the HealthBar object
        img = HealthBar.GetComponent<Image>();
        // Store the maximum health value
        maxHp = hp;
        // Set initial fill amount of the health bar
        img.fillAmount = hp / maxHp;
    }

    // Method to take damage
    void MakeDamage(int damage)
    {
        // Subtract damage from current health
        hp -= damage;

        // If health drops to zero or below, restart the scene
        if (hp <= 0)
        {
            SceneManager.LoadScene(SceneManager.GetActiveScene().name);
        }

        // Update the fill amount of the health bar
        img.fillAmount = hp / maxHp;
    }
}

Now go to the scene and select your Player object. Add the PlayerHp script to it. Drag the HealthBar (from inside the Canvas) into the Health Bar field. Set the HP value to 10.

Player object with PlayerHp script connected to HealthBar and initial HP value
The player now has health tracking and can be destroyed when it runs out.

Step 14. Set Background Color

Let’s start by turning the background of our scene to deep space black. Select Main Camera in the Hierarchy. In the Inspector, go to the Camera section and set the Background color to black.

Step 15. Add Moving Stars with Particle System

For a nice space effect, we’ll use Unity’s built-in Particle System to simulate moving stars.

  1. Go to GameObject → Effects → Particle System.
  2. Rename the new object to Stars.
  3. Set its Z Position to 10 and X Rotation to 90.
  4. Move it upward so it’s above the visible camera area.
  5. In the Particle System settings:
    • Enable Prewarm.
    • Adjust Start Lifetime so particles travel across the full screen.
    • Set Start Speed to your liking.
    • Set Start Size to 0.2 (or as preferred).
  6. Under the Shape module:
    • Set Shape to Box.
    • Set X value to 15 — this makes the starfield wide.
  7. In the Renderer module:
    • Set Order in Layer to -100 so stars render far behind the scene.
Stars Particle System placed above scene with adjusted settings
The stars now gently drift behind the game scene — the galaxy is alive.

Step 16. Add Shooting Sound

Let’s give the enemy’s rocket a proper shooting sound. When a rocket is spawned, we will play a short sound clip using Unity’s built-in audio system.

You can download the sound effects used in this tutorial here:

Import the downloaded audio files into Unity.

In the EnemyBullet script, we use the PlayClipAtPoint method to play sounds.

This plays the chosen audio file right when the rocket is launched. It creates a temporary audio object in the scene, which plays the sound and then automatically disappears.

Here is the complete updated EnemyBullet script with sound support:


using UnityEngine;

public class EnemyBullet : MonoBehaviour
{
    // Reference to the player (found by tag "Player")
    GameObject player;

    // Reference to the Rigidbody2D for physical movement
    Rigidbody2D rb;

    // Force that pushes the bullet
    public float force = 3f;

    // Damage the bullet deals
    public int damage = 1;

    // Sound to play when bullet is fired
    public AudioClip BulletSound;

    void Start()
    {
        // Get the Rigidbody2D component
        rb = GetComponent<Rigidbody2D>();

        // Find the player by tag
        player = GameObject.FindWithTag("Player");

        // If player is found
        if (player != null)
        {
            // Calculate direction to the player
            Vector3 dir = player.transform.position - transform.position;

            // Rotate bullet to look at the player
            transform.up = dir;

            // Apply force to move bullet toward the player
            rb.AddRelativeForce(transform.up * force, ForceMode2D.Impulse);

            // Play shooting sound at bullet position
            AudioSource.PlayClipAtPoint(BulletSound, transform.position);
        }
        else
        {
            // If player not found, destroy the bullet
            Destroy(gameObject);
        }
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        // If the bullet hits the player
        if (other.gameObject.tag == "Player")
        {
            // Send damage message to the player
            other.gameObject.SendMessage("MakeDamage", damage, SendMessageOptions.DontRequireReceiver);

            // Destroy the bullet
            Destroy(gameObject);
        }
    }

    void OnBecameInvisible()
    {
        // Destroy bullet if it goes off-screen
        Destroy(gameObject);
    }
}

Now select the Rocket prefab. Assign LaserSound to the Bullet Sound field in the EnemyBullet script.

💡 You can replace this sound with your own by importing any .wav file and assigning it to the AudioClip field.

Enemy rocket prefab with shooting sound attached
The rocket now makes sound when it is spawned — our battle becomes more alive.

Step 17. Add Shooting Sound to Player Laser

Just like the enemy rockets, we want to add sound to the player's laser shot. Open the LaserShot script and update it as follows:


using UnityEngine;

public class LaserShot : MonoBehaviour
{
    // Reference to Rigidbody2D to handle physics
    Rigidbody2D rb;

    // The impulse force to shoot the laser upward
    public float force = 10f;

    // How much damage the laser deals
    public int damage = 1;

    // Audio clip to play when shooting
    public AudioClip LaserSound;

    void Start()
    {
        // Get the Rigidbody2D component on this object
        rb = GetComponent<Rigidbody2D>();

        // Create a vector pointing upward (along Y axis)
        Vector3 direction = new Vector3(0, force, 0);

        // Add impulse force to launch the laser
        rb.AddForce(direction, ForceMode2D.Impulse);

        // Play shooting sound at this position
        AudioSource.PlayClipAtPoint(LaserSound, transform.position);
    }

    void OnBecameInvisible()
    {
        // Destroy the laser when it goes off screen
        Destroy(gameObject);
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        // Check if we hit something tagged as "Enemy"
        if (other.gameObject.tag == "Enemy")
        {
            // Tell the enemy to take damage
            other.gameObject.SendMessage("MakeDamage", damage, SendMessageOptions.DontRequireReceiver);

            // Destroy the laser after hitting
            Destroy(gameObject);
        }
    }
}

After updating the script, go to the Laser prefab in the Assets window and assign the LaserSound.wav clip to the new Laser Sound field.

💡 If you want to use your own sound effects instead of the ones provided, you can drag your custom .wav file into the Assets/sound folder and assign it in the same way.

Laser prefab with added sound effect
Laser prefab with added sound effect

Step 18. Add Explosions Sound to Destroyed Objects

We want destroyed enemies and mines to play a short explosion sound when they disappear. For this, we'll slightly extend the HpController script by adding an audio field and playing it when health reaches zero.


using UnityEngine;

public class HpController : MonoBehaviour
{
    // Health points of the object
    public int hp = 3;

    // Sound effect for explosion
    public AudioClip ExplosionsSound;

    void MakeDamage(int damage)
    {
        // Subtract damage from health
        hp -= damage;

        // If health is depleted
        if (hp <= 0)
        {
            // Play explosion sound
            AudioSource.PlayClipAtPoint(ExplosionsSound, transform.position);

            // Destroy the object
            Destroy(gameObject);
        }
    }
}

Select both Mine and Enemy-1 prefabs in the Assets window. In their HpController component, assign the Boom.wav file to the Explosions Sound field.

That's it! Now every time an enemy or mine is destroyed, the game gives you satisfying audio feedback.

💡 You can use your own custom explosion sound too — just drag it into the Assets/sound folder and assign it the same way.

Enemy prefab with added sound effect
Enemy prefab with added sound effect

Step 19. Add Explosion Effect

We should add a particle effect when an Enemy (like a Mine or Enemy-1) is destroyed. Create a new Particle System and rename it to KiavoBoom. Set Position and Rotation all to 0. In the Inspector, make the following adjustments:

Go to the Emission module, add a Burst at time 0.0 with count 30.
In the Shape module, change Shape to Circle and Radius to 0.1.

Enable Color over Lifetime. Open the color editor, set the final Alpha to 0, and choose colors you like at the start and end. In the Renderer module, set Order in Layer to 10 (this setting is in the Renderer section).

In the Main section, set the Stop Action parameter to Destroy. This means the object will automatically remove itself after the effect finishes.

Then create a prefab from KiavoBoom and remove it from the scene — it will stay in your project ready for spawning.

You can experiment with more dramatic settings or colors later — this is just a basic explosion for now.

Enemy rocket prefab with shooting sound attached
The KiavoBoom effect is now ready — a small burst of particles when enemies are destroyed. Simple, fast, and visually satisfying.

Step 20. Spawn explosion when enemy is destroyed

We have now an explosion prefab. We should spawn it when an enemy (like a Mine or Enemy-1) is destroyed. Open the HpController script and modify it like this:


using UnityEngine;

public class HpController : MonoBehaviour
{
    // Amount of health points
    public int hp = 3;

    // Explosion effect prefab
    public GameObject Explosion;

    // Explosion sound
    public AudioClip ExplosionsSound;

    void MakeDamage(int damage)
    {
        // Subtract damage from health
        hp -= damage;

        // If health is depleted
        if (hp <= 0)
        {
            // Play explosion sound
            AudioSource.PlayClipAtPoint(ExplosionsSound, transform.position);

            // Spawn explosion effect
            Instantiate(Explosion, transform.position, Quaternion.identity);

            // Destroy this object
            Destroy(gameObject);
        }
    }
}

Now select the Mine and Enemy-1 prefabs. In the HpController component, assign your explosion prefab (e.g. KiavoBoom) to the Explosion field.

Explosion prefab added to enemy prefabs
KiavoBoom explosion is now linked in the HpController of each enemy prefab. When destroyed, they’ll disappear with sound and particles.

Step 21. What’s Next?

Our game is now complete — it has movement, enemies, shooting, sound, and UI. This tutorial focused on building a simple but working 2D space shooter using core Unity features.

Of course, you can expand it further: add explosions, visual effects, waves of enemies, score, lives, menus, boss fights, background music… even flying chickens or space tea ☕🛸

But our goal was to show you a clean and simple foundation — and now you have it.

💡 Keep experimenting, have fun, and build your own version from here!