Search Unity

Best gun recoil for my setup Quaternion.Slerp?

Discussion in 'Scripting' started by Thrazamund, Jul 2, 2020.

  1. Thrazamund

    Thrazamund

    Joined:
    Apr 14, 2017
    Posts:
    36
    Hello, I want to add recoil to my gun that rotates the camera a small amount upwards. I want the player to have to pull down the mouse to keep the gun on target. My setup has a lookRoot object childed to the playerRoot object and the camera is childed to that. The lookRoot controls the up and down of the camera on the x rotation and the playerRoot the side to side on the y rotation. I've heard it's good to separate these rotations to avoid issues? I've managed to make a primitive version of the recoil by adding it it on my mouse look script. If I tried to put it on a separate recoil script it seems my mouse look would be happening at the same time and override the new rotation I'm setting it to? The code currently works by just subtracting 10 on the x and applying it to the lookRoot upon firing but I want to use something like Quaternion.Slerp to give the camera a jolt up and not just teleport it to a new rotation so it feels better.

    Code (CSharp):
    1.     private void LookAround()
    2.     {
    3.         currentMouseLook = new Vector2(Input.GetAxis("Mouse Y"), Input.GetAxis("Mouse X"));
    4.  
    5.        lookAngles.x += currentMouseLook.x * sensitivity * (invert ? 1f : -1f);
    6.        lookAngles.y += currentMouseLook.y * sensitivity;
    7.        lookAngles.x = Mathf.Clamp(lookAngles.x, defaultLookLimits.x, defaultLookLimits.y);
    8.         if (addRecoil)
    9.         {
    10.             Vector2 recoilAngles = new Vector2(lookAngles.x - 10, lookAngles.y);
    11.             lookAngles = recoilAngles;
    12.             lookRoot.localRotation = Quaternion.Euler(lookAngles.x, 0f, 0f);
    13.             playerRoot.localRotation = Quaternion.Euler(0f, lookAngles.y, 0f);
    14.  
    15.             addRecoil = false;
    16.         }
    17.         else
    18.         {
    19.             lookRoot.localRotation = Quaternion.Euler(lookAngles.x, 0f, 0f);
    20.             playerRoot.localRotation = Quaternion.Euler(0f, lookAngles.y, 0f);
    21.         }
    22.     }
    I tried many things including turning look angles into a Euler and then making another Euler with look angles values but subtracting on the x rotation and then using Quaternion.Slerp between the two but they appear to do nothing. Eventually I'd also like to have the recoil rotate to the left or right a bit as well. Anyone who could explain to me how to do this or a better way of doing this would be hugely helpful. Thanks!
     
    Last edited: Jul 2, 2020
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,749
    Here is one approach:

    You presentlky have an input that the player uses to move the turret. Every frame you're reading that input and applying it to your controls.

    Now I propose that when you fire the gun, begin a timer that iterates the length of how long the recoil should go (let's say 0.1 seconds).

    In between gathering the user input and applying it to the gun, check that timer.

    If that timer is ever greater than zero, use that to look up how much to deflect the player controls (i.e., add to them).

    One cool way is to make an AnimationCurve field for each axis:

    Code (csharp):
    1. public AnimationCurve RecoilHorizontal;
    2. public AnimationCurve RecoilVertical;
    You would use the timer to look up how much to "bend" the inputs for X and Y.

    Code (csharp):
    1. Vector2 NormalUserInput = .... however you get that
    2.  
    3. if (RecoilingTimer > 0)
    4. {
    5.   NormalUserInput.x += RecoilHorizontal.Evaluate( RecoilingTimer);
    6.   NormalUserInput.y += RecoilVertical.Evaluate( RecoilingTimer);
    7. }
    8.  
    9. // now apply the NormalUserInput to left/right up/down as normal.
    And of course, every frame count that timer back down to zero by subtracting Time.deltaTime.

    You can scale and shape the recoil curves however you want to give it the jerk-up look you want. Each one is just a single-axis lookup curve.

    Anyway, I think that's how I would do it. That way you can also make a ScriptableObject that defines those two curves and create a bunch of preset types of recoils for different guns.
     
  3. Thrazamund

    Thrazamund

    Joined:
    Apr 14, 2017
    Posts:
    36
    That looks great! I'll give it a shot. I've never used animation curves and it seems like a good way to fine tune the movement of an object.