How to Create a Tower Defense Game in Unity – Part 1

In this tutorial, you’ll build a 2D tower defense game using the latest Unity engine. By Jeff Fisher.

Leave a rating/review
Save for later
Share
You are currently viewing page 3 of 4 of this article. Click here to view the first page.

Test Upgrade Capability

Save the file and then switch to PlaceMonster.cs in your IDE and add this new method:

private bool CanUpgradeMonster()
{
  if (monster != null)
  {
    MonsterData monsterData = monster.GetComponent<MonsterData>();
    MonsterLevel nextLevel = monsterData.GetNextLevel();
    if (nextLevel != null)
    {
      return true;
    }
  }
  return false;
}

First check whether there is a monster that you can upgrade by checking the monster variable for null. If this is the case, you get the current level of the monster from its MonsterData.

Then you test whether a higher level is available, which is when GetNextLevel() doesn’t return null. If up-leveling is possible, you return true, otherwise, you return false.

Enable Upgrading With Gold

To enable the upgrade option, add an else if branch to OnMouseUp:

if (CanPlaceMonster())
{
  // Your code here stays the same as before
}
else if (CanUpgradeMonster())
{
  monster.GetComponent<MonsterData>().IncreaseLevel();
  AudioSource audioSource = gameObject.GetComponent<AudioSource>();
  audioSource.PlayOneShot(audioSource.clip);
  // TODO: Deduct gold
}

Check whether an upgrade is possible with CanUpgradeMonster(). If yes, you access the MonsterData component with GetComponent() and call IncreaseLevel(), which increases the level of the monster. Lastly, you trigger the monster's AudioSource.

Save the file and switch back to Unity. Run the game, place and upgrade as many monsters as you like...for now.

All the monster upgrades

Upgrade all the monsters

Pay Gold - Game Manager

Right now it’s possible to build and upgrade all the monsters immediately, but where's the challenge in that?

Let's drill down into the issue of the gold. The problem with keeping track of it is that you need to share information between different game objects.

The following image shows all the objects that want a piece of the action.

The highlighted game objects all need to know, how much gold the player owns.

The highlighted game objects all need to know, how much gold the player owns.

You'll use a shared object that's accessible to other objects to store this data.

Right-click in the Hierarchy and select Create Empty. Name the new game object GameManager.

Add a C# script named GameManagerBehavior to GameManager, then open the new script in your IDE. You'll display the player's total gold in a label, so add the following line to the top of the file:

using UnityEngine.UI;

This lets you access UI-specific classes like Text, which the project uses for the labels. Now add the following variable to the class:

public Text goldLabel;

This will store a reference to the Text component used to display how much gold the player owns.

Now that GameManager knows about the label, how can you ensure the amount of gold stored in your variable and the amount displayed on the label are in sync? You'll create a property.

Add the following code to GameManagerBehavior:

private int gold;
public int Gold {
  get
  { 
    return gold;
  }
  set
  {
    gold = value;
    goldLabel.GetComponent<Text>().text = "GOLD: " + gold;
  }
}

Seem familiar? It’s similar to the CurrentLevel you defined in Monster. At first, you create a private variable, gold, to store the current gold total. Then you define a property named Gold -- creative, right? -- and implement a getter and setter.

The getter simply returns the value of gold . The setter is more interesting. In addition to setting the variable's value, it also sets the text field on goldLabel to display the new amount of gold.

How generous do you feel? Add the following line to Start() to give the player 1000 gold, or less if you feel miserly:

Gold = 1000;

Assign the Label Object to the Script

Save the file and switch to Unity.

In the Hierarchy, select GameManager. In the Inspector, click on the circle to the right of Gold Label. In the Select Text dialog, select the Scene tab and select GoldLabel.

Assign goldLabel

Run the scene and the label displays Gold: 1000.

1000 gold

Check the Player's "Wallet"

Open PlaceMonster.cs in your IDE, and add the following instance variable:

private GameManagerBehavior gameManager;

You'll use gameManager to access the GameManagerBehavior component of the scene's GameManager. To assign it, add the following to Start():

gameManager = GameObject.Find("GameManager").GetComponent<GameManagerBehavior>();

You get the GameObject named GameManager using GameObject.Find(), which returns the first game object it finds with the given name. Then, retrieve its GameManagerBehavior component and store it for later.

Note: You could have accomplished this by setting the field in Unity's editor, or by adding a static method to GameManager that returns a singleton instance from which you could get the GameManagerBehavior.

However, there's a dark horse method in the block above: Find, which is slower at runtime but convenient and ok to use sparingly.

Get the Money!

You don't yet deduct gold, so add this line twice inside OnMouseUp(), replacing each of the comments that read // TODO: Deduct gold:

gameManager.Gold -= monster.GetComponent<MonsterData>().CurrentLevel.cost;

Save the file and switch to Unity, upgrade some monsters and watch the Gold readout update. Now you deduct gold, but players can build monsters as long as there is space; they just get into debt.

Infinite credit

Infinite credit? Awesome! But you can't allow this. Monsters should only be placed when the player has enough gold.

Require Gold for Monsters

Switch to PlaceMonster.cs in your IDE, and replace the contents of CanPlaceMonster() with the following:

int cost = monsterPrefab.GetComponent<MonsterData>().levels[0].cost;
return monster == null && gameManager.Gold >= cost;

Retrieve the cost for placing the monster from levels in its MonsterData. You then check that monster is not null and that gameManager.Gold is greater than the cost.

Challenge: Add the check for whether a player has enough gold in CanUpgradeMonster() by yourself.
[spoiler]
Replace this line:

return true; 

with this one:

return gameManager.Gold >= nextLevel.cost;

This checks if the player has more Gold than the cost of the upgrade.
[/spoiler]

Save and run the scene in Unity. Go ahead, just try to place unlimited monsters!

Now you can only build a limited amount of monsters.

Limited gold.

Tower Politics: Enemies, Waves and Waypoints

Time to "pave the road" for your enemies. Enemies appear at the first waypoint, move towards the next and repeat until they reach your cookie.

You’ll get the enemies marching by:

  1. Defining a road for the enemies to follow
  2. Moving the enemy along the road
  3. Rotating the enemy so it looks forward
Jeff Fisher

Contributors

Jeff Fisher

Author

Barbara Reichart

Author

Mitch Allen

Tech Editor

Sean Duffy

Final Pass Editor

Over 300 content creators. Join our team.