跳转至

10 Advanced Camera Controls With Cinemachine

The camera is your portal into your game so don’t underestimate how much good camera control can contribute to the feel of it. However, properly implementing complex camera behaviors isn’t trivial. It’s easy to go wrong. The Cinemachine plugin provides a turnkey solution for all your camera needs. Time to explore Cinemachine and take the veggie battles to the next level!

img

Introduction

Cinemachine is a package provided in the Unity Registry. It offers a complete solution to managing multiple cameras and complex camera behaviors.

Don’t reinvent the wheel by attempting to build custom camera scripts to control the camera in your games! Cinemachine handles all of the responsibilities via Virtual Cameras to allow you to build multiple camera views — each with unique and complex logic — to follow GameObjects and aim at targets. Cinemachine provides out-of-the-box solutions for 3rd-person-following cameras, orbiting cameras and many more.

Open the Chapter 10 starter project in Unity and begin by loading the RW / Scenes / Arenascene. Before working with the advanced camera components, you need to add the Cinemachine package via the top menu: Window ▸ Package Manager. Choose Packages: Unity Registry from the drop-down and select Cinemachine.

img

Select Install to add the package. After it’s added to the Unity project, a new top menu named Cinemachine is immediately added to the Unity Editor.

Cinemachine Components

Cinemachine coordinates multiple camera views through a central hub called the Cinemachine Brain. Virtual Cameras, also called vcams for short, provide means to customize the behaviors of your camera views and assign special camera locations in your scenes.

Cinemachine Brain

The CinemachineBrain is a component script that acts as the connector between multiple vcams and a single active Main Camera GameObject.

Select the MainCamera GameObject in the Hierarchy, and add a component called CinemachineBrain via the Inspector. The GameObject should have its Tag assigned to MainCamera.

img

The Live Camera field is currently inactivate and assigned to None. When there are vcams present in the scene, this field is automatically assigned a virtual camera.

The CinemachineBrain will transition smoothly between different vcams using Blends that determine how to animate the transition. Animations between any two vcams can be modified by assigning Custom Blends, otherwise a Default Blend will apply to any camera transition.

Virtual Cameras

You’ll start by adding some Virtual Cameras to the scene to provide different in-game views.

Create an empty GameObject in your scene named VirtualCameras to hold all the cameras you’ll now create.

Next, add your first Virtual Camera from the top menu: Cinemachine ▸ Create Virtual Camera. This will add a GameObject named CM vcam1, which will contain a CinemachineVirtualCameracomponent.

Move this into your VirtualCameras holder, and rename the GameObject to Zoom vcam.

img

View Zoom vcam in the inspector, and assign the Tank to both the Follow and LookAt items. Those targets assign the vcam to position and aim at the tank. Until you customize it further, the vcam will be positioned inside the tank.

You’ll fix that first. Expand the Body section in the inspector:

img

The Body section controls the behavior of the Virtual Camera in the scene. Here, set this to 3rd Person Follow to have a trailing 3rd-person camera view that remains close to the player. Set the Shoulder Offset to (X:4, Y:6, Z:4) to place the camera at a comfortable angle and distance from the tank.

Now, expand the Aim section:

img

The Aim section controls how the camera responds to follow the LookAt target you provided above. The Composer type keeps a single Look At target in the camera frame. As a comparison, if you changed the type to Group Composer, this could instead keep a group of enemies or other GameObjects with the view.

The additional properties allow you to fine-tune how the vcam aims at the target — such as Lookahead, which attempts to predict where the target will be for a leading shot; Damping, which controls how quickly the camera settles on the object of interest; and Dead/Soft Zonesizing, which gives the target an area to move around in without the camera continuously fidgeting to keep it exactly in the center.

Select the MainCamera again and observe that the Live Camera field is now assigned to the Zoom vcam virtual camera. This is the highest-priority (and only!) vcam active in the scene.

img

Now, create another vcam by duplicating the Zoom vcam. Rename the duplicated GameObject to Follow vcam. View this in the inspector, and expand the Body section of its CinemachineVirtualCamera.

Since this is going to be a camera that loosely follows the player, increase the Body’s Dampingto (X:2, Y:1, Z:2) to have more slack in following the player. Damping specifies how quickly the camera reacts to changes, and increasing the positional values makes it behave as if it was a slower, heavier camera following the player.

Change the Rig’s Shoulder Offset to (X:0, Y:10, Z:-12) to position the following camera directly behind the tank.

In the CinemachineVirtualCamera, decrease the Priority field to 5, then select the MainCamera, and observe that the Zoom vcam with a higher priority of 10 has taken control of the camera. Now return to the Follow vcam and increase Priority to 15.

Play the scene.

img

You’ll see the game already has a better feel because the Follow vcam camera provides a third-person view that smoothly realigns with the tank.

Gate Camera

Again, duplicate the Zoom vcam and rename the GameObject to Gate vcam. Set the Followand Look At targets to GateWall 1.

In this camera, change the Body to be an Orbital Transposer, and set Binding Mode to Lock To Target With World Up. Then, set the Follow Offset to (X:1, Y:8, Z:8). The Orbital Transposersets the vcam relative to the direction the target is moving or facing, and you’ll use this to position the gate camera in front of the spawn point. The Heading should be assigned to Target Forward.

Note: Cinemachine is designed to query user input by the standard Unity Input.GetAxis(name), which is incompatible with the Unity Input System used in this book. To avoid a conflict with accessing the old-style input API, clear the Input Axis Name under the X Axis section. When you do want to query user input affecting the cameras in Cinemachine, you can add a component CinemachineInputProvider to the vcam GameObject to override the standard input source.

img

To check that the camera will view the GateWall, raise its Priority to a value of 20, and then select the MainCamera again to see what it’s looking at - this will be the GateWall GameObject. Now, set the Priority of Gate vcam down to 1 since it shouldn’t be the highest priority.

Next, you’ll integrate these different cameras into the game!

Transitioning between cameras with scripting

Each virtual camera in the scene has a priority value; the camera which has the highest priority for the scene will be assigned to the Unity Camera. In order to change the active camera by a script, you simply need to change which camera has the highest priority.

The GameState class controls the flow of the game, and so you need to change this script so that when key events happen, such as when enemies appear or the tank gets destroyed, you redirect to the relevant camera to show the action.

Open the RW / Scripts / GameState script in an editor. At the top of the script, add a new import, just below the others:

using Cinemachine;

Then, inside GameState, add the following properties:

public CinemachineVirtualCamera zoomCamera;
public CinemachineVirtualCamera playerCamera;
public CinemachineVirtualCamera gateCamera;

These will represent the different camera views in the scene.

Now, at the bottom of the class, implement the ActivateCamera method:

public void ActivateCamera(CinemachineVirtualCamera camera)
{
    zoomCamera.Priority = lowPriority;
    playerCamera.Priority = lowPriority;
    gateCamera.Priority = lowPriority;
    camera.Priority = highPriority;
    camera.MoveToTopOfPrioritySubqueue();
}

This resets all the vcams to a low priority and then sets the specified virtual camera to the highest priority, causing the CinemachineBrain to make this the active view.

MoveToTopOfPrioritySubqueue() ensures this vcam has priority over any other vcams that happen to have the same priority value — which is a good practice when you want to make a vcam the live camera.

Now, call your new method by adding this to the end of Reset():

ActivateCamera(zoomCamera);

When the game starts, the camera will begin zoomed-in on the target of the zoomCamera — in this case, the player’s tank.

To show the first enemies as they appear at a gate, you need to switch to the gateCameravcam when they first spawn. In the Update() method, find the if (state == States.Fight) clause, and, within the block, add the following after the call to g.SpawnEnemies(5):

ActivateCamera(gateCamera);

After the enemies have spawned, you need to change back to the vcam that follows the player. Still in the Update() method, find the if (state == States.Battle) clause, and, at the top of the block, add the following:

ActivateCamera(playerCamera);

Save your changes and return to the Unity Editor.

Inspect the Game GameObject. Assign the Zoom vcam GameObject to the Zoom Camera field and Follow vcam to the Player Camera. Last, assign the Gate vcam to the Gate Camera.

img

Run your game now, and you’ll see the vcams transition between the Follow vcam and a Gate vcam as the first enemies are introduced.

However, you’ll see the animated transition to the gate vcam is too slow. This animation between the vcams is controlled by a Blend, and you can customize the behavior of the camera transitions under the MainCamera.

Inspect the MainCamera, and set the CinemachineBrain’s Default Blend to Cut.

img

When you run the scene again, the transition is instantaneous between the different vcams.

Tank destruction

A neat effect you can introduce is to show the tank being destroyed when the battle is lost.

Go back and edit the GameState script again, and add the following to the Update()method just after the line state = States.Lose;:

// Hide player.
player.SetActive(false);
ActivateCamera(zoomCamera);
UpdateGUI();

// Replace with destroyed tank.
DestroyedTank.transform.position = player.transform.position;
DestroyedTank.transform.rotation = player.transform.rotation;
DestroyedTank.SetActive(true);

This code is executed when the player’s health becomes less than zero, meaning they’re dead! It swaps the Tank prefab with a set of models with colliders and rigidbodies. The individual parts will collapse upon the activation of the GameObject in the scene and show as a quick destruction of the tank. As this happens, the camera switches to zoom in on the damaged tank.

Save your changes and switch back to the Unity Editor. Play the scene and watch as the camera transitions to highlight the destruction of the tank!

img

Challenges

If you want to go further with the Cinemachine system, try these challenges:

  1. Implement a Blending property to change the behavior of the animation transitions between your cameras in the arena. Try building more complex Custom Blends for camera transitions.
  2. Explore adding special effects to the cameras — including using an Impulse to add a camera shake that responds to in-game events. Add a Cinemachine Collision Impulse Source to the Tank GameObject, and add a Cinemachine Impulse Listener to the main TankFollow virtual camera. Can adding camera shakes on collisions enhance the immersion of the battle?
  3. Experiment with using vcams to control the camera during a dialogue between two characters. Add two characters with nearby vcam instances aimed at their heads and Priority value 0. When a character speaks a line of dialogue, increase the vcam to the highest priority to create a cinematic cut to the speaker.

Key points

  1. Cinemachine is a package that provides easy-to-use camera controls.
  2. Virtual Cameras, or vcams, are customizable cameras representing different views in your scene.
  3. CinemachineBrain is a component that should be assigned to your Main Camera. It determines the active vcam view based on the highest priority and configures how camera transitions behave.