Search Unity

  1. Check out the Unite LA keynote for updates on the Visual Effect Editor, the FPS Sample, ECS, Unity for Film and more! Watch it now!
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  4. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  5. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

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:
    2
    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:
    1,731
    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:
    2
    This worked wonderfully. It was just what I needed. You sir, saved my life. Thanks a lot!
     
    Gregoryl likes this.