Camera Follow Logic
Objective: make the camera follow the character… but not just follow, not just always
Cool stuff ahead!
I wanted to make the camera follow the player when moving, but not always. I mean that I don’t want the camera to be fixed and attached to the player and always move with it.
For that, you just have to make the camera child of the player, set a relative position and the player would just appear fixed on the screen while the environment moves around him. I don’t like it.
I was looking for something more similar to Super Mario World: you can move Mario on the screen without having the camera follow him, until he reaches some threshold in each direction (up, down, left right). In that case, and only in that case, the camera moves and follows him.
To make it clearer let’s look at this.
The red rectangle is a gizmo, painted on the screen, or camera if you want. It represents our threshold: when the character reaches its border, we have to properly follow it with the camera, but if we stay inside of it the camera stands still.
Let’s build this up, gizmo included!
We’re going to have a script attached to the camera, CameraFollow. Let’s begin with the rectangle calculation.
Orthographic size property of the camera is the measure, in pixels, of half the width of the screen, while aspect is the aspect ratio (e.g. 16:9).
Our threshold values will be stored in a vector2 field and we just need half the measures since the check is going to be performed in both directions. From the screen measure we subtract an offset value (again stored in a vector2 field): the greater the value, the narrower the threshold rectangle, if zero we are going to have our screen as threshold and the camera will follow only if we reach the screen borders.
Now we want to paint the rectangle so we can adjust it via inspector and have a much clearer view of what will happen.
Remember that gizmos are painted on the scene view, not game view.
OnDrawGizmos() draws continuously the gizmos on the scene view. We pick the colour, set the threshold value with the calculation and draw a cube which centre is the camera position and sizes are a vector3: x and y are the threshold multiplied by two, z is irrelevant.
Now it’s time for the follow logic.
It is much simpler than it looks. This method is going to be called in
Update() so every frame: we calculate the distance on x and y axes between character and camera as simple absolute value of x and y component difference.
We store the camera position in a variable, if the distances are greater than the corresponding threshold we replace the position component with the corresponding player position: if we go right above the threshold, the new camera position must have the same y and x equal to the player one.
Now the following, if we just set the new camera position we are going to have a snap effect (not ugly, but not what we want). Instead, we are going to set that position with the
MoveTowards() method (which ignores the local properties, taken into account by
As for the speed: we will have a custom speed, but since the player can overcome that (e.g. while falling and accumulating speed) we are going to use the maximum value between this custom speed and the actual player speed in order to avoid two major defects:
- camera following too slowly (camera speed much slower than player one)
- micro-snaps (the opposite condition)
Let’s look at the result, both in game and in scene view.