Creating GameObjects in code in Unity

GameObjects are everywhere in Unity. They are the basis of all your games. You can create GameObjects in lots of different, but probably the most important method is in code itself.

In this game, you shoot bullets at aliens. Each bullet on the screen is a GameObject. You’ll be shooting hundreds of them. In this tutorial, you’ll learn the code needed to create GameObject’s on demand. Before you dive into the mechanics, take a moment to reflect on a GameObject.

A GameObject is an object that has all sorts of components to it. This object is stored in a physical place in memory. The creation of it requires your computer to do some work on the CPU. Keeping it in memory increases the memory footprint of your game. Finally, deleting a GameObject also takes processing time.

Worst of all, lots of GameObjects means an increased rate of garbage collection. When there are many objects in memory, the C# runtime will examine each object to make sure it is being used. If not, the object is destroyed and the memory is collected. This increases the CPU load, which affects battery rate and worse of all, frame rate.

Note: This tutorial is part of a collection that teaches Unity development from the ground up. You can read the entire series over here. This series is free and does not require any account creation. All assets are provided. If you find it useful, feel free to buy me a coffee.

Recycling your objects

When you are dealing with many objects with short life spans, a better solution is to recycle them. When the space marine fires a bullet, once that bullet passes beyond the main camera, you can take that bullet and still keep in the scene. You store it in an “object pool.” When the code requires a bullet, it fetches one from the pool, resets all the values, then fires it again.

This keeps garbage collection to sustainable levels at the cost of a higher memory footprint. There may also be a longer loading time as the game generates the initial amount of GameObjects. Generally, players will prefer to wait longer to start a game versus frame rate drops.

This tutorial will not cover object pooling. Rather, you’ll be creating and deleting objects in code. Object pooling is an intermediate level technique, and there are plenty of solutions to this problem. Mark Placzek, one of my old colleagues at Kodeco.com, wrote an awesome tutorial on it. While the article is now somewhat old, the concepts are not (and it’s a good article). You can also read an official Unity tutorial on it.

TLDR – If you find yourself creating and deleting lots of objects, look into object pooling.

Building a bullet

It’s time to get into bullet crafting. Unfortunately, the finer parts of diplomacy are lost on the flesh-eating antagonists of this game. It’s best you give the hero some firepower so he can protect himself on his terribly relaxing (terrible?) vacation.

First, you need to create a bullet. In the Hierarchy, click the Plus button. From the drop-down, select 3D Object\Sphere to create a sphere in the Scene view.

This shows the Hierarchy selected with the Sphere highlighted in the 3D category.

Give it the name Projectile. With it still selected, check out the Inspector. You’ll notice a bunch of new components.

This shows the three components on the Projectile.

The three new components are:

  • The Mesh Filter is a component that contains data about your model’s mesh. This is all the points in space that create the 3D model.
  • The Mesh Renderer displays the mesh. It contains a lot of information about lighting, such as casting and receiving shadows.
  • Finally, you’ll notice the sphere contains a Sphere Collider. This component serves as the GameObject’s boundaries. You’ll learn cover colliders in Chapter 4

Since you want the bullet to participate in Unity’s physics, it needs a Rigidbody.

Luckily, you’ve done this before. Click the Add Component button and select Rigidbody from the Physics category. Make sure to uncheck Use Gravity.

Since the marine will burn through lots of projectiles, drag it from the Hierarchy to the Prefabs folder in the Project window. Delete the projectile from the Hierarchy because you don’t need it now that it’s become a prefab.

Creating a gun

At this point, you need to create a script to launch the projectile. In the Project Browser, select the Scripts folder then click the Create button. Choose C# Script and name it Gun. Double-click the file to launch the code editor.

This file needs a few properties underneath the class definition. Add the following:

[SerializeField]
private GameObject bulletPrefab;

[SerializeField]
private Transform launchPosition;

Again, when you create a public variable on a script, Unity exposes these variables in the editor. You will set the bulletPrefab to the bullet prefab you just created, and you will set the launchPosition to the position of the barrel of the Space Marine’s gun.

Next, add the following method:

void fireBullet() 
{
  // 1
  GameObject bullet = Instantiate(bulletPrefab) as GameObject;
  // 2
  bullet.transform.position = launchPosition.position;
  // 3
  bullet.GetComponent<Rigidbody>().linearVelocity = 
    transform.parent.forward * 100;
}

Here’s the breakdown of the code:

  1. Instantiate() is a built-in method that creates a GameObject instance for a particular prefab. In this case, this will create a bullet based on the bullet prefab. Since Instantiate() returns a type of Object, the result must be cast into a GameObject.
  1. The bullet’s position is set to the launcher’s position — you’ll set the launcher as the barrel of the gun in just a moment.
  1. Since the bullet has a Rigidbody attached to it, you can specify its velocity to make the bullet move at a constant rate. Direction is determined by the transform of the object to which this script is attached — you’ll soon attach it to the body of the space marine, ensuring the bullet travels in same the direction as the marine faces.

Save and switch back to Unity. In the Hierarchy, expand the SpaceMarine GameObject and select the BobbleMarine-Body GameObject.

In the Inspector, click the Add Component button and near the bottom of the list of components, select Scripts. From the list of scripts, choose Gun.

This shows adding the Gun script from the Add Components menu.

You’ll see that your Gun script component has been added to the body of the marine. You’ll also notice there are two new fields: Bullet Prefab and Launch Position. Do those sound familiar?

Click the circle next to Bullet Prefab.

This shows the circle selected at the end of the Bullet Prefab text field.

In the Select GameObject dialog, click the Assets tab. Select Projectile from the resulting list. Now you have loaded the bullet and just need to set the launch position.

This shows the Projectile selected in the Prefab menu.

In the Hierarchy, type Gun in the search field. You’ll see a Gun GameObject that is part of the space marine’s body.

This shows a search for the Gun GameObject in the Hierarchy.

You’ll notice that the Scene view is greyed out with just the marine body having color. This lets you know that the Scene view is being filtered.

This shows the greyed Scene view with the Marine body highlighted.

Select that GameObject and click the Plus button in the Hierarchy. Choose Create Empty Child. This GameObject will be filtered out. Clear the search. You should see the Gun and the child GameObject. Rename it to Launcher. This new GameObject lives in the center of the gun’s barrel and represents where bullets will spawn from — feel free to move it around in the scene editor if you’d like to tweak the bullet spawn position.

Here, I moved it to Launcher to the end of the gun barrel.

This shows the launcher at the end of the gun.

Keep all the GameObjects expanded and select BobbleMarine-Body so that the Inspector shows all the components. Drag the new Launcher GameObject into the Gun component’s Launch Position field.

With that, the marine’s gun is locked and loaded. All that’s left is the firing code. Thankfully, it’s pretty easy.

Writing the firing code

You have the bullet. You have the launcher. All that’s required is the actual firing code. In this game, the user fires by holding down the mouse button. You could fire per mouse-click but that would quickly become tiresome.

The complexity with firing comes with the new input system. This system already includes a fire action out of the box.

Open the Gun script. First, you need to use the InputSystem. Add the following at the top of the file:

using UnityEngine.InputSystem;

Now add the following variables underneath the class definition.

private InputSystem_Actions playerActions;
private InputAction fire;

This should look familiar from the last time you set up the input system. Next, add your boilerplate code.

void Awake()
{
  playerActions = new InputSystem_Actions();
  fire = playerActions.Player.Attack;
}

void OnEnable()
{
  fire.Enable();
}

void OnDisable()
{
  fire.Disable();
} 

If this looks new to you, see the Understanding user input tutorial. That will explain everything. The only difference is that you are accessing the Attack action versus the Move action.

You need to create two methods. One is to start firing and the other is to stop. Add the first method:

private void shoot(InputAction.CallbackContext context) // 1
{
  if (!IsInvoking("fireBullet")) // 2
  {
    InvokeRepeating("fireBullet", 0f, 0.1f); // 3
  }
}

This method does a few things. Here is the breakdown:

  1. This method signature takes in a context from the input system. This is a struct object that provides information about the action that triggered the method. You can find out the current phase (more on that soon), the interaction that started the action, and so on. You don’t need it, so you’ll ignore it in this method.
  1. This checks to see if the current object is “invoking” the fireBullet() method. Invoking means to call a method repeatedly. If the fireBullet() method isn’t being invoked, then the code execution enters the braces.
  1. This final line of code invokes the fireBullet() method. The first parameter is the delay for the first invoke. It is set 0f meaning it will start right away. The next parameter is how long it takes for the next invoke. The 0.1f means it will call the fireBullet() method every .1 seconds.

Now add the following method:

private void stopFiring(InputAction.CallbackContext context)
{
  CancelInvoke("fireBullet");
}

This is another method that works directly with the input system. All this method does is cancel the firing.

Now for the final code. Update your code to the following:

void OnEnable()
{
  fire.Enable();
  fire.started += shoot;
  fire.canceled += stopFiring;
}

void OnDisable()
{
  fire.Disable();
  fire.started -= shoot;
  fire.canceled -= stopFiring;
}

This is where the “magic” happens. When the script is enabled, methods are added to started and canceled properties. The started property indicates that the user is pressing the attack button and canceled means the user stopped pressing the button. As you can see, you can add multiples methods to these properties.

The property name canceled is confusing. It makes you think the user canceled the input, but this is not the case. It just means that the user released the button.

Finally, you’ll notice that OnDisable() is the reverse of OnEnable(). When you add a method to an action, you also take it off.

Save and switch back to Unity. Hold down the mouse button. You have bullets for days! And unfortunately, lots of bullet GameObjects.

This shows the Hierarchy filled with Projectile clones.

Don’t worry – you’ll take care of these leftover bullets soon enough.

Where to go from here

At this point, you should be feeling more comfortable with Unity. You have a walking space marine with a functioning weapon. You’ve learned the following:

  • Components and how they give your GameObjects behavior.
  • Scripting and how to use scripts to create custom behavior.
  • The Input System and how to access it from code.
  • The Game window and how to test your games.

This was a thick, heavy chapter and you made it to the end. Congratulations! You’ve come a long way. You can download the completed project for this chapter here:

https://drive.google.com/file/d/1wtvpjolZevYy_6ANu5BVKQT1bjvSz9IC/view?usp=drive_link

There’s still a lot more to do. Your poor marine is a sitting duck because he can’t turn around to see what’s sneaking up behind him. At the same time, he has nothing to worry about because there are no aliens hordes attacking him — yet!

You’ll solve these issues and more in the next chapter, Chapter 4, when you learn about the laws of game physics and how you can bend them to your own will! You’ll start on this in your next tutorial.


Discover more from Jezner Books

Subscribe to get the latest posts sent to your email.

By Brian Moakley

Brian Moakley is a writer and editor who lives amongst the quiet hills in New England. When not reading tales of high adventure, he is often telling such stories to all who will listen.

Related Post

Leave a Reply

Jezner Books
Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.