Search Unity

90* Camera Rotations while following?

Discussion in 'Cinemachine' started by thatscraigz, Jan 1, 2018.

  1. thatscraigz

    thatscraigz

    Joined:
    Mar 27, 2015
    Posts:
    100
    Hello!

    I'm trying to swap out my current camera setup with Cinemachine and am a bit stuck at how to replicate a part of it :)

    In my game, the player can rotate the camera in 90* increments. Right now it's done by just rotating the cameras parent gameobject that's following the character. Simple setup, tons of fringe issues, hence being excited to change swap it out :p

    Reference of what I'm trying to doing In Cinemachine (from my current setup)
    https://i.imgur.com/Z2I0Yn2.gifv

    Is there a way to something similar like this in Cinemachine? I've gotten close by just turning on/off cameras that are positioned in the direction I need, but it gives the transition a swoopy feel cause it just blends between them. I realllly dig the sort of hard rotate that I've got going on in the previous GIF.
    https://i.imgur.com/ScQiWhh.gifv

    Any ideas about this?

    best,

    craigz
     
  2. JakubSmaga

    JakubSmaga

    Joined:
    Aug 5, 2015
    Posts:
    417
    Change blend mode to Linear and speed up blend time.
     
  3. thatscraigz

    thatscraigz

    Joined:
    Mar 27, 2015
    Posts:
    100
    Tried that, unfortunately It seems that its more about the PATH of blend more than the easing/timing.

    For instance, in my current (non cinemachine) rig, when I rotate the camera parent thats following the player it rotates the camera in an arc (green line). Which is what I'm trying to replicate in Cinemachine.

    In Cinemachine, when I blend between camera it travels along the red line, because it's just a raw blend.

    Rather than turning on/off cameras to do the blending, is there a way I override the Y axis rotation of the cinemachine vcam so that it rotates AROUND the player?

     
  4. thatscraigz

    thatscraigz

    Joined:
    Mar 27, 2015
    Posts:
    100
    The only thing I can think to do so far is disable the transposer on my main vcam and just use my own system for following the player?
     
  5. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    @thatscraigz You won't get what you're looking for using blending, since blending will interpolate the position and rotation independently. I can think of a couple of thing that you can try:
    1. Using a standard vcam with Composer and Transposer, implement the rotation by animating the transposer offset in an arc around the local origin (i.e. just apply an incremental rotation to the offset)
    2. Or, you can use a vcam with just a Framing Transposer, and animate the y rotation of the vcam's transform
     
  6. Member123456

    Member123456

    Joined:
    Oct 17, 2012
    Posts:
    237
    If you find a way to solve this I would greatly appreciate your method. I too am trying to solve this exact issue with Cinemachine. I am doing a rotation of the y axis on the vcam, but it still feels as if its directly moving between the 90 degree angles instead of rotating in an arc. The rotation is not instant, so that is not the problem, but I just don't get the same smooth 90 degree orbit.
     
  7. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    @Zionmoose Have you tried what I suggested in my previous post? I'm pretty sure that will work.
     
  8. Member123456

    Member123456

    Joined:
    Oct 17, 2012
    Posts:
    237
    @Gregoryl I have tried both method. Neither of them produce a suitable result. The largest problem I have is I want to go with option 2, because the Framing Transposer is my preferred option for tracking my player. Using a look target is not an option since my movement is based on the direction the camera faces, and even slight changes in the look direction make movement awkward. However, simply modifying the y rotation of the vcam transform while have the Framing Transposer soft zone set to my preferred value cause jerking lag. The only way to remove the jerky lag while it reframes the character is to use a soft zone of .001, which means I get no smoothed camera lag while it follows the player. You can see the example below.

    With virtually no soft zone, the rotation movement is pretty good. But the camera follow doesnt have that smooth lagging feeling, so its not ideal.
    no-soft-zone.gif


    Here we have soft zone set to the desired level, but the rotation gets all screwy because of it trying to track the player while rotating. I also tried setting the soft zone programmatically, so when the rotation was happening there was no soft zone, and then resetting it to the desired value after the rotation completes. This however also does not look right because if you are moving while the rotation is happening, you get 2 different camera follow behaviors which looks weird.
    with-soft-zone.gif
     
  9. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    @Zionmoose Thanks for the write-up and the vids. Looks like FramingTransposer isn't the way to go in your situation.

    My first thought is that you need to relax your constraint about not having a LookAt target. I would suggest that you base your character movement on something other than the camera direction. What if the player moves during a transition? The direction will be weird and perhaps not what you want. Decoupling the movement direction from the camera direction will save a lot of headaches, in my opinion, and open up more camera options.

    Try using the OrbitalTransposer, with no axis name in the axis control (so the user can't mess with the heading). You can animate the bias or the offset to implement the rotation. The nice thing about this approach is that it plays better with the damping.
     
  10. Member123456

    Member123456

    Joined:
    Oct 17, 2012
    Posts:
    237
    @Gregoryl Thanks. I will take your advice into consideration and play around a bit. I did also try the orbital transposer while having a lookat target, and that seemed to work quite well, baring the issue I have with movement being based on the camera look direction. I will continue to experiment and see what results I can come up with.
     
  11. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    @Zionmoose @thatscraigz So I tried it myself, just for fun, and I think I got something close to what you're looking for, as far as I can tell.

    Set up the vcam with an OrbitalTransposer in the Body, and DoNothing in the aim:

    upload_2018-1-10_11-50-13.png

    Adjust its x rotation so that it's looking down on your character, like this:

    upload_2018-1-10_11-51-4.png

    upload_2018-1-10_11-51-28.png

    Next, add a custom script to the vcam, to do the rotations. Mine also does the player movement (for testing) but the main point is that the player movement must be based on the desired camera aim, not the current one. That way, you get the right results during the transitions.

    upload_2018-1-10_11-54-26.png

    Code (CSharp):
    1. using Cinemachine;
    2. using UnityEngine;
    3.  
    4. public class Turn90 : MonoBehaviour
    5. {
    6.     [Range(0, 5)]
    7.     public float m_Damping = 0.5f;
    8.  
    9.     public float m_TargetBias = 0;
    10.     CinemachineOrbitalTransposer mOrbital;
    11.  
    12.     [Space]
    13.     public Transform m_Player;
    14.     Vector3 m_PlayerTargetPos;
    15.  
    16.     [Range(1, 10)]
    17.     public float m_PlayerStepSize = 5;
    18.  
    19.     void Start()
    20.     {
    21.         var vcam = GetComponent<CinemachineVirtualCamera>();
    22.         if (vcam != null)
    23.             mOrbital = vcam.GetCinemachineComponent<CinemachineOrbitalTransposer>();
    24.         if (m_Player != null)
    25.             m_PlayerTargetPos = m_Player.position;
    26.     }
    27.  
    28.     void Update()
    29.     {
    30.         if (Input.GetKeyDown(KeyCode.LeftArrow))
    31.             m_TargetBias += 90;
    32.         if (Input.GetKeyDown(KeyCode.RightArrow))
    33.             m_TargetBias -= 90;
    34.      
    35.         // Animate the turn
    36.         if (mOrbital != null)
    37.         {
    38.             float bias = mOrbital.m_Heading.m_HeadingBias;
    39.             float delta = m_TargetBias - bias;
    40.             delta = Cinemachine.Utility.Damper.Damp(delta, m_Damping, Time.deltaTime);
    41.             mOrbital.m_Heading.m_HeadingBias += delta;
    42.             Vector3 rot = transform.rotation.eulerAngles;
    43.             rot.y = mOrbital.m_Heading.m_HeadingBias;
    44.             transform.rotation = Quaternion.Euler(rot);
    45.  
    46.             // Normalize
    47.             if (Mathf.Abs(delta) < 0.001f)
    48.                 mOrbital.m_Heading.m_HeadingBias = m_TargetBias = m_TargetBias % 360;
    49.         }
    50.  
    51.         // Move the player
    52.         if (m_Player != null)
    53.         {
    54.             Vector3 step = m_PlayerStepSize * (Quaternion.AngleAxis(m_TargetBias, Vector3.up) * Vector3.forward);
    55.             if (Input.GetKeyDown(KeyCode.UpArrow))
    56.             {
    57.                 m_PlayerTargetPos += step;
    58.                 m_Player.rotation = Quaternion.AngleAxis(m_TargetBias, Vector3.up);
    59.             }
    60.             if (Input.GetKeyDown(KeyCode.DownArrow))
    61.             {
    62.                 m_PlayerTargetPos -= step;
    63.                 m_Player.rotation = Quaternion.AngleAxis(m_TargetBias, Vector3.up);
    64.             }
    65.             Vector3 delta = m_PlayerTargetPos - m_Player.position;
    66.             delta = Cinemachine.Utility.Damper.Damp(delta, m_Damping, Time.deltaTime);
    67.             m_Player.position += delta;
    68.         }
    69.     }
    70. }
    71.  
     
    Last edited: Jan 10, 2018
    anisimovdev, roz007 and thatscraigz like this.
  12. Member123456

    Member123456

    Joined:
    Oct 17, 2012
    Posts:
    237
    @Gregoryl Wow, I have to hand it to you. That example got me exactly where I wanted to be with rotation. The camera follow and smooth 90 degree turns are fantastic now. I may end up changing my players movement to not always be based on the forward direction of the camera, but for now I kept that feature because it feels a bit awkward to be holding the stick in the desired movement direction, but it not translating 1-for-1 on the screen. You method of step movement makes sense for that functionality, but for action based movement I feel x and y stick axis should translate directly to x and y of the screen.

    Here is how it looks now.

    orbital-transposer (2).gif
     
    Adam_Myhill and Gregoryl like this.
  13. thatscraigz

    thatscraigz

    Joined:
    Mar 27, 2015
    Posts:
    100
    Hi @Gregoryl ! I'm so sorry for the crazy late follow up :) was out of town and checking in on mobile.

    Thank you SO much for getting all the notes/custom scripts together and following up about this, I'm excited to check it out and get it integrated :D

    And another big thank you to @Zionmoose for doing lots of the heavy lifting here with testing things out already ;)

    -craigz