Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Cinemachine framing transposer fixed on Y axis but moving camera towards mouse position on X and Z

Discussion in 'Cinemachine' started by Zakila, Mar 2, 2021.

  1. Zakila

    Zakila

    Joined:
    Apr 30, 2016
    Posts:
    5
    Hi!

    I've been working on a Cinemachine implementation of a camera I recently made.

    The functionality is pretty simple, where I want the camera to look ahead of the player in the direction of the cursor by moving only on the X and Z axis, while retaining a fixed height (see gif).



    However, my implementation is not entirely correct. In theory, the yellow box should be at the intersection of the blue lines, but this is not correct when moving on the mouse on the Y axis of the screen. I realize that this is because I've locked the camera's Y position which causes a slight skew, but I am unsure what the best way to rectify this is. See the following image, where the cursor is placed at the bottom of the screen but the yellow box is not at the intersection of the thin blue lines.

    upload_2021-3-2_9-51-57.png

    Zoomed in:

    upload_2021-3-2_9-53-3.png


    These are my cinemachine settings:

    upload_2021-3-2_9-54-13.png

    Furthermore, I have attached two scripts to my camera:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class CameraController : MonoBehaviour
    4. {
    5.     [Header("General")]
    6.     [SerializeField]
    7.     float minPlayerScreenPositionX;
    8.  
    9.     [SerializeField]
    10.     float maxPlayerScreenPositionX;
    11.  
    12.     [SerializeField]
    13.     float minPlayerScreenPositionY;
    14.  
    15.     [SerializeField]
    16.     float maxPlayerScreenPositionY;
    17.  
    18.     [Header("References")]
    19.     [SerializeField]
    20.     Cinemachine.CinemachineVirtualCamera virtualCamera;
    21.  
    22.     // Cached variables
    23.     Cinemachine.CinemachineFramingTransposer transposer;
    24.  
    25.     // Start is called before the first frame update
    26.     void Start()
    27.     {
    28.         transposer = virtualCamera.GetCinemachineComponent<Cinemachine.CinemachineFramingTransposer>();
    29.     }
    30.  
    31.     // Update is called once per frame
    32.     void Update()
    33.     {
    34.         updateCameraPositionBasedOnMousePosition();
    35.     }
    36.  
    37.     void updateCameraPositionBasedOnMousePosition()
    38.     {
    39.         Vector3 mousePos = Input.mousePosition;
    40.  
    41.         transposer.m_ScreenX = Mathf.Lerp(minPlayerScreenPositionX, maxPlayerScreenPositionX, Mathf.Clamp((Screen.width - mousePos.x) / Screen.width, 0f, 1f));
    42.         transposer.m_ScreenY = Mathf.Lerp(minPlayerScreenPositionY, maxPlayerScreenPositionY, Mathf.Clamp(mousePos.y / Screen.height, 0f, 1f));
    43.     }
    44. }
    45.  
    and


    Code (CSharp):
    1. using UnityEngine;
    2. using Cinemachine;
    3.  
    4. /// <summary>
    5. /// An add-on module for Cinemachine Virtual Camera that locks the camera's Z co-ordinate
    6. /// </summary>
    7. [ExecuteInEditMode] [SaveDuringPlay] [AddComponentMenu("")] // Hide in menu
    8. public class LockCameraY : CinemachineExtension
    9. {
    10.     float yPosition;
    11.  
    12.     protected override void Awake()
    13.     {
    14.         base.Awake();
    15.         yPosition = transform.position.y;
    16.     }
    17.  
    18.     protected override void PostPipelineStageCallback(CinemachineVirtualCameraBase vcam, CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
    19.     {
    20.         if (stage == CinemachineCore.Stage.Body)
    21.         {
    22.             Vector3 pos = state.RawPosition;
    23.             pos.y = yPosition;
    24.             state.RawPosition = pos;
    25.         }
    26.     }
    27. }
    28.  
    So essentially, I'm changing the screenX and screenY variables based on the position of the mouse, but fixing the camera's Y axis such that the camera's zoom level doesn't get altered.

    Any help would be greatly appreciated!

    P.S. the min- and maxPlayerScreenPosition variables are set to 0.33 and 0.66 respectively.
     

    Attached Files:

  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,233
    The framing transposer gets the desired framing by moving the camera in space - not rotating it. If you lock the camera's Y, then you're preventing the framing transposer from being able to completely do its job.

    Maybe a better approach would be to have the mouse control the position of an invisible game object that you use as a target for the vcam, instead of the player. That way, you can leave the Screen X/Y alone and just displace the invisible target to get the framing you want.
     
  3. Zakila

    Zakila

    Joined:
    Apr 30, 2016
    Posts:
    5
    I understand that the camera is moved in space and not rotated, I was just hoping to be able to configure it to move only on the X and Z and not on the Y, to always maintain the same camera height while still moving around the player.

    Good idea with the invisible game object! I'll try that out.
     
    Gregoryl likes this.