In this post we’re going to cover some more zoom and rotate options, this time without the use of a spring arm. Here are some alternatives:
In this post we will cover:
- Object that we will want to rotate in our view using left mouse button click (can bind to other buttons)
- Zoom in and out with smooth limits using mouse wheel
- Move camera field of view using right mouse button (can bind to other buttons)
Let’s get started with rotating the object, in this post we should have a ‘simpler’ version than the one covered in part 15. Check out video demo here.
Reference the rotating object in Player Controller
Pretty much all of the code will sit in our player controller class. This is somewhat optional – though if you’re using Character
as parent its not as Character will consume inputs that you don’t want.
Open up the blueprints for the object that you wish to rotate, it should support any type (which is why I made changes from part 15, which did not work on Character classes).
The highlighted parts is what you will want to add to your object blueprints:
In my blueprints, I will not always want it to be rotated, which will be controlled via boolean variable – feel free to do something similar in your project if you want to sometimes disable it.
Init Rotate and Zoom
has not been created yet, so let’s get started with that – you can create new graphs to store and separate this logic.
The Init
custom event can go inside the BindRotateZoomEvents
graph.
Inside your Player Controller
class, let’s create the entry point.
The first thing that you will want to do is make a reference of the object that you will want to rotate.
You can do this either by adding input
to your custom event and making reference to self
from your caller object, or simply Get actor of class
like I have and referenced the class I desire to rotate.
Do note that this will only support 1 object in your map to rotate.
So note, the Character Proxy
class is the object I will be rotating in the map.
I iterate over all objects because the proxy character is destroyed and recreated when you traverse between different screens (character create / select screen).
This means that sometimes the actor will still exist, but is not valid as its pending to be picked up by garbage collection.
Update rotate and zoom on timer ticks
After determining the object that will be rotated, we can setup our timer events
Set timer by event will allow us to call a custom event every 0.03 seconds in this setup. We can use update tick
instead if you prefer.
Create the booleans zoom in progress
and rotate in progress
booleans which will be true when we’re left/right clicking and dragging our mouse, otherwise they remain false.
On each timer tick, we’re going to do the following:
- update mouse drag and store it in variables, for left and right mouse buttons
- evaluate the zoom angle required for the lens
- adjust camera rotation (based on right mouse drag)
- adjust object rotation (based on left mouse drag)
Before we go into each function, let’s see what else is referenced on this graph.
Input mappings
Here we map the left mouse click will update previous location X (we don’t need Y for rotating object, but can map that too) as well as setting rotate in progress
to true.
We also map the right mouse button which will update both X and Y co-ordinates as well as setting zoom in progress
to true.
We also map the mouse wheel up/down which will control the zoom – we do this by increasing/reducing the zoom velocity variable, which we will process in a function that we’ll create shortly.
In order to map these inputs, click Edit -> Project Settings -> Input
This is how mine were defined, you can map to whatever keys you like.
Update drag
Getting drag is essentially getting the delta of the X and Y axis from last time it was executed.
That’s what this function does, we have a variable PrevLocX
and PrevLocY
storing the values of X and Y from previous iterations. Then we get the current X, Y co-ordinates and get the difference between them.
Evaluate and set zoom
Feel free to add new graph for zoom/rotate work, this is optional but could keep your work more tidy.
Let’s look into Evaluate and set zoom
Zoom is essentially the field of view – this is stored in a float
variable.
The Evaluate Field of View
function is specifically to evaluate what the value should be.
After we do so, we simply take our camera component and set the field of view to processed one (default camera is setup in few steps ahead).
In order to achieve smooth zoom in/out, we will use curves.
If the zoom velocity is positive, we use zoom in curve
, if velocity is negative, we’re zooming out, therefore using zoom out curve
.
After the processing, we will apply a small decay to the velocity (the multiplication by 0.9), which will ultimately bring it down to 0 with time.
Zoom curves
We want the minimum angle for camera lens to be 15 degrees and maximum 90 degrees.
The higher the angle, the more zoom we achieve. Do note for distortion as the angle becomes too high or too low.
The zoom in curve is used as a multiplier, which basically smoothens the zoom between 0 and 1 (0 means it will not zoom).
The zoom in curve is as follows:
The first point is 15, 0 as highlighted and the second is 90, 1 with auto tangents between them.
This means that as we zoom it will get less effective as you approach max zoom (at 15 degrees). Remember, the smaller the angle, the larger the zoom.
With zoom out curve, its essentially the opposite.
There are two keys again, first at 15, 1 and second at 90, 0. So as you zoom out, you will go from 15 degrees up to 90 degrees (max) at which point the multiplier drops to 0.
Process Field of View
Before we process the field of view, let’s first reference what it is that we’re changing.
In your map you can have your camera defined like this:
You can see the field of view
parameter is defined in the details of the camera. It’s essentially the camera lens that’s used.
Its up to you how to get the default camera variable from your player controller, I set it up in the construction of Player Controller blueprint using this:
Now that we have access to the camera and we know what the field of view parameter is, let’s process field of view.
Here we extract the current field of view of the camera and we get the float value from the curve which can be the zoom in/out curve.
If the camera field of view is currently almost 90 degrees and we’re trying to zoom out more – the multiplier will be basically 0 which means even if we’re adding velocity through our mouse wheel up/down, we’re not going to zoom out further.
Its basically the same for zoom in, with minimum allowed value of 15 degrees.
We then add the ‘zoom velocity’ (positive or negative) to current field of view and that’s how we get the resulting field of view.
That’s all for the Evaluate and set zoom function.
Adjust camera rotation
This is the next function after evaluating and setting zoom.
This custom event is responsible to evaluate the camera rotation velocity then apply it to the camera, after which reduce the overall velocity of rotation.
Let’s look inside ProcessCameraRotatorVelocity
This function will take the drag that we’ve evaluated earlier and convert it to velocity based on a multiplier. If you want to invert directions, you should add that here.
We will only add this if the right mouse button is clicked, i.e. the zoom in progress
boolean is true.
Next, let’s look at the RotateActor
function.
This is quite simple, we just take the reference of the actor and set actor rotation
.
Do note that Add actor rotation
should work, but for some reason it has some bugs, adding rotation to axis that had 0’s in. So perhaps in future versions of UE it should be fine.
That’s it for camera rotation! Let’s check the character rotation next.
Handle character rotation
This is the last piece from the tick event
This functionality also lives inside the Handle Rotate
graph, but feel free to put it in separate graph.
This custom event evaluates the rotate speed. Note the passed in argument of delta seconds – you can add it like this or just keep it as custom sensitivity parameter inside the function nested inside.
The HandleRotateHorizontalDragEvent
is as follows
We only process the object rotation velocity if the Rotate in progress
is true, i.e. the left mouse is pressed.
The process and set rotate velocity function essentially converts the drag into rotation velocity with some multipliers. Here is where the delta time is used – note that it can simply be a static variable.
The rotate actor function was the same one used for rotating the camera.
Again, note that add rotation
function may not work as expected – but feel to try it yourself.
And that’s it!
We now completed:
- zoom in/out with camera lens
- move camera field of view (rotate camera)
- rotate object
Good luck!