Unity3D: Third-Person Cameras

The camera is one of the most important elements in a 3D game. It acts as the player's eyes, letting them see the game world from different points of view. In Unity3D, a 3D camera works just like a film camera. It can be panned, tilted, and zoomed to frame scenes. This tutorial will teach you how to create multiple third person camera perspectives.

Project Setup

We need a simple project to test our camera scripts in. We'll need a scene with a ground plane that has a texture on it. This will make it easy to see how each camera moves and reacts to player inputs. When we're done, it should look like this:

Follow these steps to setup the project:

Click File > New Project

Name your project folder 3rd Person Cameras

Click Create

Click GameObject > Create Other > Directional Light

Click GameObject > Create Other > Plane

In the Inspector, find the Transform component and change the position X to 0, Y to -0.5 and Z to 0 so it will sit below the cube

This gives the player controls similar to those of a tank. The horizontal axis (the left-or-right keys) turn the player around, while the vertical axis (up-or-down keys) move the player forward and backward.

The Look At Camera

This is the most basic 3rd person camera. It sits in a fixed location in the 3D world and tracks its target like a turret.

Click Assets > Create > C# Script

Name the script LookAtCamera

Drag the LookAtCamera script from the Project panel onto the Main Camera in the Hierarchy panel

In the LookAtCamera script, create a public attribute for our camera's target at the top of the class. Public attributes are exposed in the Inspector and will allow us to assign the Player as the camera's target:

public class LookAtCamera : MonoBehaviour {
public GameObject target;

Next, we need to tell our camera's transform to look at the target object. Thankfully, transform objects have a convenient LookAt() method we can use to do just that. We could do this in the Update() method, but instead we create a LateUpdate() method. As a rule of thumb, you should always use LateUpdate() instead of the Update() method in all camera scripts. LateUpdate() happens after Update() has finished, so the Player script has a chance to finish calculating the player's position before the camera calculates its position. This results in smoother camera motion:

If you try to run the game now, you'll get errors complaining about UnassignedReferenceException. To prevent this, drag the Player from the Hierarchy panel and drop it on the script's Target property in the Inspector. The camera now has a valid target to look at.

The Dungeon Crawler Camera

This is the type of camera you'd typically find in games like Diablo, also known as a "dungeon crawler" game. The camera sits above the player and moves relative to the character, but never rotating.

Click Assets > Create > C# Script

Name the script DungeonCamera

Drag the DungeonCamera script from the Project panel onto the Main Camera in the Hierarchy panel

In the DungeonCamera script, we once again need to create a public attribute for our camera's target. We also need to create a variable to store the offset between the camera and its target. The offset is represented as a Vector3 and will be used maintain the relative distance as the player moves around. You may notice that we don't give the offset a value when we first declare it. This is because we'll be calculating the value the first time the script is run. We can use the Start() method to do this:

Drag the Player from the Hierarchy panel to the script's Target property in the Inspector.

Optional Enhancements

You may notice that the camera movement is a bit stiff. It would be nice to dampen the movement slightly so that it takes some time to catch up to the player. We can do this using the Vector3.Lerp() method. Lerp linearly interpolates between two points, meaning it smoothly transitions from one point to another in a straight line.

In order to control how much damping is applied, we can create another public attribute called, what else, damping!

public float damping = 1;

The two points we can lerp between are the current position of the camera with damping applied, and the desired position with no damping.

We can then multiply the offset by the rotation to orient the offset the same as the target. We then subtract the result from the position of the target.

transform.position = target.transform.position - (rotation * offset);

To keep looking at the player:

transform.LookAt(target.transform);

Drag the Player from the Hierarchy panel to the script's Target property in the Inspector.

Optional Enhancements

The same damping motion we applied to the Dungeon camera can be applied to the Follow camera. First, we add a damping attribute to make it easier to adjust the damping:

public float damping = 1;

Instead of lerping between two points like we did with the Dungeon camera, we'll be lerping between the angle of the camera and the angle of the target. So, rather than Vector3.Lerp(), we use the Mathf.LerpAngle() method. We replace the original angle code with:

Final Thoughts

More than one camera script can be applied to a single camera at the same time. To switch between the different scripts, enable the script you want by checking it and unchecking all the others. This could be useful for switching to a different camera style for establishing shots or cut scenes.

Unity also comes with several camera scripts you can use right out of the box. The scripts are well documented, easy to customize and make great guides for building and improving your own camera scripts.

Click Assets > Import Package > Scripts

Uncheck everything except Camera Scripts

Conclusion

Unity makes it easy to build a wide variety of cameras for any type of game. With just a few lines of code, the most important element in your game is ready to go. While some may find the math a little intimidating, Unity provides so many useful convenience functions that most of the heavy calculations are already done for you.