Search Unity

Orbital Transposer - Using one binding mode while accessing parameters of another

Discussion in 'Cinemachine' started by caiqueassis, Oct 30, 2018.

  1. caiqueassis

    caiqueassis

    Joined:
    Oct 13, 2018
    Posts:
    8
    Hello!

    I have been experimenting with Cinemachine for the past few days, trying to make a Third Person camera setup. I got one that works quite well for my purposes so far. Here are the settings:

    Settings.png

    I'm currently using the "Simple Follow With World Up" binding mode of the Orbital Transposer, which works wonderfully for my needs. I also implemented a little code to be able to rotate the "X Axis" by pressing certain buttons.

    My problem, however, is that with the "Simple Follow With World Up" binding mode, I don't have access to the "Recenter To Target Heading" setting, and I can't "recenter" the camera with a button press, for instance. I even tried accessing it through code, and while I could set values to it, it wouldn't make any effect if the binding mode was still "Simple Follow With World Up".

    I tried using the "Lock To Target With World Up" binding mode, but it just doesn't work the way I want to. The "Simple Follow With World Up" is already perfect for what I need. I just need to be able to "recenter" the camera behind the Follow Target with the press of a button.

    Is there any possible way of doing that, while still using the "Simple Follow With World Up" binding method? If there isn't, what would be my options to maintain the behaviour of the "Simple Follow With World Up" binding mode, while having a way to "recenter" the camera?

    Thanks in advance.
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    The concept of recentering doesn't exist in SimpleFollow because that binding mode is in camera space, in other words it's always centered, because in this mode centered means that camera forward points in the same direction as camera forward.

    It's possible to do what you ask with a CM extension, but it's a little tricky because you have to suppress the Aim damping that would normally occur when the vcam is moved. Here is a sample extension that does the job. Just drop it in your project and add it to the vcam using the Extensions dropdown. The extension assumes that your vcam has a Composer in the Aim. If it has something else, just modify the extension as necessary.

    Code (CSharp):
    1. using UnityEngine;
    2. using Cinemachine;
    3. using Cinemachine.Utility;
    4.  
    5. public class Recenter : CinemachineExtension
    6. {
    7.     public bool recenter;
    8.     public float recenterTime = 1;
    9.     [Range(1, 4)]
    10.     public float gamma = 1.5f;
    11.     float recenterStartTime;
    12.  
    13.     class VcamExtraState
    14.     {
    15.         // Change this to the appropriate thing for your vcam
    16.         public CinemachineComposer composer;
    17.         public float savedAimDamping;
    18.     }
    19.  
    20.     private void OnValidate()
    21.     {
    22.         recenterTime = Mathf.Max(0, recenterTime);
    23.         gamma = Mathf.Max(0, gamma);
    24.     }
    25.  
    26.     protected override void PostPipelineStageCallback(
    27.         CinemachineVirtualCameraBase vcam,
    28.         CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
    29.     {
    30.         if (recenter && stage == CinemachineCore.Stage.Body && vcam.Follow != null)
    31.         {
    32.             // This is needed to suppress the Aim damping.  Modify as necessary
    33.             VcamExtraState extra = GetExtraState<VcamExtraState>(vcam);
    34.             if (extra.composer == null)
    35.             {
    36.                 var vcam2 = vcam as CinemachineVirtualCamera;
    37.                 if (vcam2 != null)
    38.                     extra.composer = vcam2.GetCinemachineComponent<CinemachineComposer>();
    39.             }
    40.  
    41.             var up = state.ReferenceUp;
    42.             var center = vcam.Follow.position;
    43.             var start = state.RawPosition - center;
    44.             float angle = UnityVectorExtensions.SignedAngle(
    45.                 start.ProjectOntoPlane(up), -vcam.Follow.forward.ProjectOntoPlane(up), up);
    46.  
    47.             if (recenterStartTime == 0)
    48.                 recenterStartTime = Time.time;
    49.             float t = recenterTime == 0 ? 1 : (Time.time - recenterStartTime) / recenterTime;
    50.             angle = Mathf.Lerp(0, angle, Mathf.Pow(t, gamma));
    51.  
    52.             var newPos = Quaternion.AngleAxis(angle, up) * start;
    53.             state.RawPosition = center + newPos;
    54.  
    55.             // Kill the Aim damping
    56.             if (extra.composer != null && extra.composer.m_HorizontalDamping != 0)
    57.             {
    58.                 extra.savedAimDamping = extra.composer.m_HorizontalDamping;
    59.                 extra.composer.m_HorizontalDamping = 0;
    60.             }
    61.  
    62.             if (t >= 1)
    63.             {
    64.                 recenter = false;
    65.                 recenterStartTime = 0;
    66.  
    67.                 // Restore the Aim damping
    68.                 if (extra.composer != null)
    69.                     extra.composer.m_HorizontalDamping = extra.savedAimDamping;
    70.             }
    71.         }
    72.     }
    73. }
    74.  
     
    caiqueassis likes this.
  3. caiqueassis

    caiqueassis

    Joined:
    Oct 13, 2018
    Posts:
    8
    This worked wonderfully. It was just what I needed. You sir, saved my life. Thanks a lot!
     
    Gregoryl likes this.
  4. Pronotron

    Pronotron

    Joined:
    Aug 27, 2018
    Posts:
    7
    I'm facing a similar issue. Simple Follow With World Up works well but it doesn't recenter (180°) when target going backward at initial position. And I can't get sure is it possible to set the recentering speed for some special situations like sudden player movement?

    Lock The Target's
    recenter option works well with first issue but can't set any customized recentering options based on target's velocity. And I can't get sure binding custom values from outside will not create jitter.

    Is your recommendation for such situations to write a special extension?
     
  5. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    I'm not sure exactly what you're asking. Can you describe in detail the desired camera movement you are trying to achieve?