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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Unity Tutorial: How to Make a Game Like Space Invaders
40 mins
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 theRespawn
coroutine starts. -
Respawn
first disables thecannonCollider
and makes the cannon sprite invisible. After a few moments, it makes the cannon sprite slightly transparent and sets cannon's position back tostartPos
. 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.
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.
Now, save and Play. You'll see the respawn sequence as well as the lives update whenever a bullet hits the cannon.
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
incrementsscore
by thevalue
passed to it and updates the UI label to reflect the changes. -
TriggerGameOver
shows the Game Over panel iffailure
is true. Otherwise, it shows the All Clear panel. It also enables therestartButton
, pauses the game and stops the music. -
Awake
handles theonClick
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 typename
with itspoints
value. -
IncreaseDeathCount
keeps track of and updateskillCount
when the player eliminates an invader. When the player eliminates all of the invaders,TriggerGameOver
receivesfalse
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 typeBullet
. - If the cannon bullet hit the spawner, the score and kill count update. Also, the current
followTarget
's Sprite Renderer disables, then updates thecurrentRow
. - If there aren't any rows left, the GameObject is disabled. Otherwise, you call
Setup
to update thefollowTarget
.
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.
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.
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.
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 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.