Search Unity

Cinemachine Impulse Shake wont return to original position after shaking

Discussion in 'Cinemachine' started by scozirge, Apr 15, 2022.

  1. scozirge

    scozirge

    Joined:
    Feb 24, 2015
    Posts:
    80
    I use Cinemachine Impulse Listener and Cinemachine Impulse Source to generate a shaking effect but it won't return to its original position after shaking. How do you make the camera back to its original position?

    This is my setting.

    upload_2022-4-16_5-50-45.png
    upload_2022-4-16_5-51-3.png
    upload_2022-4-16_5-50-24.png
    upload_2022-4-16_5-52-10.png
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    It's normal that in the absence of logic that tells the camera where to be, the impulse will shake an object randomly and just leave it where it ends up (think of what happens to real-life things in an earthquake).

    Because you have "Do Nothing" in Aim and Body, there is nothing that tells the camera where it "ought" to be. Try replacing CInemachineImpulseListener with CinemachineIndependentImpulseListener, which has logic to return the object to its unshaken position.
     
    SassyPantsy and scozirge like this.
  3. scozirge

    scozirge

    Joined:
    Feb 24, 2015
    Posts:
    80
    Thank you, I got it!
     
  4. Prosto_Lyubo

    Prosto_Lyubo

    Joined:
    Aug 15, 2013
    Posts:
    18
    I'm using CinemachineIndependentImpulseListener and my object (UI) does not return into position (0,0,0) after multiple shakes are applied in a short period of time. Can you make sure the object returns to its original position after shaing? Thanks!
     
  5. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    It is supposed to return to its original position. Can you send me a scene that reproduces the problem?
     
  6. SassyPantsy

    SassyPantsy

    Joined:
    May 17, 2020
    Posts:
    142
    I'm having the same problem. cinmemachineindependentimpulse listener with both a follow and look at target that doesn't reset.
     
  7. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    It is supposed to return to its original position. Can you send me a scene that reproduces the problem?
     
  8. TaylorCaudle

    TaylorCaudle

    Joined:
    Feb 8, 2018
    Posts:
    158
    also getting this error, is it possible the "starting position" is being reset between shakes?
     
  9. CortiWins

    CortiWins

    Joined:
    Sep 24, 2018
    Posts:
    150
    I had the same problem, the object not returning to the base position. I had a CinemachineImpulseListener that was meant to apply the recoil of gunshots to the first person camera.

    The problem is, that the CinemachineImpulseListener does not correctly work in objects that are part of a hierachy where the objects world space is changed by other sources, in my case, the players movement.

    I solved the problem by creating a copy of CinemachineImpulseListener that does only change the transform.localPosition and transform.localRotation of the gameobject. Not sure was "m_UseLocalSpace" was supposed to do in the original script.

    Code (CSharp):
    1. using UnityEngine;
    2. namespace CortiWins
    3. {
    4.     /// <summary>
    5.     ///  Copied from: Cinemachine.CinemachineImpulseListener<br/>
    6.     ///  [projectfolder]\Library\PackageCache\com.unity.cinemachine@2.9.7\Runtime\Impulse\CinemachineImpulseListener.cs<br/>
    7.     ///  Replaced worldspace position/rotation with local position/rotation.
    8.     /// </summary>
    9.     public sealed class CustomImpulseListener : MonoBehaviour
    10.     {
    11.         private Vector3 impulsePosLastFrame;
    12.         private Quaternion impulseRotLastFrame;
    13.  
    14.         /// <summary>
    15.         /// Impulse events on channels not included in the mask will be ignored.
    16.         /// </summary>
    17.         [Tooltip("Impulse events on channels not included in the mask will be ignored.")]
    18.         [Cinemachine.CinemachineImpulseChannelProperty]
    19.         public int m_ChannelMask;
    20.  
    21.         /// <summary>
    22.         /// Gain to apply to the Impulse signal.
    23.         /// </summary>
    24.         [Tooltip("Gain to apply to the Impulse signal.  1 is normal strength.  Setting this to 0 completely mutes the signal.")]
    25.         public float m_Gain;
    26.  
    27.         /// <summary>
    28.         /// Enable this to perform distance calculation in 2D (ignore Z).
    29.         /// </summary>
    30.         [Tooltip("Enable this to perform distance calculation in 2D (ignore Z)")]
    31.         public bool m_Use2DDistance;
    32.  
    33.         /// <summary>
    34.         /// Enable this to process all impulse signals in camera space.
    35.         /// </summary>
    36.         [Tooltip("Enable this to process all impulse signals in camera space")]
    37.         public bool m_UseLocalSpace;
    38.  
    39.         /// <summary>
    40.         /// This controls the secondary reaction of the listener to the incoming impulse.
    41.         /// The impulse might be for example a sharp shock, and the secondary reaction could
    42.         /// be a vibration whose amplitude and duration is controlled by the size of the
    43.         /// original impulse.  This allows different listeners to respond in different ways
    44.         /// to the same impulse signal.
    45.         /// </summary>
    46.         [Tooltip("This controls the secondary reaction of the listener to the incoming impulse.  "
    47.             + "The impulse might be for example a sharp shock, and the secondary reaction could "
    48.             + "be a vibration whose amplitude and duration is controlled by the size of the "
    49.             + "original impulse.  This allows different listeners to respond in different ways "
    50.             + "to the same impulse signal.")]
    51.         public Cinemachine.CinemachineImpulseListener.ImpulseReaction m_ReactionSettings;
    52.  
    53.         private void Reset()
    54.         {
    55.             this.m_ChannelMask = 1;
    56.             this.m_Gain = 1;
    57.             this.m_Use2DDistance = false;
    58.             this.m_UseLocalSpace = true;
    59.             this.m_ReactionSettings = new Cinemachine.CinemachineImpulseListener.ImpulseReaction
    60.             {
    61.                 m_AmplitudeGain = 1,
    62.                 m_FrequencyGain = 1,
    63.                 m_Duration = 1f
    64.             };
    65.         }
    66.  
    67.         private void OnEnable()
    68.         {
    69.             this.impulsePosLastFrame = Vector3.zero;
    70.             this.impulseRotLastFrame = Quaternion.identity;
    71.         }
    72.  
    73.         private void Update()
    74.         {
    75.             // Unapply previous shake
    76.             this.transform.localPosition -= this.impulsePosLastFrame;
    77.             this.transform.localRotation = this.transform.localRotation * Quaternion.Inverse(this.impulseRotLastFrame);
    78.         }
    79.  
    80.         // We do this in LateUpdate specifically to support attaching this script to the
    81.         // Camera with the CinemachineBrain.  Script execution order is after the brain.
    82.         private void LateUpdate()
    83.         {
    84.             // Apply the shake
    85.             var haveImpulse = Cinemachine.CinemachineImpulseManager.Instance.GetImpulseAt(
    86.                 this.transform.position,
    87.                 this.m_Use2DDistance,
    88.                 this.m_ChannelMask,
    89.                 out this.impulsePosLastFrame,
    90.                 out this.impulseRotLastFrame);
    91.  
    92.             var haveReaction = this.m_ReactionSettings.GetReaction(
    93.                 Time.deltaTime,
    94.                 this.impulsePosLastFrame,
    95.                 out var reactionPos,
    96.                 out var reactionRot);
    97.  
    98.             if (haveImpulse)
    99.             {
    100.                 this.impulseRotLastFrame = Quaternion.SlerpUnclamped(
    101.                     Quaternion.identity,
    102.                     this.impulseRotLastFrame,
    103.                     this.m_Gain);
    104.                 this.impulsePosLastFrame *= this.m_Gain;
    105.             }
    106.  
    107.             if (haveReaction)
    108.             {
    109.                 this.impulsePosLastFrame += reactionPos;
    110.                 this.impulseRotLastFrame *= reactionRot;
    111.             }
    112.  
    113.             if (haveImpulse || haveReaction)
    114.             {
    115.                 if (this.m_UseLocalSpace)
    116.                 {
    117.                     this.impulsePosLastFrame = this.transform.localRotation * this.impulsePosLastFrame;
    118.                 }
    119.  
    120.                 this.transform.localPosition += this.impulsePosLastFrame;
    121.                 this.transform.localRotation = this.transform.localRotation * this.impulseRotLastFrame;
    122.             }
    123.         }
    124.     }
    125. }
    126.  
     
    TaylorCaudle likes this.
  10. TaylorCaudle

    TaylorCaudle

    Joined:
    Feb 8, 2018
    Posts:
    158

    Exact same problem, you're a life saver. Wanted to avoid this but works great!