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
Creating the Invaders
How do all antagonists start out their lives in games? Spawning of course! You’ll do that next.
Spawning the Invaders
Navigate to RW/Scripts to examine the SimpleAnimator script. You’ll use it to animate the invaders, but you don’t need to worry about its inner workings for this tutorial.
When you add SimpleAnimator to a GameObject you also add a SpriteRenderer because it’s a required component for the script to function.
SimpleAnimator also requires an array of sprites. It’ll keep updating the SpriteRenderer‘s sprite cyclically using the sprites inside the array, essentially animating it.
Now, select Invader Swarm attached to Game Controller. Open the associated script inside your code editor. Add the following code the inside the class:
[System.Serializable]
private struct InvaderType
{
public string name;
public Sprite[] sprites;
public int points;
public int rowCount;
}
Here’s a code breakdown:
- This code defines an InvaderType struct.
- The
sprites
array stores all the sprites associated with the invader type, which SimpleAnimator uses to animate the invader. -
rowCount
is the number of rows the invader type will have in the swarm. -
name
stores the type name for the invader andpoints
stores the score contribution if the player eliminates an invader of this type. These will come in handy later.
Now add the following right below InvaderType
:
[Header("Spawning")]
[SerializeField]
private InvaderType[] invaderTypes;
[SerializeField]
private int columnCount = 11;
[SerializeField]
private int ySpacing;
[SerializeField]
private int xSpacing;
[SerializeField]
private Transform spawnStartPoint;
private float minX;
You’ll use all of these fields for the spawning logic:
-
invaderTypes
: Represents all the invader types in use. -
columnCount
: Total number of columns for the swarm. -
ySpacing
: The spacing between each invader in the swarm along the Y-axis. -
xSpacing
: The spacing between each invader in the swarm along the X-axis. -
spawnStartPoint
: Spawning point for the first invader. -
minX
: Stores the minimum X position value for the swarm.
Next, paste the following code after all the variable declarations:
private void Start()
{
minX = spawnStartPoint.position.x;
GameObject swarm = new GameObject { name = "Swarm" };
Vector2 currentPos = spawnStartPoint.position;
int rowIndex = 0;
foreach (var invaderType in invaderTypes)
{
var invaderName = invaderType.name.Trim();
for (int i = 0, len = invaderType.rowCount; i < len; i++)
{
for (int j = 0; j < columnCount; j++)
{
var invader = new GameObject() { name = invaderName };
invader.AddComponent<SimpleAnimator>().sprites = invaderType.sprites;
invader.transform.position = currentPos;
invader.transform.SetParent(swarm.transform);
currentPos.x += xSpacing;
}
currentPos.x = minX;
currentPos.y -= ySpacing;
rowIndex++;
}
}
}
Here’s a code breakdown:
- This code sets up
minX
insideStart
. Then it creates an empty GameObject named Swarm. -
xSpacing
andySpacing
updatecurrentPos
along the X and Y-axis, respectively. -
currentPos.x
increments after every invader iteration in the row. After a row is complete,currentPos.y
decrements. - Looping over the members of
invaderTypes
, for eachinvaderType
, you iterate row-wise to create individual invader GameObjects at thecurrentPos
position. -
xSpacing
andySpacing
updatecurrentPos
along the X and Y axis, respectively. - Each created invader GameObject has its name set to
invaderName
. You then add aSimpleAnimator
component, and assign its sprite array to thesprites
associated with theinvaderType
. - Finally, the invader becomes a child of
Swarm
and its position is set tocurrentPos
.
Save everything and go back to Unity.
Select Game Controller from the Hierarchy. On Invader Swarm, set:
- Y Spacing to 25
- X Spacing to 25
- Spawn Start Point to INVADERS Spawn Start, which is a child of Helpers.
Then, set the Invader Types size to 3 and set the member fields as follows:
- 0: Set Name to SQUID, Points to 30 and Row Count to 1.
- 1: Set Name to CRAB, Points to 20 and Row Count to 1.
- 2: Set Name to OCTOPUS, Points to 10 and Row Count to 2.
Now, navigate to RW/Sprites and look at the INVADERS spritesheet. These aren’t the original Space Invaders but they’ll work for this tutorial.
Go back to Invader Swarm and set it up as follows, using the spritesheet:
For the SQUID entry, set the Sprites list to contain the following sprites from the spritesheet in this order:
- bugs_invaders_0
- bugs_invaders_5
- bugs_invaders_9
- bugs_invaders_4
Perform the same exercise, but this time for CRAB using the following sprites:
- bugs_invaders_13
- bugs_invaders_18
Lastly, assign the sprites for OCTOPUS using:
- bugs_invaders_7
- bugs_invaders_2
Here is a visual reference of what things should look like now:
Save and Play. Notice the swarm spawns, and the invaders animate in one place.
Wonderful! But they’re not moving. You’ll fix that in the next section.
Moving the Invaders
Go back to the InvaderSwarm.cs script and add the following after the existing variable declarations:
[Space]
[Header("Movement")]
[SerializeField]
private float speedFactor = 10f;
private Transform[,] invaders;
private int rowCount;
private bool isMovingRight = true;
private float maxX;
private float currentX;
private float xIncrement;
All of these variables will help move the swarm:
-
speedFactor
for now represents the speed at which the invaders move along the X-axis. Later, speed will involve the music tempo so the actual speed is the product of the two. -
invaders
stores the Transforms of all the created invader GameObjects. -
rowCount
stores the total row count of the swarm. -
isMovingRight
represents the direction of movement and is set totrue
by default. -
maxX
is the maximum X position for the swarm movement. -
currentX
represents the overall X position of the swarm. -
xIncrement
is the value per frame that moves the invaders along the X-axis.
Now, in Start
, add the following code right above int rowIndex = 0;
:
foreach (var invaderType in invaderTypes)
{
rowCount += invaderType.rowCount;
}
maxX = minX + 2f * xSpacing * columnCount;
currentX = minX;
invaders = new Transform[rowCount, columnCount];
This code calculates the total row count and stores it inside rowCount
. Then, you calculate maxX
based on the total columns and the spacing between each invader. Initially, currentX
is set to the spawnStartPoint
‘s X position.
You declared the invaders
array. To populate it, you’ll need one more line of code.
Paste the following line inside the innermost for
loop, right above currentPos.x += xSpacing;
:
invaders[rowIndex, j] = invader.transform;
This line takes care of populating invaders
.
Finally, right after Start
, paste:
private void Update()
{
xIncrement = speedFactor * Time.deltaTime;
if (isMovingRight)
{
currentX += xIncrement;
if (currentX < maxX)
{
MoveInvaders(xIncrement, 0);
}
else
{
ChangeDirection();
}
}
else
{
currentX -= xIncrement;
if (currentX > minX)
{
MoveInvaders(-xIncrement, 0);
}
else
{
ChangeDirection();
}
}
}
private void MoveInvaders(float x, float y)
{
for (int i = 0; i < rowCount; i++)
{
for (int j = 0; j < columnCount; j++)
{
invaders[i, j].Translate(x, y, 0);
}
}
}
private void ChangeDirection()
{
isMovingRight = !isMovingRight;
MoveInvaders(0, -ySpacing);
}
Here's a code breakdown:
-
MoveInvaders
accepts two float values:x
andy
. It moves each Transform ininvaders
by the same value along the X and Y axis respectively. -
ChangeDirection
togglesisMovingRight
and moves the swarm down by theySpacing
amount. - Inside
Update
, you calculatexIncrement
and updatecurrentX
based on the direction every frame. - You use
currentX
to check whether the swarm X position is approaching a threshold. If yes, you callChangeDirection
. If not, you move the swarm usingMoveInvaders
.
Save everything. Go back to Unity and click Play. You'll see the invader swarm moving. While in Play Mode, try different values for the Invader Swarm's Speed Factor and see how it affects the swarm's speed.
The invaders are moving, but they don't shoot bullets yet. You'll work on that in the next section.