Politics, Sociology, Firefighting, Technology, and Original Fiction

Unity3d RTS Camera Part 2: Zoom and Rotate

This is part two of a multipart discussion of the camera system I have constructed for my experimental RTS game using Unity3d. In Unity3d RTS Camera Part 1: Data Component, I explained the DataComponent script that would be used to contain and provide all the data for the camera so that all the other components can share data easily. I highly suggest that you start there if you have not read it yet, as the Data Component is essential to the entire camera system.

For this post we’ll explore both zoom and rotation. The system can implement one or both of them, so they are not actually coupled in any way, but it makes much more sense to talk about them together than separately. To accomplish the two tasks we’ll be creating 3 new files – one that handles adjusting zoom, one that handles adjusting the rotation, and one that actually does the positioning of the camera.

Adjusting Zoom

First we need to create a script that will handle adjusting our zoom. Create a new C# file in the <project root>/Scripts/Camera folder (or wherever you saved your CameraData script from the last post) and name it CameraZoom.

Class Properties

For this script we only need one property, and that’s a reference to our CameraData component.

The cameraData property is left without a value as we will define this value when the component starts up.

The Start Method

The Start method is provided by Unity3d as a part of Monobehavior. We will use it as our constructor to define the cameraData property.

Since we need the CameraData script to power this script, the Start method tries to get the CameraData object assigned to the camera. If we have forgotten to add the CameraData script to the camera, then we need to add the script to our camera. Once that is complete, and we have a reference to the script stored in our cameraData property, we can call the storeTarget method on the CameraData script, which is explained in Unity3d RTS Camera Part 1: Data Component.

The FixedUpdate Method

In order to have our camera do anything we need to update it periodically. Unity3d provides 2 built-in methods for this, Update and FixedUpdate. Here I have chosen to use FixedUpdate, but you can just as easily use Update if desired.

As the goal of this class is merely to handle the user input and update the CameraData appropriately, there is not much going on here. First, we grab the value from the Axis representing the scrollwheel of the user’s mouse. This is a normalized value, so it ranges from -1 to 1. If it is positive it means we’re zooming in, and if it is negative then we are zooming out. We add the value to the zoom property of the CameraData script. If the user is not actively zooming in or out, it will add 0.

Next we need to make sure that the new zoom level is within our limits. The final two lines first make sure that the CameraData component’s zoom property first isn’t too small (zoomed too far in) and not too large (zoomed too far out), and if either is true, the property is set to the actual limit.

If the zoom property was a dynamic property, a setter could have been used to do when the last 2 lines are doing, and I may go back and do that, but this works just fine for now.

The Whole CameraZoom Script

The CameraZoom script is not very large. All we’re doing is setting the new zoom level every fixed update. Applying zoom will happen later, but for now here’s the entire CameraZoom script.

Adjusting Rotation

Now that zoom is being set, time to worry about rotation. Create a new C# file in the <project root>/Scripts/Camera folder (or wherever you saved your CameraData script from the last post) and name it CameraRotate.

Class Properties and the Start Method

Since the CameraRotate script shares the same properties and Start method as the CameraZoom script, there is no need to explain it again.

The FixedUpdate Method

Like we did in the CameraZoom script, we’ll use the provided FixedUpdate method to handle adjusting our rotation according to user input.

Here we are finally taking advantage of some of the helper methods defined in the CameraData script. What we want to know is should we be rotating, and if so, in which direction? CameraData::shouldRotateLeft() will return true if we should move left, and if that is the case we subtract 1 from the current rotation (this moves us clockwise). If we should not be rotating left, we will use shouldRotateRight to see if we should rotate right, and if so add 1 to the current rotation (this moves us clockwise).

What value is added or subtracted from the rotation could probably be yet another property of the CameraData component, and I will probably go back and implement that as my project progresses, but for now this is fine.

The Whole CameraRotate Script

The CameraRotate script is also not very large. Simply adjusting some data with every fixed-update. Applying the rotation, as well as the zoom, will happen next. In the meantime, here is the complete CameraRotate script.

The CameraAdjustSelf Script

All this time we have been updating the data in the Data Component, but we have not actually touched the camera itself. Well all that changes now. Go ahead and create a new C# script in the <project root>/Scripts/Camera folder (or where ever you have been saving scripts thus far) and name it CameraAdjustSelf.

Class Properties and the Start Method

Again, we open this class the same as the previous two. Explanation is above, so here is the code:

The FixedUpdate Method

Finally time to start adjusting the camera so that it moves towards or away from our target based on the level of zoom and rotates appropriately around the target. As with the other classes, we can throw this into FixedUpdate.

There is a lot more going on in this method than any other previously, but it is not overly complex.

First, we create a new Vector3 and assign it the values of the x, y, and z position of the camera’s target. We use the position of the camera’s target because the target is what the camera will move around.

After that, it is time to take advantage of the dynamic properties we built into the DateComponent script. The xDistance, yDistance, and zDistance properties of the Data Component are not static values; they will do the math of determining what the camera’s position needs to be relative to the target, taking into account zoom and rotation. We add those properties to the position of the target as this will create a point in space that is as far from the target as our zoom dictates, and the x and z values are set to account for rotation.

Once we have this new point in space determined, we check if that is where the camera already is. If the camera does occupy that point, there is nothing more to do and the function returns. Otherwise the function continues on to Lerp towards the given point using the panSpeed property of the Data Component. The Lerp will ease our camera towards its new location to give a nice, smooth feel.

Finally, now that the camera has been positioned correctly, we tell the camera to look at the target, merely as a safeguard to ensure the camera is always looking at the target.

The Whole CameraAdjustSelf Script

For the first time we actually have some functionality to play with. Add the CameraAdjustSelf script to the camera, and then both CameraZoom and CameraRotate, and the camera should allow us to rotate around the target and zoom in and out. If you want to disable rotation, just remove the CameraRotate script from the camera. Same for zoom. This is the nice thing about separating the data from the scripts that check input and react to it. The CameraAdjustSelf script will go back to the DataComponent script to get its data. If the CameraZoom script does not exist to change the zoom value, then no harm done, the zoom will just forever be the same.

Next Time

Two of three actions are complete, leaving just panning. We will wrap this up in Part 3, which I will link to as soon as I have it written and posted which you can find at Unity3d RTS Camera Part 3: Panning.

Questions or thoughts? Feel free to leave a comment.



Unity3d RTS Camera Part 1: Data Component


Unity3d RTS Camera Part 3: Panning

1 Comment

  1. Matheus

    Finally a good tutorial about the subject…congratulations and thank you very much!

Leave a Reply

Powered by WordPress & Theme by Anders Norén