Cinemachine - How to add Zoom control to Freelook camera

My project requires Zoom control along with Orbit control in Free Look camera.
Can you please guide to add it to the existing script

You can directly manipulate the vcamā€™s FOV with script, the same way you would manipulate an ordinary Cameraā€™s FOV. Something like this:

using Cinemachine;
CinemachineVirtualCamera vcam = bla;
vcam.m_Lens.FieldOfView = 20;

For a FreeLook, there is the added complexity that itā€™s possible to have separate lens setting on each of the 3 internal rigs. The simplest solution is to use a common lens:

using Cinemachine;
CinemachineFreeLook vcam = bla;
vcam.m_CommonLens = true;
vcam.m_Lens.FieldOfView = 20;

Otherwise, youā€™ll have to maipulate the FOV of each of the rigs:

using Cinemachine;
CinemachineFreeLook vcam = bla;
vcam.m_CommonLens = false;
for (int i = 0; if < 3; ++i)
    vcam.GetRig(i).m_Lens.FieldOfView = 20;
11 Likes

FOV manipulation is a pretty bad idea for a player driven camera if the zoom is an important gameplay control rather than a simple visual effect that the player can disable in a settings menu. The change in FOV can induce simulator sickness, and thereā€™s a limit to how far you can feasibly zoom in or out with FOV alone without introducing significant distortion.

Instead, my best suggestion at the moment would be to interpolate the orbit circle offsets and radii to simulate the orbit itself expanding. Ideally, Iā€™d like a utility function that calculates and sets the offset and radius values based on an origin position offset, radius, lower angle limit, and upper angle limit, as calculating those values manually is quite clunky, to say the least. Although, as I havenā€™t updated Cinemachine in a while, itā€™s possible that calculating those values has been simplified in a more recent version.

4 Likes

Or just blend between different freelooks based on game events. That way you can sculpt the outcome VS driving an input.

The Gears of War ā€˜Roadie Runā€™ is an example of an FOV change on a player driven camera. Definitely needs to be done in moderation and with skill.

1 Like

Thanks a lot for the help

Oh! You can also probably just nest a virtual camera as a child of the free lookā€™s virtual camera, pull it back as far as you need, and then blend between those two. The free lookā€™s camera would then drive the zoom out camera automatically. The downside is that you might have to reduce the free lookā€™s speed to compensate for the extra perceived speed caused by being farther from the orbitā€™s center.

2 Likes

Hi Gregoryl. Thanks for providing your help.

I understand that you can use vcam.m_lens.FieldOfView to adjust the FOV but how do I adjust the ā€œCamera Distanceā€ variable? I canā€™t seem to find it.

There is no single Camera Distance variable, as the radius is defined 3 times: once for each rig.
Look at freeLook.m_Orbits.

Oh sorry I took things out of context after skimming through different threads. Iā€™m not using a freelook camera but a virtual camera with a framing transposer (as a 3D Platformer) is freeLook.m_Orbits still the best place to modify? thanks

In that case youā€™ll want vcam.GetCinemachineComponent<CinemachineFramingTransposer>().m_CameraDistance = bla;

4 Likes

i think adding the different fields of view would be a welcome addition. That trick of bringing the camera in, looking up, and widening the FOV from Journey is a brilliant notion. And I know weā€™re all looking for a way to implement it. Cinemachine is SO close to easily providing this functionality.

Perfect. Thatā€™s exactly what I was after. Thank you.

If youā€™re talking about the possibility of having different FOV settings on each of the 3 FreeLook rigs, then we already have it. If you uncheck this:

3399102--267539--upload_2018-2-21_9-30-33.png

then you can set the lens individually on each rig.

oh neat Gergoryl! Awesome!

For a camera zoom, is it not possible to change the height and radius uniformly?

It would be nice if the freelook camera used the mouse wheel to do this automatically across all three rigs. That way I could use the GetInputAxis delgate.

ok I got zoom working this way

just figure out the percentage of your zoom and call UpdateOrbit on Update();

        private CinemachineFreeLook freelook;
        private CinemachineFreeLook.Orbit[] originalOrbits;
        public void Start()
        {
            freelook = GetComponentInChildren<CinemachineFreeLook>();
            originalOrbits = new CinemachineFreeLook.Orbit[freelook.m_Orbits.Length];
            for (int i = 0; i < freelook.m_Orbits.Length; i++)
            {
                originalOrbits[i].m_Height = freelook.m_Orbits[i].m_Height;
                originalOrbits[i].m_Radius = freelook.m_Orbits[i].m_Radius;
            }
        }
 
        public void UpdateOrbit(float zoomPercent)
        {
 
            for (int i = 0; i < freelook.m_Orbits.Length; i++)
            {
                freelook.m_Orbits[i].m_Height = originalOrbits[i].m_Height * zoomPercent;
                freelook.m_Orbits[i].m_Radius = originalOrbits[i].m_Radius * zoomPercent;
            }
        }
4 Likes

Kev, please share for beginners where to insert your code lines.
I really want my follow camera to scroll as well.
Much obliged!

Sure here you go. Add this script to the game object with your CinemachineFreeLookCamera.

For the sake of simplicity, you can use the slider to change the zoom.

Please note that the initial orbit settings for the FreeLook camera will be your max zoom, but you should be able to modify the range of the slider to change that.

In my game Iā€™ve hooked the slider up to my mouse wheel and added a Lerp.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cinemachine;
using UnityEngine;

namespace Test
{

    [RequireComponent(typeof(CinemachineFreeLook))]
    class CinemachineFreeLookZoom : MonoBehaviour
    {
        private CinemachineFreeLook freelook;
        private CinemachineFreeLook.Orbit[] originalOrbits;

        [Range(0.0F, 1F)]
        public float zoomPercent;
        public void Awake()
        {
            freelook = GetComponentInChildren<CinemachineFreeLook>();
            originalOrbits = new CinemachineFreeLook.Orbit[freelook.m_Orbits.Length];

           
            for (int i = 0; i < freelook.m_Orbits.Length; i++)
            {
                originalOrbits[i].m_Height = freelook.m_Orbits[i].m_Height;
                originalOrbits[i].m_Radius = freelook.m_Orbits[i].m_Radius;
            }
        }

        public void Update()
        {
            for (int i = 0; i < freelook.m_Orbits.Length; i++)
            {
                freelook.m_Orbits[i].m_Height = originalOrbits[i].m_Height * zoomPercent;
                freelook.m_Orbits[i].m_Radius = originalOrbits[i].m_Radius * zoomPercent;
            }
        }
    }
}
2 Likes

thank you but i cannot add that script due to this error:

3508802--280038--upload_2018-5-24_20-0-57.png

it is because of 1 line i see
using System.Collections;
instead of simple System

brb to test

did you name the script the same as the class? CinemachineFreeLookZoom.cs should be the name of the script.