Unity Tutorial Part 3: Components

In the final part of our Unity tutorial series, you’ll learn how to make your first game in Unity with C# from scratch: a twin-stick shooter called Bobblehead Wars! By Brian Moakley.

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

Camera Movement

There’s only one problem with the space marine’s movement: He will slip off screen. You want the camera to follow the hero around the arena, so he doesn’t get away from you.

With a little scripting, you can keep the marine in focus.

First, make sure you’re not in play mode – to stop play mode, select the play button again.

In the Hierarchy, click the Create button and select Create Empty. Name it CameraMount.

The basic idea is you want CameraMount to represent the position the camera should focus on and have the camera be relative to this position.

Initially you want the camera to focus where the space marine is, so let’s configure the CameraMount to be at the exact same position as the space marine.

To do this, select the space marine, click on the Gear button to the upper-right of the Transform component, and select Copy Component

Then select the CameraMount, click on the Gear button to the upper right of the Transform component, and select Paste Component Values:

Next, drag the Main Camera GameObject into the CameraMount GameObject.

Great! Now as you move the player around, you can move the CameraMount to move with the player, and the camera will track the player. You just need to write a script to do this.

With the CameraMount selected, click the Add Component button in the Inspector and select New Script. Call it CameraMovement and then click Create and Add.

Note: When you make a new script by clicking the Add Component button, Unity will create the script in the top level of your assets folder. Get into the habit of moving assets into their respective folders the moment you make or see them.

Drag your new file from the top level of the assets folder into the Scripts folder.

Double-click the CameraMovement script to open it in your code editor. Underneath the class definition, add the following variables:

public GameObject followTarget;
public float moveSpeed;

followTarget is what you want the camera to follow and moveSpeed is the speed at which it should move. By creating these as public variables, Unity will allow you to set these within the Unity editor itself, so you can set the followTarget to the space marine and fiddle with the moveSpeed to your heart’s content, as you’ll see shortly.

Now add the following to Update():

if (followTarget != null) 
{
  transform.position = Vector3.Lerp(transform.position, 
    followTarget.transform.position, Time.deltaTime * moveSpeed);
}

This code checks to see if there is a target available. If not, the camera doesn’t follow.

Next, Vector3.Lerp() is called to calculate the required position of the CameraMount.

Lerp() takes three parameters: A start position in 3D space, an end position in 3D space, and a value between 0 and 1 that represents a point between the starting and ending positions. Lerp() returns a point in 3D space between the start and end positions that’s determined by the last value.

For example, if the last value is set to 0 then Lerp() will return the start position. If the last value is 1, it returns the end position. If the last value is 0.5, then it returns a point halfway between the start and end positions.

In this case, you will supply the camera mount position as the start and the player position as the end. Finally, you multiply the time since the last frame rate by a speed multiplier to get a suitable value for the last parameter. Effectively, this makes the camera mount position smoothly move to where the player is over time.

Save your code and return to Unity. Select CameraMount in the Hierarchy, and look in Inspector. You’ll see two new fields named Follow Target and Move Speed. As mentioned earlier, these were automatically derived by Unity from the public variables you just added to the script. These variables need some values.

With the CameraMount still selected in the Hierarchy, drag SpaceMarine to the Follow Target field and set the Move Speed to 20.

Play your game to see what’s changed.

The marine is a real superstar now, complete with a personal camera crew. Granted, he can’t turn, and he walks right through objects just like Kitty Pryde, but these are easily solvable issues that you don’t have to tackle now.

Note: The bigger the move speed, the faster the camera mount will move to the player. The smaller, the more the camera will “lag” behind the space marine’s position, letting the player “jump ahead” of the camera. Try changing the move speed to a smaller value, like 2, and see what happens for yourself!

Adding Gunplay

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 Create button. From the drop-down, select 3D Object\Sphere to create a sphere in the Scene view.

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

The three new components are:

  1. The Mesh Filter is a component that contains data about your model’s mesh and passes it to a renderer.
  2. The Mesh Renderer displays the mesh. It contains a lot of information about lighting, such as casting and receiving shadows.
  3. Finally, you’ll notice the sphere contains a Sphere Collider. This component serves as the GameObject’s boundaries.

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 Browser. Delete the projectile from the Hierarchy because you don’t need it now that it’s gone on to be a prefab.

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:

public GameObject bulletPrefab;
public 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>().velocity = 
    transform.parent.forward * 100;
}

Let’s review this section by section:

  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.
  2. 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.
  3. 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.

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. 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.

In the Hierarchy, hold the Alt key on PC or Option on Mac and click the disclosure triangle next to the BobbleMarine-Body. You’ll see a large list of child GameObjects. Look for Gun.

Select that GameObject and click the Create button. Choose Create Empty Child and 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 spawn position.

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.

Notice that when you add the GameObject to a transform field, Unity finds and references the attached transform.

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

Switch back to your code editor and open Gun.cs.

The gun should fire when the user presses the mouse button and stop when the user releases it.

You could simply check to see if the button is pressed in Update() and call fireBullet() if so, but since Update() is called every frame, that would mean your space marine would shoot up to 60 times per second! Our space marine can shoot fast, but not that fast.

What you need is a slight delay between when you shoot bullets. To do this, add the following to Update():

if (Input.GetMouseButtonDown(0)) 
{
  if (!IsInvoking("fireBullet")) 
  {
    InvokeRepeating("fireBullet", 0f, 0.1f);
  }
}

First, you check with the Input Manager to see if the left mouse button is held down.

Note: If you wanted to check the right mouse button, you’d pass in 1, and for the middle mouse button, you’d pass in 2.

If the mouse is being held down, you check if fireBullet() is being invoked. If not, you call InvokeRepeating(), which repeatedly calls a method until you call CancelInvoke().

InvokeRepeating() needs a method name, a time to start and the repeat rate. InvokeRepeating() is a method of MonoBehaviour.

After that bit of code, add the following:

if (Input.GetMouseButtonUp(0)) 
{
  CancelInvoke("fireBullet");
}

This code makes it so the gun stops firing once the user releases the mouse button. Save your work and return to Unity, then play the game.

Hold down the mouse button. You have bullets for days!