In this article by Francesco Sapio author of the book Getting Started with Unity 2D Game Development - Second Edition we will see how to create our towers. This is not an easy task, but at the end we will acquire a lot of scripting skills.
(For more resources related to this topic, see here.)
First of all, it's useful to write down what we want to achieve and define what exactly a cupcake tower is supposed to do. The best way is to write down a list, to have clear idea of what we are trying to achieve:
There are a lot of things to implement. Let's start by creating a new script and naming it CupcakeTowerScript. As we already mentioned for the Projectile Script, in this article, we implement the main logic, but of course there is always space to improve.
Even if we don't have enemies yet, we can already start to program the behavior of the cupcake towers to shoot to the enemies. In this article we will learn a bit about using Physics to detect objects within a range.
Let's start by defining four variables. The first three are public, so we can set them in the Inspector, the last one is private, since we only need it to check how much time is elapsed. In particular, the first three variables store the parameters of our tower. So, the projectile prefab, its range and its reload time. We can write the following:
public float rangeRadius; //Maximum distance that the Cupcake Tower can shoot
public float reloadTime; //Time before the Cupcake Tower is able to shoot again
public GameObject projectilePrefab; //Projectile type that is fired from the Cupcake Tower
private float elapsedTime; //Time elapsed from the last time the Cupcake Tower has shot
Now, in the Update() function we need to check if enough time has elapsed in order to shoot. This can be easily done by using an if-statement. In any case, at the end, the time elapsed should be increased:
void Update () {
if (elapsedTime >= reloadTime) {
//Rest of the code
}
elapsedTime += Time.deltaTime;
}
Within the if statement, we need to reset the elapsed time, so to be able to shoot the next time. Then, we need to check if within its range there are some game objects or not.
if (elapsedTime >= reloadTime) {
//Reset elapsed Time
elapsedTime = 0;
//Find all the gameObjects with a collider within the range of the Cupcake Tower
Collider2D[] hitColliders = Physics2D.OverlapCircleAll(transform.position, rangeRadius);
//Check if there is at least one gameObject found if (hitColliders.Length != 0) {
//Rest of the code
}
}
If there are enemies within range, we need to decide a policy about which enemy the tower should be targeted. There are different ways to do this and different strategies that the tower itself could choose. Here, we are going to implement one where the nearest enemy to the tower will be the one targeted.
To implement this policy, we need to loop all all the game objects that we have found in range, check if they actually are enemies, and using distances, pick the nearest one. To achieve this, write the following code inside the previous if statement:
if (hitColliders.Length != 0) {
//Loop over all the gameObjects to identify the closest to the Cupcake Tower
float min = int.MaxValue;
int index = -1;
for (int i = 0; i < hitColliders.Length; i++) {
if (hitColliders[i].tag == "Enemy") {
float distance = Vector2.Distance(hitColliders[i].transform.position, transform.position);
if (distance < min) {
index = i;
min = distance;
}
}
}
if (index == -1)
return;
//Rest of the code
}
Once we got the target, we need to get the direction, that the tower will use to throw the projectile. So, let's write this:
//Get the direction of the target
Transform target = hitColliders[index].transform;
Vector2 direction = (target.position - transform.position).normalized;
Finally, we need to instantiate a new Projectile, and assign to it the direction of the enemy, as the following:
//Create the Projectile
GameObject projectile = GameObject.Instantiate(projectilePrefab, transform.position, Quaternion.identity) as GameObject;
projectile.GetComponent<ProjectileScript>().direction = direction;
Instantiate Game Objects it is usually slow, and it should be avoided. However, for the learning propose we can live with that. And that is it for shooting to the enemies.
In order to create a function to upgrade the tower, we first need to define a variable to store the actual level of the tower:
public int upgradeLevel; //Level of the Cupcake Tower
Then, we need an array with all the Sprites for the different upgrades, like the following:
public Sprite[] upgradeSprites; //Different sprites for the different levels of the Cupcake Tower
Finally, we can create our Upgrade function. We need to upgrade the graphics, and increase the stats. Feel free to tweak this values as you prefer. However, don't forget to increase the level of the tower as well as to assign the new sprite. At the end, you should have something like the following:
public void Upgrade() {
rangeRadius += 1f;
reloadTime -= 0.5f;
upgradeLevel++;
GetComponent<SpriteRenderer>().sprite = upgradeSprites[upgradeLevel];
}
Save the script, and for now we have done with it.
As we have done with the Sprinkle, we need to do something similar for the cupcake Tower. In the Prefabs folder in the Project Panel, create a new Prefab by right clicking and then navigate to Create | Prefab. Name it SprinklesCupcakeTower.
Now, drag and drop the Sprinkles_Cupcake_Tower_0 from the Graphics/towers folder (within the cupcake_tower_sheet-01 file) in the Scene View. Attach the CupcakeTowerScript to the object by navigating to Add Component | Script | CupcakeTowerScript. The Inspector should look like the following:
We need to assign the Pink_Sprinkle_Projectile_Prefab to the Projectile Prefab variable. Then, we need to assign the different Sprites for the upgrades. In particular, we can use Sprinkles_Cupcake_Tower_* (replacing the * with the level of the cupcake tower) from the same sheet as before. Don't worry too much about the other parameters of the tower, like the range radius or the reload time, since we will see how to balance the game later on. At the end, this is what we should see:
The last step is to drag this game object inside the prefab. As a result, our cupcake tower is ready.
In this article we covered the topic of creating a cupcake tower and scripting it.
Further resources on this subject: