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. MSachs

    MSachs

    Joined:
    Nov 22, 2017
    Posts:
    122
    Oh that actually wasn't my intention at all. Then again I didn't write that code myself :rolleyes:
    How exactly do I change the axis names via script? Just tried a few things but it doesn't seem to work like that...
     
    ugotstoopt likes this.
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    something like:
    var freeLook = GetComponent<CinemachineFreeLook>();
    freeLook.m_XAxis.m_InputAxisName = "blabla";
    etc
     
    ugotstoopt likes this.
  3. MSachs

    MSachs

    Joined:
    Nov 22, 2017
    Posts:
    122
    Okay great, thank you. It works... kind of. For some reason now the Decel Time doesn't get triggered when releasing the button... so the camera just spins around the target forever.
     
    ugotstoopt likes this.
  4. MSachs

    MSachs

    Joined:
    Nov 22, 2017
    Posts:
    122
    Just kind of fixed it by adding a WaitForSeconds to delay the reset of the axis a split second. don't know if thats the best way though.

    Edit: It appears to happen, when the Mouse is moving the second the input gets turned of. Then it kind of saves the mouse movement and continues to spin around as long as the input isn't turned on again. Is there a command to force the deceleration to happen?
     
    Last edited: Sep 14, 2018
  5. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    Right. You also need to set the m_xAxis.m_InputAxisValue to zero, or it simply freezes with the last value seen.
     
    ugotstoopt and MSachs like this.
  6. MSachs

    MSachs

    Joined:
    Nov 22, 2017
    Posts:
    122
    Great! Thanks a lot!
     
  7. protopop

    protopop

    Joined:
    May 19, 2009
    Posts:
    1,557
    Thank you:) You have dropped so many helpful cinema chine hints in the forum. Im working on my third open world game and decided to try cinemachine - it looks great and all the extra options (peril noise, etc) give it a professional feel.
     
    Gregoryl likes this.
  8. Bubsavvy

    Bubsavvy

    Joined:
    Sep 18, 2017
    Posts:
    48
    Its kind of wonky, but you can also do something like this if you want to go the extension route.

    Code (CSharp):
    1. using UnityEngine;
    2. using Cinemachine;
    3.  
    4. [ExecuteInEditMode]
    5. [SaveDuringPlay]
    6. [AddComponentMenu("")] // Hide in menu
    7. public class CinemachineOrbitalZoom : CinemachineExtension
    8. {
    9.     [Range(0f, 15f)]
    10.     public float zoomMin;
    11.     [Range(15f, 30f)]
    12.     public float zoomMax;
    13.     [Range(0f, 1f)]
    14.     public float zoomAngle;
    15.  
    16.     protected override void PostPipelineStageCallback(CinemachineVirtualCameraBase vcam, CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
    17.     {
    18.         CinemachineFreeLook freeLook = vcam.ParentCamera as CinemachineFreeLook;
    19.  
    20.         // This extention only works for free look cameras
    21.         if (!freeLook)
    22.             return;
    23.  
    24.         if (enabled && stage == CinemachineCore.Stage.Body)
    25.         {
    26.  
    27.             float bottomRigHypotenuse = zoomMin;
    28.             float bottomRigAdjacent = Mathf.Cos(zoomAngle) * bottomRigHypotenuse;
    29.             float bottomRigOpposite = Mathf.Sin(zoomAngle) * bottomRigHypotenuse;
    30.  
    31.             float middleRigHypotenuse = zoomMin +(zoomMax - zoomMin) / 2;
    32.             float middleRigAdjacent = Mathf.Cos(zoomAngle) * middleRigHypotenuse;
    33.             float middleRigOpposite = Mathf.Sin(zoomAngle) * middleRigHypotenuse;
    34.  
    35.             float topRigHypotenuse = zoomMax;
    36.             float topRigAdjacent = Mathf.Cos(zoomAngle) * topRigHypotenuse;
    37.             float topRigOpposite = Mathf.Sin(zoomAngle) * topRigHypotenuse;
    38.  
    39.             freeLook.m_Orbits[2].m_Height = bottomRigAdjacent;
    40.             freeLook.m_Orbits[2].m_Radius = bottomRigOpposite;
    41.  
    42.             freeLook.m_Orbits[1].m_Height = middleRigAdjacent;
    43.             freeLook.m_Orbits[1].m_Radius = middleRigOpposite;
    44.  
    45.             freeLook.m_Orbits[0].m_Height = topRigAdjacent;
    46.             freeLook.m_Orbits[0].m_Radius = topRigOpposite;
    47.         }
    48.     }
    49. }
     
  9. Michal_Stangel

    Michal_Stangel

    Joined:
    Apr 17, 2017
    Posts:
    151
    I use this script (quoted) to control camera zooming. It works fine, but now I switched to the new Input System and I am quite lost. I added CinemachineInputProvider component to free look camera and added references for input actions. One for XY axis and one for scrolling action for Z axis. It works fine for camera rotation and method GetAxisValue(int axis) inside CinemachineInputProvider is called to read axis 0 and 1 values. However it's not the case for axis 2, which should be Z axis I suppose. Method is not called to read scrolling input action value. What should I do to make it work?
     
  10. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    Try adding this code in Awake():
    Code (CSharp):
    1. zAxis.SetInputAxisProvider(2, freelook.GetInputAxisProvider());
     
  11. Michal_Stangel

    Michal_Stangel

    Joined:
    Apr 17, 2017
    Posts:
    151
    Didn't expect it to be that easy, thank you!
    Values from the new input system are again really big, about 120 when scrolling, but it's only subject of speed adjustment.
     
  12. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    You can also try adding scaling to your input channel, to more closely mimic the legacy input system
     
  13. Michal_Stangel

    Michal_Stangel

    Joined:
    Apr 17, 2017
    Posts:
    151
    Added Scale Processor with value 0.001 and it matches old input system speed. Thanks again for quick help.
     
  14. hawaiian_lasagne

    hawaiian_lasagne

    Joined:
    May 15, 2013
    Posts:
    120
    How can I implement camera zoom using a second free look camera with a different rig compared to the first camera I'm blending from? It kind of works, except the resulting camera direction after blending is not the same as the first, sometimes it is even pointing 180 deg in the other direction. How can I fix this please?
     
  15. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
  16. hawaiian_lasagne

    hawaiian_lasagne

    Joined:
    May 15, 2013
    Posts:
    120
    Ok that helps.. but the direction still ends up being off. The camera I blend to has a much smaller rig radius and height, so it then sort of just snaps to the closest direction from the inherited position. If you imagine a 3rd person camera, I’m zooming In and the cross hair should stay fixed in the center of the screen over the same object after zooming.
     
  17. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    Are your LookAt target and your Follow target set to the same point? If not, then that might be contributing to this problem. Try setting them to the same thing.
     
  18. hawaiian_lasagne

    hawaiian_lasagne

    Joined:
    May 15, 2013
    Posts:
    120
    Yes both LookAt and Follow targets are the same. I did a little more digging into it and found different FOV and camera offsets will produce a slight shift in the aim, but it's not too bad.

    It is worst when the rig radius on one of the cameras is smaller than the other. Could it be because 'inherit position' results in a different camera angle for the same mouse coordinates between the two cameras?
     
  19. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    Is it looking right at the LookAt target, or is there a Tracked Object Offset in the Composer?
     
  20. hawaiian_lasagne

    hawaiian_lasagne

    Joined:
    May 15, 2013
    Posts:
    120
    No there is no offset. The two cameras are FreeLookCameras with 'WorldSpace' as the binding mode. The only difference between them is the middle rig radius.

    My lookat target is the character's head, and the follow target is the base of the character.
     
    Last edited: Aug 17, 2020
  21. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    Can you try setting both the LookAt target AND the Follow target to the head? You will need to adjust the orbit heights appropriately.
     
  22. hawaiian_lasagne

    hawaiian_lasagne

    Joined:
    May 15, 2013
    Posts:
    120
    Yes that fixes it, thank you!

    I was about to switch over and use the 3rd person follow virtual cam, as that rig seemed better out of the box. Now I'm not sure what is better, blending between two cameras or animating one.

    Are there any major differences/benefits you can think of?
     
  23. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    The two approaches are quite different. The FreeLook gives you the out-of-the-box benefit of different settings for top/middle/bottom rigs, but comes at the cost of complexity and slower performance.

    I generally try to encourage use of the 3rdPersonFollow setup, as it is more efficient and better suited to the purpose. See the AimingRig sample scene for an example of that.

    You might also consider looking at the 3rdPersonWithAimMode sample scene, for yet another alternative. This one uses a Framing Transposer + POV instead of the FreeLook.

    As for whether it's better to blend or to animate settings, that depends on the effect you're trying to get, and how many different variations there are. Animating is good if you might want to hold at an intermediary point in the blend.
     
  24. hawaiian_lasagne

    hawaiian_lasagne

    Joined:
    May 15, 2013
    Posts:
    120
    I ended up switching over to use 3rdPersonFollow camera. I'm loving that camera collision comes with it out of the box too.

    No need to blend between cameras anymore as the 3rd person follow cam keeps the character in frame when changing the camera distance. Just what I needed!

    Thanks again for your help
     
    Gregoryl likes this.
  25. DLeb

    DLeb

    Joined:
    Feb 13, 2019
    Posts:
    10
    The script may look stupid and oversimplified by the way - I want to share the code with anybody who is trying to implement mouse scroll control not for cinemachine camera zooming but for direct freeLookCamera's Orbits Height and Value control. I used Kev00 code as basis:

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

    [RequireComponent(typeof(CinemachineFreeLook))]
    public class CinemachineOrbitsController : MonoBehaviour//CinemachineExtension
    {
    public CinemachineFreeLook.Orbit m_Orbits;
    public CinemachineFreeLook freelook;
    private CinemachineFreeLook.Orbit[] originalOrbits;
    public float mouseScrollIndex = 1f;

    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.m_Height = freelook.m_Orbits.m_Height;
    originalOrbits.m_Radius = freelook.m_Orbits.m_Radius;
    }
    }

    public void Update()
    {
    mouseScrollIndex = mouseScrollIndex + (float)Input.mouseScrollDelta.y*0.1f;
    if (mouseScrollIndex<0.3f)
    {
    mouseScrollIndex=0.3f;
    }
    if (mouseScrollIndex>1.3f)
    {
    mouseScrollIndex=1.3f;
    }
    for (int i = 0; i < freelook.m_Orbits.Length; i++)
    {
    freelook.m_Orbits.m_Height = originalOrbits.m_Height * mouseScrollIndex;// - I use multiplier to change cinemachine orbits values you can also use + mouseScrollIndex for more gradual calculation.
    freelook.m_Orbits.m_Radius = originalOrbits.m_Radius * mouseScrollIndex;
    }
    }
    }

    (Script should be attached to a cinemachine FreeLook Camera or to a Gameobject with such children/component)
    In realtime the player is able to make the position of Camera closer/farther without constant camera zoom
     
  26. Leif_In_The_Wind

    Leif_In_The_Wind

    Joined:
    Oct 17, 2020
    Posts:
    1
    I just wanted to thank all of you for working on this (especially Gregoryl and Kev00), this is a really useful little script!
     
    Gregoryl likes this.
  27. nobluff67

    nobluff67

    Joined:
    Nov 3, 2016
    Posts:
    338
    3 years later, just want to confirm that this is still the way to go?
     
  28. beariscool123

    beariscool123

    Joined:
    Oct 8, 2020
    Posts:
    2
    To add zoom use this code


    Code (CSharp):
    1. public CinemachineCameraOffset playerzoomcam;
    2.   if (Input.GetAxis("Mouse ScrollWheel") > 0f)
    3.         {
    4.             playerzoomcam.m_Offset.z += 3;
    5.         }
    6.         if (Input.GetAxis("Mouse ScrollWheel") < 0f)
    7.         {
    8.             playerzoomcam.m_Offset.z -= 3;
    9.         }
    Then on your free look camera add a camera offset component and drag it on the script
     
    nobluff67 and protopop like this.
  29. beariscool123

    beariscool123

    Joined:
    Oct 8, 2020
    Posts:
    2
    No you can use my code its simpler
     
    nobluff67 likes this.
  30. Radivarig

    Radivarig

    Joined:
    May 15, 2013
    Posts:
    119
    @beariscool123 with some smooth interpolations:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class CinemachineZoom : MonoBehaviour
    4. {
    5.     public CinemachineCameraOffset playerzoomcam;
    6.     public float scrollSensitivity = 3;
    7.     public float lerpSpeed = 10;
    8.     public float minDistance = 10;
    9.     public float maxDistance = 30;
    10.     float targetDistance;
    11.  
    12.     void SetTargetDistance(float value)
    13.     {
    14.         targetDistance = Mathf.Clamp(value, minDistance, maxDistance);
    15.     }
    16.  
    17.     void Update()
    18.     {
    19.         if (Input.GetAxis("Mouse ScrollWheel") > 0f)
    20.         {
    21.             SetTargetDistance(targetDistance - scrollSensitivity);
    22.         }
    23.         else if (Input.GetAxis("Mouse ScrollWheel") < 0f)
    24.         {
    25.             SetTargetDistance(targetDistance + scrollSensitivity);
    26.         }
    27.  
    28.         playerzoomcam.m_Offset.z = Mathf.Lerp(
    29.             playerzoomcam.m_Offset.z, -targetDistance, Time.deltaTime * lerpSpeed);
    30.     }
    31. }
    32.  
     
    beariscool123 likes this.
  31. MikkoHaavisto

    MikkoHaavisto

    Joined:
    Apr 17, 2021
    Posts:
    2
    Here is a super simple way to make mouse scroll adjust field of view. Attach the script to a CM vcam object with a CinemachineVirtualCamera component. Note that this is for following camera, not a mouse look camera.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using Cinemachine;
    4.  
    5. public class CameraController : MonoBehaviour
    6. {
    7.     private CinemachineVirtualCamera vcam;
    8.     public float zoomSpeed = 40;
    9.  
    10.     void Start()
    11.     {
    12.         vcam = GetComponent<CinemachineVirtualCamera>();
    13.     }
    14.  
    15.     void Update()
    16.     {
    17.         vcam.m_Lens.FieldOfView -= Input.GetAxis("Mouse ScrollWheel") * zoomSpeed;
    18.         vcam.m_Lens.FieldOfView = Mathf.Clamp(vcam.m_Lens.FieldOfView, 40, 100);
    19.     }
    20. }
    21.  
     
    Lefko and Organik05 like this.
  32. Organik05

    Organik05

    Joined:
    Feb 15, 2016
    Posts:
    10
    is this still usable?

     
  33. Organik05

    Organik05

    Joined:
    Feb 15, 2016
    Posts:
    10
    Thanks dude, I am using a character controller with a camera already on it and it doesn't include zoom so I was trying to figure out a way to do it and seems like the virutal camera is the best so far.
     
  34. Shadeace7278

    Shadeace7278

    Joined:
    Sep 19, 2021
    Posts:
    1
    How do I make
    I tries this and it worked well, but how do i make it zoom on right mouse clicked instead of mouse wheel?
     
  35. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    @Shadeace7278 I don't understand what you want. Right-click and what should happen?
     
  36. squirtpistol

    squirtpistol

    Joined:
    Jan 23, 2021
    Posts:
    2
    If none of this works delete the Cinemachine and then the the size on the main camera and then re ad the Cinemachine