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 (9) · 3 Reviews

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

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 and points 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:

  1. This code sets up minX inside Start. Then it creates an empty GameObject named Swarm.
  2. xSpacing and ySpacing update currentPos along the X and Y-axis, respectively.
  3. currentPos.x increments after every invader iteration in the row. After a row is complete, currentPos.y decrements.
  4. Looping over the members of invaderTypes, for each invaderType, you iterate row-wise to create individual invader GameObjects at the currentPos position.
  5. xSpacing and ySpacing update currentPos along the X and Y axis, respectively.
  6. Each created invader GameObject has its name set to invaderName. You then add a SimpleAnimator component, and assign its sprite array to the sprites associated with the invaderType.
  7. Finally, the invader becomes a child of Swarm and its position is set to currentPos.

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:

Set up for Game Controller's Invader Swarm component's Invader Types field.

Save and Play. Notice the swarm spawns, and the invaders animate in one place.

The game now has spawned invaders.

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 to true 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 and y. It moves each Transform in invaders by the same value along the X and Y axis respectively.
  • ChangeDirection toggles isMovingRight and moves the swarm down by the ySpacing amount.
  • Inside Update, you calculate xIncrement and update currentX based on the direction every frame.
  • You use currentX to check whether the swarm X position is approaching a threshold. If yes, you call ChangeDirection. If not, you move the swarm using MoveInvaders.

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 now moving at increasing speed across and then down the screen.

The invaders are moving, but they don't shoot bullets yet. You'll work on that in the next section.