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
Making the Invaders Shoot Lasers
You'll use a variant of the Bullet prefab for the invaders. Navigate to RW/Prefabs and find the EnemyBullet. It's the same as Bullet, except the sprite points in the opposite Y direction and its layer is set to Enemy.
Select EnemyBullet. Notice the Speed of Bullet is set to -200. This ensures the bullet moves in the opposite direction of the cannon bullets but with the same magnitude.
In the game, only invaders at the front of the swarm shoot laser bullets. To achieve this, you'll use the BulletSpawner prefab located in RW/Prefabs.
You'll instantiate as many of them as the invader column count. You'll also make the bullet spawners follow the invader Transforms at the front of the swarm.
This will ensure that when firing, the bullets will appear to be coming from the front row invaders.
Before you do that, you need a way to get an invader Transform at a specific row and column from the invaders
array inside InvaderSwarm
.
Open the InvaderSwarm.cs script and add the following line after the InvaderType
struct declaration:
internal static InvaderSwarm Instance;
This helps turn the InvaderSwarm
into a Singleton.
Then paste the following right above Start
:
internal Transform GetInvader(int row, int column)
{
if (row < 0 || column < 0
|| row >= invaders.GetLength(0) || column >= invaders.GetLength(1))
{
return null;
}
return invaders[row, column];
}
private void Awake()
{
if (Instance == null)
{
Instance = this;
}
else if (Instance != this)
{
Destroy(gameObject);
}
}
GetInvader
returns the invader Transform at the row
and column
index of invaders. Awake
turns the InvaderSwarm
into a Singleton by ensuring that when the game starts, only one instance of InvaderSwarm
will be alive.
Now, select the BulletSpawner prefab and take a look at the Inspector. Notice it has Bullet Spawner attached to it.
There's also a Kinematic Rigidbody 2D, a Box Collider 2D and the layer is set to Enemy. You won't add colliders to the invaders, but rather use this collider to detect hits from the cannon bullets.
In your code editor, open the BulletSpawner.cs script attached to BulletSpawner and add the following inside the class:
internal int currentRow;
internal int column;
[SerializeField]
private AudioClip shooting;
[SerializeField]
private GameObject bulletPrefab;
[SerializeField]
private Transform spawnPoint;
[SerializeField]
private float minTime;
[SerializeField]
private float maxTime;
private float timer;
private float currentTime;
private Transform followTarget;
internal void Setup()
{
currentTime = Random.Range(minTime, maxTime);
followTarget = InvaderSwarm.Instance.GetInvader(currentRow, column);
}
private void Update()
{
transform.position = followTarget.position;
timer += Time.deltaTime;
if (timer < currentTime)
{
return;
}
Instantiate(bulletPrefab, spawnPoint.position, Quaternion.identity);
GameManager.Instance.PlaySfx(shooting);
timer = 0f;
currentTime = Random.Range(minTime, maxTime);
}
Here's a code breakdown:
-
currentTime
represents the time to wait until shooting the next bullet. It's set to a random value betweenminTime
andmaxTime
. -
currentRow
andcolumn
link a bullet spawner with an invader. Thecolumn
is set once and won't change. But, as you'll see later,currentRow
updates if the player's bullets hit this spawner. - Inside
Setup()
, you setfollowTarget
by callingGetInvader
from theInvaderSwarm
instance usingcurrentRow
andcolumn
. You also set an initial value tocurrentTime
. - Inside
Update
, you update the position of the bullet spawner to match thefollowTarget.position
. In addition, you increment thetimer
until it reachescurrentTime
. When this happens, you create a bullet atspawnPoint.position
while playing theshooting
sound effect, followed by resettingtimer
andcurrentTime
.
Save everything. Return to Unity and open BulletSpawner in Prefab Mode. Ensure the following values are set for Bullet Spawner:
- Shooting to InvaderBullet located at RW/Sounds.
- Bullet Prefab to EnemyBullet located at RW/Prefabs.
- Spawn Point to the SpawnPoint Transform which is the only child of BulletSpawner.
- Min Time to 1 and Max Time to 10.
To use the BulletSpawner, you need to go back to the InvaderSwarm.cs script.
First, paste the following line at the end of all the variable declarations:
[SerializeField]
private BulletSpawner bulletSpawnerPrefab;
Then, inside Start
, add the following lines at the end:
for (int i = 0; i < columnCount; i++)
{
var bulletSpawner = Instantiate(bulletSpawnerPrefab);
bulletSpawner.transform.SetParent(swarm.transform);
bulletSpawner.column = i;
bulletSpawner.currentRow = rowCount - 1;
bulletSpawner.Setup();
}
In this code, you create a bullet spawner and set it up. You instantiate bulletSpawner
for each column of the swarm and set its column
and currentRow
followed by calling its Setup
method. You also parent the bulletSpawner
to the Swarm to prevent clutter in the Hierarchy.
Save everything and go back to Unity. Select Game Controller from the Hierarchy and set the Bullet Spawner Prefab for Invader Swarm to BulletSpawner, located in RW/Prefabs.
Save and Play. You now have invaders who shoot bullets at the player.
Notice that both bullets disappear when an invader bullet and cannon bullet collide. The invader bullet disappears when it hits the cannon and the cannon bullet disappears when it hits a bullet spawner. They disappear because OnCollisionEnter2D
calls DestroySelf
inside Bullet
.
There's one thing missing, however, and that's explosions. :] You'll add them next.
Adding Explosions
Navigate to RW/Prefabs. Notice the Explosion prefab. It's a simple GameObject with a pre-made sprite animation you'll use for the explosion visuals.
Now, open GameManager.cs again. Add the following after declaring sfx
:
[SerializeField]
private GameObject explosionPrefab;
[SerializeField]
private float explosionTime = 1f;
[SerializeField]
private AudioClip explosionClip;
internal void CreateExplosion(Vector2 position)
{
PlaySfx(explosionClip);
var explosion = Instantiate(explosionPrefab, position,
Quaternion.Euler(0f, 0f, Random.Range(-180f, 180f)));
Destroy(explosion, explosionTime);
}
CreateExplosion
creates an explosion at position
with a random rotation along the Z-axis, and destroys it after explosionTime
seconds.
To use CreateExplosion
, add the following line at the end of DestroySelf
inside the Bullet
class:
GameManager.Instance.CreateExplosion(transform.position);
Save all. Return to Unity and select Game Controller from the Hierarchy. For the Game Manager set:
- Explosion Prefab to Explosion located in RW/Prefabs.
- Explosion Clip to Explosion located in RW/Sounds.
Save the scene and Play. You now have explosions. :]
Currently, the bullets don't affect the invaders or the cannon. In the following sections, you'll add scores and lives.
Adding Scores and Lives
Did you notice those super retro UI labels in the game view? Right now they're just deadweight. It's time to get them working so that there are goals and consequences to give this game meaning.