Unity Tutorial: How to Make a Game Like Space Invaders

In this Unity tutorial, you’ll learn how to make a classic 2D space shooting game similar to Space Invaders. By Najmm Shora.

4.9 (8) · 2 Reviews

Download materials
Save for later
Share
You are currently viewing page 4 of 5 of this article. Click here to view the first page.

Implementing Player Lives

Open GameManager.cs and add the following code after the variable declarations:

[SerializeField] 
private int maxLives = 3;

[SerializeField] 
private Text livesLabel;

private int lives;

internal void UpdateLives()
{
    lives = Mathf.Clamp(lives - 1, 0, maxLives);
    livesLabel.text = $"Lives: {lives}";
}

Calling UpdateLives decrements the lives variable by one and updates the UI label to reflect the change. Currently, nothing happens when lives reaches zero but you'll change that later.

Add the following at the end of Awake:

lives = maxLives;
livesLabel.text = $"Lives: {lives}";

This code sets the default value for lives and also updates the UI label.

Now, open CannonControl and paste the following lines after the variable declarations:

[SerializeField] 
private float respawnTime = 2f;

[SerializeField] 
private SpriteRenderer sprite;

[SerializeField] 
private Collider2D cannonCollider;

private Vector2 startPos;

private void Start() => startPos = transform.position;

Then, add the following lines after Update:

private void OnCollisionEnter2D(Collision2D other)
{
    GameManager.Instance.UpdateLives();
    StopAllCoroutines();
    StartCoroutine(Respawn());
}

System.Collections.IEnumerator Respawn()
{
    enabled = false;
    cannonCollider.enabled = false;
    ChangeSpriteAlpha(0.0f);

    yield return new WaitForSeconds(0.25f * respawnTime);

    transform.position = startPos;
    enabled = true;
    ChangeSpriteAlpha(0.25f);

    yield return new WaitForSeconds(0.75f * respawnTime);

    ChangeSpriteAlpha(1.0f);
    cannonCollider.enabled = true;
}

private void ChangeSpriteAlpha(float value)
{
    var color = sprite.color;
    color.a = value;
    sprite.color = color;
}

Here's what's happening:

  • ChangeSpriteAlpha changes the opacity of the cannon sprite.
  • When a bullet hits the cannon, GameManager.UpdateLives decrements the total lives and the Respawn coroutine starts.
  • Respawn first disables the cannonCollider and makes the cannon sprite invisible. After a few moments, it makes the cannon sprite slightly transparent and sets cannon's position back to startPos. Finally, it restores the opacity of the sprite and enables the collider again.

Save everything and return to Unity. Select Game Controller and set the Game Manager's Lives Label to Lives Text, which is a child of Canvas.

The Inspector for Game Manager

For the Cannon Control on CANNON, set Sprite to the Sprite Renderer on Sprite, a child GameObject of CANNON. Set Collider to the Box Collider 2D on the CANNON.

The Inspector for the Cannon Control component

Now, save and Play. You'll see the respawn sequence as well as the lives update whenever a bullet hits the cannon.

The cannon now loses lives.

The bullets don't seem to affect the invaders. You'll work on that in the next section.

Implementing Score and Game Over

Before you do anything else, open the MusicControl.cs script. You want to stop the music at game over, so paste the following code inside the class:

[SerializeField] 
private AudioSource source;

internal void StopPlaying() => source.Stop();

StopPlaying stops the audio source when called.

Now, open the GameManager.cs script and add the following after the variable declarations:

[SerializeField] 
private MusicControl music;

[SerializeField] 
private Text scoreLabel;

[SerializeField] 
private GameObject gameOver;

[SerializeField] 
private GameObject allClear;

[SerializeField] 
private Button restartButton;

private int score;

internal void UpdateScore(int value)
{
    score += value;
    scoreLabel.text = $"Score: {score}";
}

internal void TriggerGameOver(bool failure = true)
{
    gameOver.SetActive(failure);
    allClear.SetActive(!failure);
    restartButton.gameObject.SetActive(true);

    Time.timeScale = 0f;
    music.StopPlaying();
}

Then, paste the following lines at the end of UpdateLives:

if (lives > 0) 
{
    return;
}

TriggerGameOver();

Finally, add the following at the end of Awake:

score = 0;
scoreLabel.text = $"Score: {score}";
gameOver.gameObject.SetActive(false);
allClear.gameObject.SetActive(false);

restartButton.onClick.AddListener(() =>
{
    SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    Time.timeScale = 1f;
});
restartButton.gameObject.SetActive(false);

Here's what this code does:

  • allClear stores a reference to the All Clear panel, which displays when the player eliminates all the invaders. gameOver references the Game Over panel that shows when the player runs out of lives.
  • UpdateScore increments score by the value passed to it and updates the UI label to reflect the changes.
  • TriggerGameOver shows the Game Over panel if failure is true. Otherwise, it shows the All Clear panel. It also enables the restartButton, pauses the game and stops the music.
  • Awake handles the onClick event for the restart button. It reloads the scene when clicked.

Open InvaderSwarm.cs and add the following inside the class after the variable declarations:

private int killCount;
private System.Collections.Generic.Dictionary<string, int> pointsMap;

internal void IncreaseDeathCount()
{
    killCount++;
    if (killCount >= invaders.Length)
    {
        GameManager.Instance.TriggerGameOver(false);
        return;
    }
}

internal int GetPoints(string alienName)
{
    if (pointsMap.ContainsKey(alienName)) 
    {
        return pointsMap[alienName];
    }
    return 0;
}

Then paste the following line right above int rowIndex = 0; inside Start:

pointsMap = new System.Collections.Generic.Dictionary<string, int>();

Below the line right under var invaderName = invaderType.name.Trim(); add the following:

pointsMap[invaderName] = invaderType.points;

Here's a code breakdown:

  • pointsMap is a Dictionary (a map of string to integer). It maps the invader type name with its points value.
  • IncreaseDeathCount keeps track of and updates killCount when the player eliminates an invader. When the player eliminates all of the invaders, TriggerGameOver receives false and displays the All Clear panel.
  • GetPoints returns the points associated with an invader type by passing in its name as the key.

Finally, open BulletSpawner.cs to handle collision detection for the invaders. Paste the following right after Update:

private void OnCollisionEnter2D(Collision2D other)
{
    if (!other.collider.GetComponent<Bullet>()) 
    {
        return;
    }

    GameManager.Instance.
        UpdateScore(InvaderSwarm.Instance.GetPoints(followTarget.gameObject.name));

    InvaderSwarm.Instance.IncreaseDeathCount();

    followTarget.GetComponentInChildren<SpriteRenderer>().enabled = false;
    currentRow = currentRow - 1;
    if (currentRow < 0) 
    {
        gameObject.SetActive(false);
    }
    else 
    {
        Setup();
    }
}

Here's what this code does:

  • OnCollisionEnter2D returns without doing anything if the object that hit the bullet spawner wasn't of type Bullet.
  • If the cannon bullet hit the spawner, the score and kill count update. Also, the current followTarget's Sprite Renderer disables, then updates the currentRow.
  • If there aren't any rows left, the GameObject is disabled. Otherwise, you call Setup to update the followTarget.

Wow! That was a lot of work. Save everything and jump back into Unity to finish this step.

Select Music and set Source of Music Control to the Audio Source component on the same GameObject.

The Inspector for the Music Control component

Then, select Game Controller. For Game Manager, set:

  • Music to Music Control of Music.
  • Score Label to Score Text.
  • Game Over to Game Over Panel.
  • All Clear to All Clear.
  • Restart Button to Restart Button.

The Inspector showing the Game Manager component

Save and Play. Now you can kill the invaders! Enable Gizmos in the Game View and select the Swarm to see how the bullet spawners update.

The laser bullets now hit and remove the invaders.

Kill all the invaders to see the All Clear, or let the lives run out to see the Game Over. Then, you can use the Restart button to reload the scene.

The Game Over panel
The All Clear panel

The invaders are a bit slow and have the same speed throughout. In the next section, you'll update their speed with the tempo of the music.