Help Adding Recoil While Maintaing Clamp for Pitch for FPS Camera

    private void UpdateInputs()
    {
        _verticalRot += -LookInput.y * _mouseSensitivity;
        _horizontalRot = LookInput.x * _mouseSensitivity;
    }
    private void UpdateRotation()
    {
        transform.localEulerAngles = new Vector3(Mathf.Clamp(_verticalRot + _currentRecoil, -_maxPitch, _maxPitch), transform.eulerAngles.y + _horizontalRot, 0);
    }

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.

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.

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.

1 Like

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.

2 Likes

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.

2 Likes

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.

 // e.g. ClampAngle(pitch, -89, 89);
private static float ClampAngle(float ang, float min, float max)
{
    var nMin = Mathf.DeltaAngle(ang, min);
    var nMax = Mathf.DeltaAngle(ang, max);

    if (nMin <= 0 && nMax >= 0)
        return ang;
    return Mathf.Abs(nMin) < Mathf.Abs(nMax) ? min : max;
}

Aside from doing the hierarchy separation, you need to Add your recoil, not Assign it.

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.

    private void ApplyRecoil()
    {
        float currentPitch = Vector3.Angle(transform.forward, Vector3.up) - 90;
        minRecoil = -_maxPitch - currentPitch;
        maxRecoil = +_maxPitch - currentPitch;
        float finalizedRecoil = Mathf.Clamp(-_currentRecoil, minRecoil, maxRecoil);
        transform.Rotate(finalizedRecoil * Time.deltaTime, 0, 0);
    }

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.