Camera recoil system with Clamp and Player Input

  • The camera will never exceed -90 or go under 90 in its vertical axis, standard in FPS
  • During the recoil duration the vertical mouse input is still take accounted for but recoil is affecting the camera.
  • The recovery moves the camera downward.
  • Both recoil and recovery which moves the camera outside of the player input can be mitigated by pushing or pulling the mouse against the forced rotation.

What steps would I need to implement this? Ideally I would like to use coroutines for the recoil system to benefit from using animation curves unique to each gun. Also because I need to modify the time it takes for the gun to return to its original position based on the firiing rate.

The camera function, as you can see I’m adding and clamping the final recoil modifier within the script. However it doesn’t work well when the player moves their mouse during this time.

    void CameraLook()
    {
        _rotationY += _settings.MouseSensitivity * Input.GetAxis("Mouse X");
        _rotationX -= _settings.MouseSensitivity * Input.GetAxis("Mouse Y");

        var finalEuler = new Vector3(_rotationX, _rotationY, 0);
        finalEuler.x = Mathf.Clamp(finalEuler.x + (_settings.DisableModifers ? 0 : _feedback.GetRecoilModifer()), -_settings.MaxLookY, _settings.MaxLookY);
        transform.eulerAngles = finalEuler;

    }

Heres the recoil and recovery coroutine, do not know how to implement animation curve into this yet.

    private IEnumerator Rotate(Transform gunTransform, Vector3 targetEuler, float duration) 
    {
        float time = 0;
        var start = gunTransform.localRotation;
        var target = Quaternion.Euler(targetEuler);
        while (time < duration)
        {
            _targetRot = Quaternion.Lerp(start, target, time / duration);
            time += Time.deltaTime / duration;
            yield return null;
        }
        _targetRot = target;
    }

Recoil should be a layer on top of the rotation calculated by mouse movement. Ergo, you should have a final rotation value (stored on its own as a quaternion, not using the actual rotation of a transform). Then you calculate a rotation for recoil, combine the two, and apply that to the transform.

Usual advice is to avoid eulers as you’ll run into the usual issues with them. Quaterions are the way.

Mind you I believe 100% of this is built into Cinemachine. Both the mouse-look and recoil.

1 Like
    void CameraLook()
    {
        _rotationY += _settings.MouseSensitivity * Input.GetAxis("Mouse X");
        _rotationX -= _settings.MouseSensitivity * Input.GetAxis("Mouse Y");
        var finalEuler = new Vector3(_rotationX, _rotationY, 0);
        finalEuler.x = Mathf.Clamp(finalEuler.x, -_settings.MaxLookY, _settings.MaxLookY);
        finalEuler.x+=recoil;       // set recoil to something like -5 when the player shoots
        recoil*=0.95f; // slowly return to zero
        transform.eulerAngles = finalEuler;
    }

The number of which it returns to 0 is modifiable right? Also this doesnt seem to factor in clamping of the recoil, lets say that the camera is already at the clamped look, the recoil would make it bypass it.

Yep, you can put any value in recoil. And you can place the recoil before the clamping if you feel it’s important.

So far so good. How would you guys approach having some kind of resistance with the recoil? Detect the input of the player and if it’s opposite of where the recoil is going divide the recoilmodifier in half?

You can adjust the recoil at the shooting stage with something like:

recoil=-5+Input.GetAxis("Mouse Y");