Search Unity

Adding recoil to a third person camera but cannot slow it on the way back down

Discussion in 'Scripting' started by mudflaps, Sep 18, 2020.

  1. mudflaps

    mudflaps

    Joined:
    Mar 16, 2017
    Posts:
    8
    Hi - I have added recoil into my game as below, it moves up and down at the same speed, what I am looking to do is manipulate it so that on the way down it takes twice as long to reset the camera to its origonal position. However whenever I try manipulate it, it goes twice as far instead of taking twice as long.

    The issue is that the camera is rotating per tick by a value, so if you try double or half the value the camera moves further / shorter. Is there a way of manipulating this method of recoil on the (third person) camera so it takes twice as long to reset?

    Code (CSharp):
    1.     public static void rotateThirdPersonCamera()
    2.     {
    3.         // reference the game obejcts to manipulate
    4.         GameObject cameraRotator = GameObject.Find("CameraRotator");
    5.         GameObject player = GameObject.Find("mainCharacter");
    6.        
    7.             float h = _recoilX + _mouseSensitivity * Input.GetAxis("Mouse X");
    8.             player.transform.Rotate(0, h, 0);
    9.             float v = _mouseSensitivity * -Input.GetAxis("Mouse Y") - _recoilY;
    10.             cameraRotator.transform.Rotate(new Vector3(1, 0, 0), v);
    11.  
    12.             // control reset direction of weapon recoil
    13.             if ((_recoilState == RecoilState.Resetting))
    14.             {
    15.                 player.transform.Rotate(0, h - _recoilXReset, 0);
    16.                 cameraRotator.transform.Rotate(new Vector3(1, 0, 0), v + _recoilYReset);
    17.             }
    18.  
    19.             if (cameraRotator.transform.rotation.eulerAngles.x < 327.0f && cameraRotator.transform.rotation.eulerAngles.x > 270.0f)
    20.             {
    21.                 cameraRotator.transform.rotation = Quaternion.Euler(
    22.                     327.0f,
    23.                     cameraRotator.transform.rotation.eulerAngles.y,
    24.                     cameraRotator.transform.rotation.eulerAngles.z);
    25.  
    26.             }
    27.             if (cameraRotator.transform.rotation.eulerAngles.x > 30.0f && cameraRotator.transform.rotation.eulerAngles.x < 270.0f)
    28.             {
    29.                 cameraRotator.transform.rotation = Quaternion.Euler(
    30.                     30.0f,
    31.                     cameraRotator.transform.rotation.eulerAngles.y,
    32.                     cameraRotator.transform.rotation.eulerAngles.z);
    33.             }
    34.             Camera.main.transform.LookAt(cameraRotator.transform.position);
    35.         }
    36.  
    37.         _smoothRecoil();
    38.  
    39.     }
    Code (CSharp):
    1.     private static void _smoothRecoil()
    2.     {
    3.  
    4.         // smoothing for recoil
    5.         if (_recoilState == RecoilState.Moving)
    6.         {
    7.             _recoilX -= _recoilSmoothing * Time.deltaTime;
    8.             _recoilY -= _recoilSmoothing * Time.deltaTime;
    9.         }
    10.         else if (_recoilState == RecoilState.Resetting)
    11.         {
    12.             _recoilXReset -= _recoilSmoothing * Time.deltaTime;
    13.             _recoilYReset -= _recoilSmoothing * Time.deltaTime;
    14.         }
    15.  
    16.         // prevent negative recoil
    17.         if (_recoilX <= 0) _recoilX = 0;
    18.         if (_recoilY <= 0) _recoilY = 0;
    19.         if (_recoilXReset <= 0) _recoilXReset = 0;
    20.         if (_recoilYReset <= 0) _recoilYReset = 0;
    21.  
    22.         // configure for resetting animation
    23.         if ((_recoilX == 0 && _recoilY == 0) && (_recoilXReset > 0 || _recoilYReset > 0)) _recoilState = RecoilState.Resetting;
    24.  
    25.         // stop the recoil if everything = 0
    26.         if (_recoilX == 0 && _recoilY == 0 && _recoilXReset == 0 && _recoilYReset == 0) _recoilState = RecoilState.Stopped;
    27.  
    28.     }
    29.  
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    You may want to consider making an AnimationCurve property in your script and putting the recoil curve there, so you can make it look "real," the way it might if you were really recoiling.

    Code (csharp):
    1. public AnimationCurve RecoilUpwards;
    Then you can set up something like this and drive it through your code using the
    .Evaluate()
    method on the curve. It makes it trivial to tweak the curve until it looks awesome sauce as you're firing.

    Screen Shot 2020-09-18 at 7.07.28 AM.png
     
    mudflaps likes this.
  3. mudflaps

    mudflaps

    Joined:
    Mar 16, 2017
    Posts:
    8
    I've not seen that before, thank you! Does this generate the math into something where i can add the value of the curve to:

    Code (CSharp):
    1. float h = _recoilX + _mouseSensitivity * Input.GetAxis("Mouse X");
    2. player.transform.Rotate(0, h, 0);
    3. float v = _mouseSensitivity * -Input.GetAxis("Mouse Y") - _recoilY;
    4. cameraRotator.transform.Rotate(new Vector3(1, 0, 0), v);
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    You would keep track of a "time" that the recoil is happening, say over 0.25 of a second.

    Code (csharp):
    1. float RecoilTimer;
    The recoil would be in effect when that time goes from 0.0f to 0.25f (or whatever you want it to be)

    You would set the AnimationCurve domain (left to right) to be from 0.0f to 0.25f

    Then you can get the recoil by:

    Code (csharp):
    1. float recoilAmount = RecoilCurve.Evaluate( RecoilTimer);
    You can scale that to however many degrees up you want it to be by tweaking key values in the curve.
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    It is often useful to have an extra Transform in your hierarchy that ONLY handles the recoiling deflection of the gun, to keep you from getting entangled with any other rotations or offsets or whatever. That also lets you make the recoil happen from a very specific point in the gun, which should be near the gun's center of mass to make it look right, not around the zero mark of the player, for instance.
     
    mudflaps likes this.
  6. mudflaps

    mudflaps

    Joined:
    Mar 16, 2017
    Posts:
    8
    Thanks, I think I have implemented most of this now, do you know what part of my script to I insert
    RecoilCurve.Evaluate( RecoilTimer);
    ? I have tried both within the smoothing method and the main rotate method in place of
    _recoilX +


    EDIT: nevermind, i have refactored my whole script and this is much better, thank you!
     
    Last edited: Sep 18, 2020
    Kurt-Dekker likes this.