Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Cinemachine - How to add Zoom control to Freelook camera

Discussion in 'Cinemachine' started by muniraj_143, Nov 21, 2017.

  1. muniraj_143

    muniraj_143

    Joined:
    Oct 2, 2015
    Posts:
    23
    My project requires Zoom control along with Orbit control in Free Look camera.
    Can you please guide to add it to the existing script
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    You can directly manipulate the vcam's FOV with script, the same way you would manipulate an ordinary Camera's FOV. Something like this:
    Code (CSharp):
    1. using Cinemachine;
    2. CinemachineVirtualCamera vcam = bla;
    3. 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:
    Code (CSharp):
    1. using Cinemachine;
    2. CinemachineFreeLook vcam = bla;
    3. vcam.m_CommonLens = true;
    4. vcam.m_Lens.FieldOfView = 20;
    Otherwise, you'll have to maipulate the FOV of each of the rigs:
    Code (CSharp):
    1. using Cinemachine;
    2. CinemachineFreeLook vcam = bla;
    3. vcam.m_CommonLens = false;
    4. for (int i = 0; if < 3; ++i)
    5.     vcam.GetRig(i).m_Lens.FieldOfView = 20;
     
    Last edited: Nov 21, 2017
  3. OhiraKyou

    OhiraKyou

    Joined:
    Mar 27, 2012
    Posts:
    259
    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. Adam_Myhill

    Adam_Myhill

    Joined:
    Dec 22, 2016
    Posts:
    342
    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.
     
    DBarlok likes this.
  5. muniraj_143

    muniraj_143

    Joined:
    Oct 2, 2015
    Posts:
    23
    Thanks a lot for the help
     
  6. OhiraKyou

    OhiraKyou

    Joined:
    Mar 27, 2012
    Posts:
    259
    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.
     
    homemacai and Adam_Myhill like this.
  7. nswayze

    nswayze

    Joined:
    Nov 17, 2016
    Posts:
    21
    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.
     
  8. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    There is no single Camera Distance variable, as the radius is defined 3 times: once for each rig.
    Look at freeLook.m_Orbits.
     
  9. nswayze

    nswayze

    Joined:
    Nov 17, 2016
    Posts:
    21
    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
     
  10. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    In that case you'll want
    Code (CSharp):
    1. vcam.GetCinemachineComponent<CinemachineFramingTransposer>().m_CameraDistance = bla;
     
  11. mradfo21

    mradfo21

    Joined:
    May 16, 2013
    Posts:
    194
    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.
     
  12. nswayze

    nswayze

    Joined:
    Nov 17, 2016
    Posts:
    21
    Perfect. That's exactly what I was after. Thank you.
     
  13. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    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:

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

    then you can set the lens individually on each rig.
     
  14. mradfo21

    mradfo21

    Joined:
    May 16, 2013
    Posts:
    194
    oh neat Gergoryl! Awesome!
     
  15. Kev00

    Kev00

    Joined:
    Dec 6, 2016
    Posts:
    229
    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.
     
  16. Kev00

    Kev00

    Joined:
    Dec 6, 2016
    Posts:
    229
    ok I got zoom working this way

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

    Code (CSharp):
    1.  
    2.         private CinemachineFreeLook freelook;
    3.         private CinemachineFreeLook.Orbit[] originalOrbits;
    4.         public void Start()
    5.         {
    6.             freelook = GetComponentInChildren<CinemachineFreeLook>();
    7.             originalOrbits = new CinemachineFreeLook.Orbit[freelook.m_Orbits.Length];
    8.             for (int i = 0; i < freelook.m_Orbits.Length; i++)
    9.             {
    10.                 originalOrbits[i].m_Height = freelook.m_Orbits[i].m_Height;
    11.                 originalOrbits[i].m_Radius = freelook.m_Orbits[i].m_Radius;
    12.             }
    13.         }
    14.  
    15.         public void UpdateOrbit(float zoomPercent)
    16.         {
    17.  
    18.             for (int i = 0; i < freelook.m_Orbits.Length; i++)
    19.             {
    20.                 freelook.m_Orbits[i].m_Height = originalOrbits[i].m_Height * zoomPercent;
    21.                 freelook.m_Orbits[i].m_Radius = originalOrbits[i].m_Radius * zoomPercent;
    22.             }
    23.         }
     
    Last edited: Mar 8, 2018
  17. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
    Kev, please share for beginners where to insert your code lines.
    I really want my follow camera to scroll as well.
    Much obliged!
     
  18. Kev00

    Kev00

    Joined:
    Dec 6, 2016
    Posts:
    229
    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.

    Code (CSharp):
    1.  
    2. using System;
    3. using System.Collections.Generic;
    4. using System.Linq;
    5. using System.Text;
    6. using Cinemachine;
    7. using UnityEngine;
    8.  
    9. namespace Test
    10. {
    11.  
    12.     [RequireComponent(typeof(CinemachineFreeLook))]
    13.     class CinemachineFreeLookZoom : MonoBehaviour
    14.     {
    15.         private CinemachineFreeLook freelook;
    16.         private CinemachineFreeLook.Orbit[] originalOrbits;
    17.  
    18.         [Range(0.0F, 1F)]
    19.         public float zoomPercent;
    20.         public void Awake()
    21.         {
    22.             freelook = GetComponentInChildren<CinemachineFreeLook>();
    23.             originalOrbits = new CinemachineFreeLook.Orbit[freelook.m_Orbits.Length];
    24.  
    25.            
    26.             for (int i = 0; i < freelook.m_Orbits.Length; i++)
    27.             {
    28.                 originalOrbits[i].m_Height = freelook.m_Orbits[i].m_Height;
    29.                 originalOrbits[i].m_Radius = freelook.m_Orbits[i].m_Radius;
    30.             }
    31.         }
    32.  
    33.         public void Update()
    34.         {
    35.             for (int i = 0; i < freelook.m_Orbits.Length; i++)
    36.             {
    37.                 freelook.m_Orbits[i].m_Height = originalOrbits[i].m_Height * zoomPercent;
    38.                 freelook.m_Orbits[i].m_Radius = originalOrbits[i].m_Radius * zoomPercent;
    39.             }
    40.         }
    41.     }
    42. }
     
    DLeb and Gregoryl like this.
  19. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
    thank you but i cannot add that script due to this error:

    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
     
    Last edited: May 24, 2018
  20. Kev00

    Kev00

    Joined:
    Dec 6, 2016
    Posts:
    229
    did you name the script the same as the class? CinemachineFreeLookZoom.cs should be the name of the script.
     
  21. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
    no

    i will do it now .. brb
     
  22. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
    I did it now and it seem to work but the camera stays zoomed in
    I think i should work on some mouse scroll behavoiurs ( unity or AC module)
     
  23. Kev00

    Kev00

    Joined:
    Dec 6, 2016
    Posts:
    229
    yeah, it defaults to 0 so you need to zoom out with the sldier. also, make sure your orbit settings for all three rigs are large enough.
     
  24. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
    the orbits went to 0 for some reason .. i made them larger like 6-7 but it does not zoom on moving the scroll
    can u tell me a link where to read about linking scroll to camera ? i didnt find yet on google :)
    thank you!
     
  25. Kev00

    Kev00

    Joined:
    Dec 6, 2016
    Posts:
    229
    try changing zoomPercent code to.

    [Range(0.0F, 2F)]
    public float zoomPercent = 1f;
     
  26. Kev00

    Kev00

    Joined:
    Dec 6, 2016
    Posts:
    229
    Also make sure you have set the orbits of your TopRig, MiddleRig, and BottomRig correctly.

    I'm using a top down sort of view so mine are set to the following
    upload_2018-5-24_14-18-33.png
     
  27. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
    I did what you showed me and I also eneterd the AC module settings and find a setting to zoom window instead of pan if i scroll --- but still nothing when i press play in game window
    what i can tell is that i have the Brain on a GameCamera who is the default camera in AC and has the live camera from the Freeelok one.

    see here: http://myprintscreen.com/s/tout/3c808b44da

    in AC is like this
    http://myprintscreen.com/s/tov0/ac4e1e3e2c
    and pressing the mouse button and moving left right it pans
    this means that the input from mouse scroll wheel is readed (at least the pressing)
    on available inputs i have this
    http://myprintscreen.com/s/tov2/981d86faf9
    so i see zoom movable axes is present
    do i have to work on something here ? http://myprintscreen.com/s/tov5/b0249fee79

    this is the state drive camera: http://myprintscreen.com/s/tov8/24406ea325
    this is the freelook: http://myprintscreen.com/s/tov9/bb768163cf
    i also have a sprint camera as in the Cinemachine example -- should I add the script to that one too ? and the settings u gave me ? http://myprintscreen.com/s/tovb/c58400bbea
     
    Last edited: May 24, 2018
  28. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
    Last edited: May 24, 2018
  29. Kev00

    Kev00

    Joined:
    Dec 6, 2016
    Posts:
    229
    You need to add the script to all the freelook cameras you are using. In addition, make sure your freelook cameras have a follow target and lookat set.

    The mouse wheel isn't going to work unless you add more code to the zoom script I provided.

    When I have time I'll update the script with mouse wheel functionality.
     
  30. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
    the follow and lookat is setup ccorrectly as i tested my cameras and they worked good
    i just want the scrolling to work
    i requested support for AC developer because I found there is a special script for mousewheel they use.
    indeeed if u add the script with this functionality in your script it would get over the AC.
    i found some scripts but they are obsolete and i dont get yet how to use the new one with .delta
     
  31. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
    i succeded zooming in and out with some tricks on AC module
    it messes a bit the Cinemachine
    AC advised me to put a basic camera on Cinemachine cameras so they are recognised as normal cameras but this does not solve the zooming not working
    I am pretty sure the code needs a line of code to make the scroll working :)
     
    Last edited: May 25, 2018
  32. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    @Kev00 Thanks for posting your script. I took it and ran with it a little, adding MouseWheel support and addressing the issue that the scaled orbits get caught by SaveDuringPlay, crushing the original orbits when you exit play mode.

    @VP_3 Just add it as a component to every FreeLook that you want to be able to zoom.

    Don't do that. If you must do that, make sure to disable the Camera components.

    Here is the modified FreeLookZoom script:
    Code (CSharp):
    1. using UnityEngine;
    2. namespace Cinemachine
    3. {
    4.     [RequireComponent(typeof(CinemachineFreeLook))]
    5.     class CinemachineFreeLookZoom : MonoBehaviour
    6.     {
    7.         private CinemachineFreeLook freelook;
    8.         private CinemachineFreeLook.Orbit[] originalOrbits;
    9.         [Tooltip("The minimum scale for the orbits")]
    10.         [Range(0.01f, 1f)]
    11.         public float minScale = 0.5f;
    12.  
    13.         [Tooltip("The maximum scale for the orbits")]
    14.         [Range(1F, 5f)]
    15.         public float maxScale = 1;
    16.  
    17.         [Tooltip("The zoom axis.  Value is 0..1.  How much to scale the orbits")]
    18.         [AxisStateProperty]
    19.         public AxisState zAxis = new AxisState(0, 1, false, true, 50f, 0.1f, 0.1f, "Mouse ScrollWheel", false);
    20.  
    21.         void OnValidate()
    22.         {
    23.             minScale = Mathf.Max(0.01f, minScale);
    24.             maxScale = Mathf.Max(minScale, maxScale);
    25.         }
    26.  
    27.         void Awake()
    28.         {
    29.             freelook = GetComponentInChildren<CinemachineFreeLook>();
    30.             if (freelook != null)
    31.             {
    32.                 originalOrbits = new CinemachineFreeLook.Orbit[freelook.m_Orbits.Length];
    33.                 for (int i = 0; i < originalOrbits.Length; i++)
    34.                 {
    35.                     originalOrbits[i].m_Height = freelook.m_Orbits[i].m_Height;
    36.                     originalOrbits[i].m_Radius = freelook.m_Orbits[i].m_Radius;
    37.                 }
    38. #if UNITY_EDITOR
    39.                 SaveDuringPlay.SaveDuringPlay.OnHotSave -= RestoreOriginalOrbits;
    40.                 SaveDuringPlay.SaveDuringPlay.OnHotSave += RestoreOriginalOrbits;
    41. #endif
    42.             }
    43.         }
    44.  
    45. #if UNITY_EDITOR
    46.         private void OnDestroy()
    47.         {
    48.             SaveDuringPlay.SaveDuringPlay.OnHotSave -= RestoreOriginalOrbits;
    49.         }
    50.  
    51.         private void RestoreOriginalOrbits()
    52.         {
    53.             if (originalOrbits != null)
    54.             {
    55.                 for (int i = 0; i < originalOrbits.Length; i++)
    56.                 {
    57.                     freelook.m_Orbits[i].m_Height = originalOrbits[i].m_Height;
    58.                     freelook.m_Orbits[i].m_Radius = originalOrbits[i].m_Radius;
    59.                 }
    60.             }
    61.         }
    62. #endif
    63.  
    64.         void Update()
    65.         {
    66.             if (originalOrbits != null)
    67.             {
    68.                 zAxis.Update(Time.deltaTime);
    69.                 float scale = Mathf.Lerp(minScale, maxScale, zAxis.Value);
    70.                 for (int i = 0; i < originalOrbits.Length; i++)
    71.                 {
    72.                     freelook.m_Orbits[i].m_Height = originalOrbits[i].m_Height * scale;
    73.                     freelook.m_Orbits[i].m_Radius = originalOrbits[i].m_Radius * scale;
    74.                 }
    75.             }
    76.         }
    77.     }
    78. }
    79.  
     
    Last edited: May 25, 2018
    Kaden4, NSokolovskyi, AmyV and 4 others like this.
  33. Kev00

    Kev00

    Joined:
    Dec 6, 2016
    Posts:
    229
    wow, thanks.. I wasn't using SaveOnPlay so I didn't even know about that issue.
     
  34. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
    thank you!
    I have to add a basic cam to make it recognisable but I am disabling it and it all works good
    I will test now the scrolling thank you!
     
  35. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
    i have these errors
    upload_2018-5-25_20-30-53.png
    i have unity 2017.4.3f1
     
  36. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    Oh sorry, this script is only good for newer versions of CM, available with Unity 2018.1 and up.
    Maybe you should consider upgrading :)
     
  37. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
    I would like to upgrade but AC is not supporting yet 2018 beta
    what should I do now :( ?
     
  38. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    2018.1 is not beta
     
  39. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
  40. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    I think it's stable.

    Since my last post I've made a version of the FreeLookZoom script that's compatible with CM 2.1.10 and Unity 2017. However, it's a little different: Once you add it to your FreeLook, you have to use the FreeLookZoom fields to define the original orbits, the FreeLook orbits themselves will be always overwritten. It works, though.

    Here it is:
     

    Attached Files:

  41. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
    Thank you very much! I will test in 2018 after the upgrade and hopefully it will work there :)
    Huge fan of Cinemachine and it is the main reason that keeps me going to learn every day more Unity platform ;) I still have to learn about how to properly use every Orbit becasue there are so many combinations :)
     
  42. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
    I updated project to 2018.1.1f1
    I repimported CinemaMachine and reinstall.
    it has the same errors with the script you put inside.
    I will try the file you uploaded.
     
  43. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
    yupiii, your file works in .1 and it zooms and I have the controls !
    AWESOMENESS !
    thank you a million times!
     
  44. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    I'm guessing you reinstalled CM 2.1.10 from the asset store.
    To get the latest version of CM, open the Package Manager window and install it from there.
    But before you do, you must delete the asset-store Cinemachine asset from your project, as it says on the package manager panel.
    That is, if you want to upgrade. Sounds like you don't need to just yet.
     
  45. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
    I updated more packages with package manager, I deleted the CM folders and then got it with PM.
    I have these errors I cannot get over
    upload_2018-5-26_9-11-38.png
    the file I use is the one you attached
     
  46. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
    Maybe this helps too:
    upload_2018-5-26_9-18-11.png
     

    Attached Files:

  47. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    Yes, that's because the script was adapted to work with CM 2.1.10. If you open it, you'll see a couple of
    Code (CSharp):
    1. # if true
    statements inside it. Change them to
    Code (CSharp):
    1. #if false
    to make it compatible with CM 2.1.13
     
  48. VP_no1

    VP_no1

    Joined:
    May 12, 2018
    Posts:
    132
    It works with those small changes!
    Thank you a bunch! Hopefully it will help some others too ;)
     
    Last edited: May 27, 2018
  49. MSachs

    MSachs

    Joined:
    Nov 22, 2017
    Posts:
    122
    Hi guys!

    I implemented the code to zoom using the mouse wheel and it works as intended. But I also have a code implemented, which only let's me move the camera when the left mouse button is pressed.

    Code (CSharp):
    1. using Cinemachine;
    2. using UnityEngine;
    3.  
    4. [RequireComponent(typeof(CinemachineFreeLook))]
    5. public class CameraControl: MonoBehaviour
    6. {
    7.     public bool _freeLookActive;
    8.  
    9.  
    10.     private void Start ()
    11.     {
    12.         CinemachineCore.GetInputAxis = GetInputAxis;
    13.     }
    14.  
    15.  
    16.     private void Update()
    17.     {
    18.         _freeLookActive = Input.GetMouseButton(0);
    19.     }
    20.  
    21.  
    22.     private float GetInputAxis(string axisName)
    23.     {
    24.         return !_freeLookActive ? 0 : Input.GetAxis(axisName == "Mouse Y" ? "Mouse Y" : "Mouse X");
    25.     }
    26. }
    The two scripts seem to conflict with each other since when both scripts are activated the zoom with the mouse wheel doesn't work anymore but in stead it zooms when the left mouse button is pressed and the mouse is moved from left to right or right to left. What would be the best way to make both scripts work together? :)
     
    ugotstoopt likes this.
  50. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    Your problem is here:
    Code (CSharp):
    1.  
    2.     private float GetInputAxis(string axisName)
    3.     {
    4.         return !_freeLookActive ? 0 : Input.GetAxis(axisName == "Mouse Y" ? "Mouse Y" : "Mouse X");
    5.     }
    You have aggressively told all of Cinemachine to ignore all input unless the mouse button is pressed, and to have all axis requests other than Mouse Y mapped to Mouse X. Probably that's not what you intended to do.

    Instead of globally overriding GetInputAxis(), why don't you do something more targeted, like: when the button is pressed, set the freeLook's axis names to "Mouse X" and "Mouse Y", else set them to "".
     
    ugotstoopt likes this.