Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Question Help Adding Recoil While Maintaing Clamp for Pitch for FPS Camera

Discussion in 'Scripting' started by billygamesinc, May 15, 2024.

  1. billygamesinc

    billygamesinc

    Joined:
    Dec 5, 2020
    Posts:
    358
    Code (CSharp):
    1.     private void UpdateInputs()
    2.     {
    3.         _verticalRot += -LookInput.y * _mouseSensitivity;
    4.         _horizontalRot = LookInput.x * _mouseSensitivity;
    5.     }
    6.     private void UpdateRotation()
    7.     {
    8.         transform.localEulerAngles = new Vector3(Mathf.Clamp(_verticalRot + _currentRecoil, -_maxPitch, _maxPitch), transform.eulerAngles.y + _horizontalRot, 0);
    9.     }
    If the recoil factor isn't 0 then the camera pitch will adjust accordingly. If it's 0 it will maintain its current position.
    The issue here is that the recoil is being used to set where the camera should be rather than moving it.

    I.e. _currentRecoil at 4 changes the pitch of the camera upwards but when _currentRecoil is 0 the camera moves back. What it should be doing is leaving the camera where it is.
     
  2. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,936
    It's a good idea to read your own post over at least once after you've posted it.
    There is no _currentRecoil in the code you've posted.
     
  3. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    8,381
    It's in line 8 with the long chain of other variables.

    OP, this is like your 10th post on this particular subject/problem. I think you should know by now that using euler angles is really not the best approach when ti comes to rotations.

    At the very least break your calculations down and debug what each individual one influences - and whether it's working or not. At present there's no way for you to actually determine what isn't working as you're doing it all in one go.
     
    ArachnidAnimal likes this.
  4. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,936
    I find that works out better when working with cameras is to have a camera hierarchy, with each level responsible for one task of the camera.

    Something like:

    Player
    ....Camera Hierarchy
    ........Rotation Control
    ............Recoil
    ................Shake
    ....................Camera Component



    Rotation Control: Control pitch based on user input
    Recoil: Adjust local position/rotation when performing a recoil
    Shake: Adjust local position/rotation when performing a shake

    Using this approach can alleviate the headaches of trying to add-on positions and rotations of the camera, and lets you control each effect separately by simply altering the local positions/rotations of the individual levels.

    When you want to reset the recoil/shake, you simple move the local transform positions/rotations back to Vector3.zero.


    Also, please do not mix-n-match the terms "rotate" with "move/position". These are two separate things. It is incredibly frustrating when users post threads asking for help who confuse these terms, because it makes it harder for people reading your post to know what your talking about.
     
    Last edited: May 15, 2024
    Stardog and spiney199 like this.
  5. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    6,909
    Now if you were to use Cinemachine you could simply use an ImpulseSource and configure the hell out of that recoil effect rather than fighting with this on the code level, with euler angle transformations no less.
     
    Kurt-Dekker and spiney199 like this.
  6. Lekret

    Lekret

    Joined:
    Sep 10, 2020
    Posts:
    369
    You can try this ClampAngle function, it works perfectly, even for euler angles. If it doesn't work that way, then the problem is somewhere else.

    Code (CSharp):
    1.  // e.g. ClampAngle(pitch, -89, 89);
    2. private static float ClampAngle(float ang, float min, float max)
    3. {
    4.     var nMin = Mathf.DeltaAngle(ang, min);
    5.     var nMax = Mathf.DeltaAngle(ang, max);
    6.  
    7.     if (nMin <= 0 && nMax >= 0)
    8.         return ang;
    9.     return Mathf.Abs(nMin) < Mathf.Abs(nMax) ? min : max;
    10. }
     
  7. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,919
    Aside from doing the hierarchy separation, you need to Add your recoil, not Assign it.
     
    Last edited: May 15, 2024
  8. billygamesinc

    billygamesinc

    Joined:
    Dec 5, 2020
    Posts:
    358
    The problem is that when I split the recoil, the recoil can potentially go past the clamp limit. The player cannot extend the camera past a certain angle but the recoil object doesn't know that.
     
  9. billygamesinc

    billygamesinc

    Joined:
    Dec 5, 2020
    Posts:
    358
    Code (CSharp):
    1.     private void ApplyRecoil()
    2.     {
    3.         float currentPitch = Vector3.Angle(transform.forward, Vector3.up) - 90;
    4.         minRecoil = -_maxPitch - currentPitch;
    5.         maxRecoil = +_maxPitch - currentPitch;
    6.         float finalizedRecoil = Mathf.Clamp(-_currentRecoil, minRecoil, maxRecoil);
    7.         transform.Rotate(finalizedRecoil * Time.deltaTime, 0, 0);
    8.     }
    Here is what I came up with. After applying the mouse euler determine how much recoil can be applied based on the currentPitch and how close is it to the limits.