Spawning GameObjects

This is an excerpt chapter from my Weekend Code Project: Unity’s New 2D Workflow book. I hope you enjoy this free content on how to use Unity’s new 2D features. If you like what you see, please pick up a copy of the book to get access to the artwork, source code and a PDF/ePub version of the book.

Creating a Gizmo

Our game isn’t much fun or challenging right now. We need some more bad guys on the screen. Up until this point, we added new GameObjects manually to the scene. Now it’s time for us to actually look at how to dynamically create new GameObjects at runtime. To get started, we need to build a spawner, which is an object that creates other GameObjects. Go to the GameObject menu at the top of the screen and select Create Empty.

This is going to be a simple GameObject that lets us add the code we need to turn it into a spawner. Name the empty GameObject Spawner and create a new script on it called Gizmo.

A Gizmo in Unity is used for visually debugging GameObjects in your game. A Gizmo has its own draw method that gets called when viewing in the Scene Editor but not during runtime in your game. This will allow us to create a simple box to represent our spawner as we work with it in the Scene Editor, and it will remain invisible when the game runs. Make sure you import generic collections at the top of the class:

using System.Collections.Generic;

Then add the following properties to the Gizmo script:

public Color color=new Color(0.985f, 0.022f, 0.022f, 0.2f);
public List targets=new List();
public Vector3 size=new Vector3(1, 1, 0);

These properties will allow us to change the gizmo’s color, its size, and targets which will represent other GameObjects the gizmo is connected to. This will make a little more sense later on when we build out the rest of the spawner logic. For now we need to add the following methods to our gizmo. These next few lines of code will render the gizmo in the Scene Editor, and also help us access the targets via code when we connect other scripts to this script.

void OnDrawGizmos()
{
 Gizmos.color=color;
 Gizmos.DrawCube(transform.position, size);
 if (targets.Count > 0)
 {
 for (int i=0; i < targets.Count; i++)
 {
 Gizmos.DrawLine(transform.position, targets[i].transform.position);
 }
 }
}
public GameObject GetRandomTarget()
{
 if (targets.Count==0)
 return null;
 return targets[Random.Range(0, targets.Count)];
}
public GameObject GetTargetAt(int index)
{
 if (targets.Count==0)
 return null;
 return targets[index];
}

Now let’s add the gizmo script to our spawner GameObject. At this point, you should see the spawner rendering as a red box in the Scene tab.

You can change its color by simply clicking on the color dropper next to the Color field on the Gizmo script, as well as its Size below that.

Spawning GameObjects

Now we are ready to create the spawner logic. Attach a new script to the spawner GameObject and call it Spawner. From there you will want to set up the following properties:

public GameObject[] enemyPool;
public float delay=2.0f;
public bool active=true;
private Vector2 direction=new Vector2(1, 1);
private List targets;
private Gizmo parentGizmo;

Here we are setting up places to store the enemies we will spawn, the delay between new spawns, whether the spawner is active, as well as some internal values, such as direction to spawn the GameObjects in, targets for where to spawn at, and a reference to the Gizmo script also attached to our spawner. Make sure you import the generic collections again.

using System.Collections.Generic;

Then in the Start method, add the following:

parentGizmo=gameObject.GetComponent();
targets=parentGizmo.targets;
StartCoroutine(EnemyGenerator());

The first line is very important. This allows us to actually get a reference to another component script on our GameObject. In this case, we are looking for a reference to the Gizmo script. We will need this reference to get a listing of targets, which we will set up later on the Gizmo script in the Scene editor. The next important part of this method is the StartCoroutine call. This allows us to continually call the EnemyGenerator method. In that method, we will add a delay to keep it from being called too many times. Here is what that method should look like, just add it below the Start one:

IEnumerator EnemyGenerator()
{
 if (active)
 {
 var newTransform=transform;
 yield return new WaitForSeconds(delay);
 if (targets.Count > 0)
 {
 var spawnTarget=targets[Random.Range(0, targets.Count)];
 newTransform=spawnTarget.transform;
 direction=spawnTarget.transform.localScale;
 }
 GameObject clone=Instantiate(enemyPool[Random.Range(0, enemyPool.Length)], newTransform.position, Quaternion.identity) as GameObject;
 clone.transform.localScale=direction;
 StartCoroutine(EnemyGenerator());
 }
}

Here you can see we first test if the spawner is active. Next we get a reference to the spawner’s own transform. Then we use WaitForSeconds while passing in our delay value to decide if the spawner should actually create a new GameObject. You’ll notice that this has a return built into it, so if the wait has not happened for long enough, it will exit from the method and not run the rest of the code. If the script is ready to create a new GameObject, it checks for target locations and picks a random one. Then it replaces the spawner’s own transform position with the new target. It also sets the direction to match that of the target as well. Finally, it creates a new GameObject randomly from the enemy pool list, modifies its direction to match the direction from either the target or the spawner itself, and then sets a new Coroutine to call the EnemyGenerator method again.

We now have everything we need to get this working; we just need to set this up in the Scene. Start by populating the Enemy Pool on the component. Set the Size property to 1 and then select the Knight prefab for the first item.

It’s important that you use the Knight from the Assets tab and not the Scene tab because we will be removing the Knight GameObject from the Scene tab now that we have the Spawner in place. When you are done setting this up, select the Knight from the Hierarchy tab and delete it from the Scene tab so we don’t forget to remove it.

Now, if you run the game and switch over to the Scene tab, you will see Knights getting spawned at the spawner’s location, which is in the sky.

I have moved my spawner into the top area of the background. Also, you may notice that it is spawning a lot of Knights. Simply stop the game, go into the spawner instance, and change the delay value of the spawner component to something bigger, like 5.

Now you should see fewer Knights spawned, but it still doesn’t fix that they are floating up in the sky. Next we are going to create some GameObjects to represent spawn points in our scene. Go back to your Scene tab and add a new GameObject; call it LeftSpawnZone. Then add the Gizmo script to it so we can see it. You should end up with something like this:

As we keep adding Gizmos to the scene, it’s going to get hard to tell one from the other. First, we can change the color, but the other thing we should do is turn on a label so we can see the name in the editor. Click on the icon to the left of the GameObject’s name in the Inspector panel, and from here you can pick a label or other icon to show in the Scene editor.

Here you see the label for my LeftSpawnZone. Now we just want to customize it a little bit more. Adding the Gizmo doesn’t really do much outside of helping us visualize what the spawn zone actually looks like. Here is how I ended up tweaking mine:

Make sure you put it off to the side of the background. I also changed the size to fit within the ground image. 

Now we should do the same thing to create the other spawn zone. We can save ourselves some work by simply duplicating the existing LeftSpawnZone and renaming it. Right-click on it in the Hierarchy view and select Duplicate.

Now rename it to RightSpawnZone and move it to the other side of the scene. You’ll also want to make one additional modification: change the Scale X to -1. While this won’t make a visual change to the spawn zone, it will play a more important role, which I’ll get into shortly.

You should also make sure both spawn zones have their Z position set to 0. It’s a good habit to get into when working in the 2D tools to make sure GameObjects don’t disappear behind another 2D object. So, now with the Scale X set to -1, any GameObject spawned from this will get that scale factor and not only face to the left but also walk to the left, assuming they have our MoveForward script.

At this point, we should have everything we need to connect the Spawner to the spawn zones. Select it in the Hierarchy panel, and then in the Inspector panel, add both spawn zones to the Gizmo component’s target list.

Once you have done that, you should see two red lines being drawn from the Spawner to the spawn zones to help you visualize the connection. This is part of the Gizmo code we added and is now built into the script. Run the game and you’ll see Knights being spawned to the new spawn zones, and also walking in the correct direction.

We now have everything connected to spawn bad guys, so now all that is left is a way to kill them.

Subscribe To My Mailing List

Want to learn how to make a game? Not sure where to start? Even if you are a seasoned game maker there is still a lot you can learn from my mailing list. I'll be covering tips and tricks for how to build, release and market games each month.

Simply sign up for my mailing list and also get access to a 50% off discount code for my eBooks and other content. I promise to not spam your inbox!

Join Now