Let’s Make a 4X Space Game with Unity – Part 8 Camera Control 2
Hi guys and welcome to part 8. In the last part we added a panning system so we could move the camera around with WASD. In this part we will talk about
- How we clamp that movement
- Add the ability to zoom the camera in and out using the mouse wheel.
1. How we Clamp Our Movement
Currently when we pan around our galaxy or solar system we can keep panning in any direction forever. This is bad because we could easily get lost. To solve this we need a way to clamp the camera so it stays in a defined area. But how do we do this?
In the CameraControl script add a new method called ClampCameraPan. Make it void and don’t pass it anything. We need to declare a Vector3 equal to the current position of the Pan Object. Call this position.
Now we need to clamp the X and Z values in position to our upper and lower limits. But what are these limits? Well in our galaxy view the upper limit will be our maximumRadius and the lower limit will be -maximumRadius. In our solar system view it will be the maximum solar system size which at the moment is 50 (The maximum planet count is 10 in my example code and the current distance between planets is set at 5). But how does the game know what view we are in?
Well at the moment there isn’t anything definitive which tells the game what view it is in. Let’s change that. Open up the Galaxy script and declare a public bool called galaxyView with get and set functions. In the CreateGalaxy method before we create the stars set galaxyView to true.
Open the SolarSystem script and in the CreateSolarSystem method set galaxyView to false.
Now we have a simple way the game can check it is in the galaxy view or not.
Back in the CameraController script add an if statement to our ClampCameraPan method. The condition will be if galaxyView is equal to true.
Now we use the Mathf.Clamp to set the X and Z values in position. As this is if the galaxyView is true the clamp limits will be + and – the maximumRadius .
Add an else statement and this time clamp the X and Z to -50 and 50 (if you had a different number of max planets to me change your number to 5 * the max number you chose).
Finally set the position of the Pan Object to position.
Note: We have to set the X and Z numbers in position because Unity does not allow editing of the single elements of the transform.position directly.
Call ClampCameraPan at the end of ChangePosition.
Press play and move the camera around. It should now be clamped to the edges of our galaxy/solar systems. Exactly what we want!
2. Zooming In and Out
Before we start organizing how the camera zooms in and out lets sort out exactly where our camera objects will be in space at the start of the game. We will be editing the ResetCamera method to do this.
The Pan Object will start at (0,0,0) with no rotation. We already have this in our ResetCamera method so lets move down the hierarchy to the Rotation Object. This will be responsible for our camera rotation as we zoom in and out. We now need to make a decision on whether we start with the camera zoomed as far out as possible or zoomed in as far as possible. This will have an effect on the angle we start at.
Let’s start fully zoomed in. At the top of the CameraController class declare two new floats. Call them zoomedInAngle and zoomedOutAngle. Make them public so we can edit them in the inspector. Give zoomedInAngle a default value of 45 and zoomedOutAngle a default value of 90. Also add a float called zoomLevel and set it equal to 0 (don’t make this one public).
In ResetCamera we need to set zoomLevel back to 0 and then set the X rotation of the Rotation Object to zoomedInAngle.
Now we need to position our Zoom Object. This will only ever move in Z and its Z position will always be negative due to the orientation of all the objects. Declare two new floats at the top of the class called maxZoom and minZoom. Make the default value for maxZoom 200 and the default for minZoom 20.
In the ResetCamera method set the Z position of the Zoom Object to negative minZoom.
ResetCamera is now complete, the last thing we need to do before we start the zoom in and out is to set the Main Camera position and rotation to (0,0,0) in the inspector.
Press play and see how the new camera looks to you. Feel free to edit the minZoom and the zoomedInAngle if you don’t like them.
Right lets start zooming in and out. Add a new method to CameraController called ChangeZoom. Make it void and don’t pass it anything. The input name for the mouse wheel in Unity is “Mouse ScrollWheel” and like the ChangePosition method we only move the camera if the Mouse ScrollWheel input doesn’t equal zero.
There are two ways we could set this up. We could have it so that when the player pushes the mouse wheel forwards the camera zooms in. When they pull it backwards the camera zooms out. This would be my preference, however I know some people prefer the opposite way around and so we are going to add the ability to inverse the zoom. At the top of the Class declare a new public bool called inverseZoom and set it equal to false. Then back in ChangeZoom embed another if statement into our first one with an else after it. The If will have the condition inverseZoom is false.
In the if make zoomLevel equal to Mathf.Clamp01(zoomLevel – Input.GetAxis(“Mouse ScrollWheel”)) and in the else change the – to a +.
This treats our zoomLevel as a linear value between 0 and 1 where 0 is fully zoomed in and 1 is fully zoomed out.
After the else statement declare a new float called zoom. This will be the Z value in our Zoom Object position so we need to use Mathf.Lerp with the first value (a) –minZoom and the second (b) –maxZoom; The final value (t) will be our zoomLevel (remember the max and min zoom values should be negative because the Zoom Object’s Z position is always negative).
Now we simply set the Zoom Object’s local Z position to zoom (using Transform.localPosition) and call ChangeZoom in the Update method. Call it before the ChangePosition method. The reason we call this before changing the position will become clear in the next part.
Press play and try it out. Feel free to edit the public values in the inspector and don’t forget if you prefer you can inverse the zoom controls :). Notice though as you zoom out the speed of the camera panning does not remain constant.
I think this is a good time to stop so in the next part we will finish the camera controls by adding rotation to the camera as it zooms and fixing this issue of panning speed as we zoom in and out.
scripts_for_part_8 (zip file)