Search Unity

Question How to make a Virtual Cam work nearly identical to Free Look Cam, except ???

Discussion in 'Cinemachine' started by AerionXI, May 17, 2022.

  1. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    Can someone please show an example in Script of how to make a virtual camera work exactly like an orbit free look camera? For some reason with Free look, I can no longer position / rotate the camera to how I want it and that is a problem. I need to be able to give my camera a correct starting position / rotation even when targeting the player.

    Thank you!
     
  2. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    Can someone please help? Much thanks!
     
  3. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,730
    You mean you want to re-write FreeLook in a script?
    Vague questions such as this one are difficult to answer.
    It would help if you could describe exactly what camera behaviour you're trying to achieve. Perhaps there is a way to get FreeLook to do what you want.
    Pictures and videos would help too.
     
  4. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    Hi there, Gregoryl! So what I am trying to do is create a full, SMOOTH Orbit Camera with mouse wheel zoom in / out with a Virtual Camera because no matter what I do, I cannot seem to move / rotate the Free Look Camera to a default starting Position / Rotation. It does what it wants basically & puts it in the same Position / Rotation every time without me being able to specify how I want the Camera 1st Positioned / Rotated when the Game 1st starts.
     
  5. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,730
    Have you tried calling FreeLook.ForceCameraPosition()?

    Also: "a full, SMOOTH Orbit Camera with mouse wheel zoom in / out" can you elaborate on this? What is a full orbit? Can you describe the target and its movement, and what you want the camera to do?
     
  6. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    Ok, so a full Camera Orbit has the ability to rotate its' Pitch up to 90.0f degrees, or down to -90.0f degrees. It also can rotate on the Y Axis to -180 & 180 degrees. But when you're looking up at the sky, the Camera should drag smoothly on the Ground towards the player and then stop at a given value. Same thing when looking down at the ground, except it should zoom into the player's head until a given point. Then combine it with Fade nearby objects to create a transparent zoom-like effect. Also, smooth means Interpolate the values so the Camera smoothly stays on course when rotating / positioning to its' point. The zoom part is simple. You are able no matter at what angle to zoom in / out smoothly using the Mousewheel up to a certain value.
     
  7. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,730
    When the camera rotates, does it keep the target always in view?
     
  8. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
  9. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,730
    You can use a vcam with FramingTransposer in Body and POV in Aim. Have a look at the 3rdPersonWithAimMode sample scene. It uses that setup. You can adjust the limits of the POV to give you a full Y orbit.

    For the scrollwheel zoom, you will have to write a custom script that manipulates the FramingTransposer's m_CameraDistance field in response to the scrollwheel input.
     
  10. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,730
    @AerionXI Have a look at MouseScrollZoom2D.cs that ships with the CM samples. It implements mouse scroll zoom. You will have to change it a little so that it modifies FramingTransposer.m_CameraDistance instead of Lens.OrthographicSize, but it is a good starting point.
     
  11. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    So I decided to use 3rdPersonWithAimMode's `Framing Transposer` and it works great. I have combined it with this script I both found on the net & tweaked. Problem is, when I hold down Mouse Button left and drag, the Orbit is not smooth, and when I roll the mouse wheel, zoom is not smooth. So, I have tried to rotate the cameras behind the player, but for some reason I cannot get the cameras to stay behind the Player... Also, when I zoom out and drag the camera across the ground, the camera won't stay above the ground even with a CinemachineCollider as seen in this small video I attached to this post.



    Here's the current Script:

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using Cinemachine;
    6.  
    7. public class CinemachineMouseDown : MonoBehaviour {
    8.  
    9.     CinemachineVirtualCamera vcam;
    10.     CinemachineFramingTransposer framingTransposer;
    11.  
    12.     [ SerializeField ]
    13.     private float startingCameraDistance = 1.0f;
    14.  
    15.     [ Space ( 5 ) ]
    16.  
    17.     [ SerializeField ]
    18.     private float minCameraDistance = 1.0f;
    19.  
    20.     [ SerializeField ]
    21.     private float maxCameraDistance = 45.0f;
    22.  
    23.     [ Space ( 10 ) ]
    24.  
    25.     [ Range ( 0.025f, 1.0f ) ]
    26.  
    27.     [ SerializeField ]
    28.     private float scrollSensitivity = 0.5f;
    29.  
    30.     public bool negateScrollDirection = false;
    31.  
    32.     public float maxLookaheadTime = 0.0f;
    33.     public float lookaheadAdjusted = 0.0f;
    34.  
    35.     public void NewCameraDistance ( float adjustedScroll ) {
    36.  
    37.         if ( negateScrollDirection ) {
    38.             framingTransposer.m_CameraDistance = Mathf.Clamp (
    39.                 framingTransposer.m_CameraDistance += adjustedScroll,
    40.                 minCameraDistance,
    41.                 maxCameraDistance
    42.             );
    43.         }
    44.         else {
    45.             framingTransposer.m_CameraDistance = Mathf.Clamp (
    46.                 framingTransposer.m_CameraDistance -= adjustedScroll,
    47.                 minCameraDistance,
    48.                 maxCameraDistance
    49.             );
    50.         }
    51.  
    52.         if ( maxLookaheadTime == 0 ) { return; }
    53.  
    54.         lookaheadAdjusted = Mathf.Clamp (
    55.             framingTransposer.m_CameraDistance / maxCameraDistance,
    56.             0.1f,
    57.             maxLookaheadTime
    58.         );
    59.  
    60.         framingTransposer.m_LookaheadTime = lookaheadAdjusted;
    61.  
    62.     }
    63.  
    64.     public float GetAxisCustom ( string axisName ) {
    65.  
    66.         if ( axisName == "Mouse X" ) {
    67.             if ( Input.GetMouseButton ( 0 ) ) {
    68.                 return UnityEngine.Input.GetAxis ( "Mouse X" );
    69.             }
    70.             else {
    71.                 return 0;
    72.             }
    73.         }
    74.  
    75.         if ( axisName == "Mouse Y" ) {
    76.             if ( Input.GetMouseButton ( 0 ) ) {
    77.                 return UnityEngine.Input.GetAxis ( "Mouse Y" );
    78.             }
    79.             else {
    80.                 return 0;
    81.             }
    82.         }
    83.  
    84.         return UnityEngine.Input.GetAxis ( axisName );
    85.  
    86.     }
    87.  
    88.     void Start ( ) {
    89.  
    90.         CinemachineCore.GetInputAxis = GetAxisCustom;
    91.  
    92.         vcam = GetComponent <CinemachineVirtualCamera> ( );
    93.  
    94.         framingTransposer = vcam.GetCinemachineComponent <CinemachineFramingTransposer> ( );
    95.         framingTransposer.m_CameraDistance = startingCameraDistance;
    96.         maxLookaheadTime = framingTransposer.m_LookaheadTime;
    97.  
    98.     }
    99.  
    100.     void LateUpdate ( ) {
    101.  
    102.         if ( Input.mouseScrollDelta.y != 0.0f ) {
    103.             var scroll = Input.mouseScrollDelta.y;
    104.             var adjustedScroll = scroll * scrollSensitivity;
    105.             NewCameraDistance ( adjustedScroll );
    106.         }
    107.  
    108.     }
    109.  
    110. }
    Much thanks!
     
  12. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,730
    I don't understand what you're trying to make. Can you describe clearly the camera behaviour you want to have? How should it respond to player movement and rotation? How should it respond to user input? Is there a published game that has the camera behaviour you want? Which one?

    Have you seen this tutorial? Is it close to what you want to make?

     
  13. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    1) Camera should ALWAYS be behind player no matter its' rotation.
    2) Movement / rotation should be smooth.
    3) Zooming in / out should also be smooth.
    4) If you hold down the left mouse button then hold the turn key, it will turn character but not turn the camera until the mouse button is let go. When letting go of the mouse button, the camera smoothly returns to behind it's main position / rotation which is behind the player.
    5) if NOT holding mouse button down and turning, camera will turn WITH player smoothly.
    6) Camera should NOT be able to go under the landscape when zooming out then holding down left mouse button then dragging the mouse up / down.

    I find that the 3rdPersonAimMode Framing Transposer works correctly for the most part except number 1 above and number 6 above.

    Does that explain it clearly?
     
    Last edited: May 21, 2022
  14. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    Can someone please help? :(
     
  15. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,730
    I am afk for a few days. If someone else wants to help they are welcome. Otherwise, I will answer properly when I get back.
     
  16. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    Can someone else help? Gregory is AFK for a few days.
     
  17. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
  18. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
  19. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,730
    Yes, that's more clear.

    The problem with the FramingTransposer solution is that it has no knowledge of the player rotation. Camera rotation is controlled by the user input alone. You would have to write custom code to sync up the rotation to the player. We don't have sample code for this specific thing.

    Your point #6 should work if you set up the CMCollider properly on the vcam.

    Possibly a better starting point for you is the AimingRig sample scene. It uses a 3rdPersonFollow behaviour on the vcam. The mouse controls the character directly (via the CharacterMovementNoCamera.cs script). You would have to modify it so that when the mouse button is pressed, it horizontally rotates the GunOrigin child object instead of the the character itself. You would also need to add code to bring the GunOrigin object's local rotation to 0 for recentering.
     
  20. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    @Gregoryl

    can you show an example of bringing the GunOrigin object's local rotation to 0 for recentering ?

    Much thanks and total appreciation!
     
  21. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,730
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class RecenterMe : MonoBehaviour
    4. {
    5.     public float RecenterTime = 1;
    6.     public bool RecenterNow;
    7.  
    8.     void Update()
    9.     {
    10.         if (RecenterNow)
    11.         {
    12.             var targetRotation = Quaternion.identity;
    13.             float t = Cinemachine.Utility.Damper.Damp(1, RecenterTime, Time.deltaTime);
    14.             var q = Quaternion.Slerp(transform.localRotation, targetRotation, t);
    15.             transform.localRotation = q;
    16.  
    17.             // Turn off when close enough to target
    18.             if (Quaternion.Angle(q, targetRotation) < 0.01f)
    19.                 RecenterNow = false;
    20.         }
    21.     }
    22. }