Search Unity

(CM 2.3.4) Recenter To Target Heading - stuck after first cycle?

Discussion in 'Cinemachine' started by Malaussene, Jun 7, 2019.

  1. Malaussene

    Malaussene

    Joined:
    Feb 14, 2017
    Posts:
    17
    The issue may be mLastAxisInputTime in the m_RecenterToTargetHeading never getting reset on player input.
    This means the Recenter To Target Heading actually "locks" to the target rotation. I also tried to call a CancelRotation(), but had no luck.

    At first I tought it was a problem with the rewired bridge I'm using, but I just tried in an empty project in the Free Look Character example scene with the same results.

    Is there anything I can do to solve this?

    Thank you!
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,728
    Yes, this might be a regression.
    We'll look into it next week.
    Thanks for letting us know!
     
    Malaussene likes this.
  3. Malaussene

    Malaussene

    Joined:
    Feb 14, 2017
    Posts:
    17
    Thank you Gregoryl!

    It may be something also breaking the RecenterNow() and CancelRotation() for the m_RecenterToTargetHeading, if you can look into it. Everything works fine on the m_YAxisRecentering.

    Also, since I'm here I'm asking (let me know if you want me to open another thread with the question): is there any way to unsmooth the recentering velocity, making it linear from start to finish? I noticed it takes almost the double of the time set in Recentering Time to actually complete. Or is there, at least, a way to check if the recentering process is finished?

    Thank you again
     
  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,728
    In fact it's possible to completely customize the way user input drives the axis values. The only thing the FreeLook cares about is axis.Value - you can drive that any way you like. For instance, you can turn off the built-in recentering and make your own script that sends the value back to 0 at the appropriate time.

    As an example, here is a little script that disables the built-in input axis driver and replaces it with one that has a snappier feel to it. Many people prefer this input behaviour. You could add custom recentering functionality to it if you like, although it currently works with the built-in one.
    Code (CSharp):
    1. using UnityEngine;
    2. using Cinemachine;
    3.  
    4. [RequireComponent(typeof(CinemachineFreeLook)), DisallowMultipleComponent]
    5. public class FreeLookAxisDriver : MonoBehaviour
    6. {
    7.     public CinemachineInputAxisDriver xAxis;
    8.     public CinemachineInputAxisDriver yAxis;
    9.  
    10.     private CinemachineFreeLook freeLook;
    11.  
    12.     private void Awake()
    13.     {
    14.         freeLook = GetComponent<CinemachineFreeLook>();
    15.         freeLook.m_XAxis.m_MaxSpeed = freeLook.m_XAxis.m_AccelTime = freeLook.m_XAxis.m_DecelTime = 0;
    16.         freeLook.m_XAxis.m_InputAxisName = string.Empty;
    17.         freeLook.m_YAxis.m_MaxSpeed = freeLook.m_YAxis.m_AccelTime = freeLook.m_YAxis.m_DecelTime = 0;
    18.         freeLook.m_YAxis.m_InputAxisName = string.Empty;
    19.     }
    20.  
    21.     private void OnValidate()
    22.     {
    23.         xAxis.Validate();
    24.         yAxis.Validate();
    25.     }
    26.  
    27.     private void Reset()
    28.     {
    29.         xAxis = new CinemachineInputAxisDriver
    30.         {
    31.             multiplier = -10f,
    32.             accelTime = 0.1f,
    33.             decelTime = 0.1f,
    34.             name = "Mouse X",
    35.         };
    36.         yAxis = new CinemachineInputAxisDriver
    37.         {
    38.             multiplier = 0.1f,
    39.             accelTime = 0.1f,
    40.             decelTime = 0.1f,
    41.             name = "Mouse Y",
    42.         };
    43.     }
    44.  
    45.     private void Update()
    46.     {
    47.         bool changed = yAxis.Update(Time.deltaTime, ref freeLook.m_YAxis);
    48.         changed |= xAxis.Update(Time.deltaTime, ref freeLook.m_XAxis);
    49.         if (changed)
    50.         {
    51.             freeLook.m_RecenterToTargetHeading.CancelRecentering();
    52.             freeLook.m_YAxisRecentering.CancelRecentering();
    53.         }
    54.     }
    55. }
    The recentering time is just approximate, because the deceleration can be quite stretched out to avoid a rough landing. Just set it low enough so that the timing looks right to you. To find out when it's finished, you can look at the axis value, and when it's near enough to the rest value you can call it done.
     
  5. Malaussene

    Malaussene

    Joined:
    Feb 14, 2017
    Posts:
    17
    This works like a charm. Thanks a lot @Gregoryl
     
    Gregoryl likes this.
  6. VojakVolted

    VojakVolted

    Joined:
    Feb 4, 2021
    Posts:
    1
    Hello, I'm sorry, that I'm reopenning this thread, but I have a small issue. I was trying to implement the @Gregoryl code, but I'm using Input Actions, and adding this code to the camera resulted with error about not using Input Actions. I tried to edit the code, but finally I gave up. Is there an option to override the built-in input axis driver code while using Input Actions?
     
  7. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,728
    If I understand, you are using the Input System package. Is that correct?
    If so, you should first upgrade to the latest version of Cinemachine. It provides explicit support for the Input package.
     
  8. Dmc_ex0

    Dmc_ex0

    Joined:
    Feb 19, 2022
    Posts:
    2
    Please tell me how I can:
    1. How to disable the rotation of the Free Look camera on the X axis
    2. The most important thing. How to rotate the camera around a character when a certain button is pressed using the new input system
     
    Last edited: Mar 16, 2023
  9. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,728
    1. You have to set up an input asset with an action that only modifies the Y value of a Vector2. Use that action in the InputProvider instead of the default Player/Look.
    2. You'll have to be more specific about what you want. Rotate the camera at a certain speed while the button is held down? Do a 360 around the player when the button is pressed? Recenter the X axis to some value when the button is pressed?
     
  10. Dmc_ex0

    Dmc_ex0

    Joined:
    Feb 19, 2022
    Posts:
    2
    1. Understood, thank you
    2. I want to do the following: by holding down the right mouse button, you can rotate the camera around the player.
    The only thing I could think of was to disable the "InputProvider" script if the right mouse button is not pressed. But maybe there are more options?
     
  11. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,728
    I think you can set up an input action to do that, and feed it to the input provider. It should set the Vector2 x value to 1 or -1 when a button is pressed.
     
  12. antoinecharton

    antoinecharton

    Unity Technologies

    Joined:
    Jul 22, 2020
    Posts:
    189
    Hello,
    Here is an other suggestion to do it using input processors. Made a little modified version of the example they provided. Not necessarily the only/best way to do it.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.InputSystem;
    3.  
    4. #if UNITY_EDITOR
    5. using UnityEditor;
    6. [InitializeOnLoad]
    7. #endif
    8. public class OutputIfRightClick : InputProcessor<Vector2>
    9. {
    10.  
    11. #if UNITY_EDITOR
    12.     static OutputIfRightClick()
    13.     {
    14.         Initialize();
    15.     }
    16. #endif
    17.  
    18.     [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    19.     static void Initialize()
    20.     {
    21.         InputSystem.RegisterProcessor<OutputIfRightClick>();
    22.     }
    23.  
    24.     public override Vector2 Process(Vector2 value, InputControl control)
    25.     {
    26.         if(Mouse.current.rightButton.isPressed)
    27.             return value;
    28.  
    29.         return Vector2.zero;
    30.     }
    31. }
    You add this code to your project then you add the processor to your action (Right side of the Input map window).
    Screen Shot 2023-03-19 at 7.15.00 PM.png

    Hope this helps :)
     
    Gregoryl likes this.