public class CameraController : MonoBehaviour
{
private Camera _camera;
private float _defaultFov;
private float _currentFov;
private float _currentTilt;
[SerializeField] private float _fovChangeOnRun = 10f;
[SerializeField] private float _fovLerpSpeed = 2f;
[SerializeField] private float _fovLerpReturn = 10f;
[SerializeField] private float _tiltLerpSpeed = 4f;
[SerializeField] private float _tiltLerpReturn = 10f;
[SerializeField] private float _tiltAmount = 1f;
[SerializeField] float _bobSpeed = 14f;
[SerializeField] float _bobAmount = 0.02f;
private Vector2 _rawLookInput;
private Vector2 _lookInputReady;
[SerializeField] private float _horizSensitity;
[SerializeField] private float _verticalSensitity;
[SerializeField] private float _sensitivityMultiplierOnForwardRun = 0.6f;
private float _xRotation;
private float _yRotation;
private float _maxVertLookDegree = 80;
private void Start()
{
_camera = GetComponent();
_yRotation = transform.localRotation.eulerAngles.y;
_defaultFov = _camera.fieldOfView;
_currentFov = _camera.fieldOfView;
Cursor.lockState = CursorLockMode.Locked;
}
private void Update()
{
var inputManager = FirstPersonCharacter.Instance.InputManager;
_rawLookInput = inputManager.LookInput;
_rawLookInput.x *= _horizSensitity;
_rawLookInput.y *= _verticalSensitity;
_lookInputReady = _rawLookInput;
// Vertical look
_xRotation -= _lookInputReady.y;
_xRotation = Mathf.Clamp(_xRotation, -_maxVertLookDegree, _maxVertLookDegree);
// Horizontal look
_yRotation += inputManager.RunForward
? _lookInputReady.x * _sensitivityMultiplierOnForwardRun
: _lookInputReady.x;
float tilt = 0f;
if (inputManager.MoveOblique && inputManager.Running && inputManager.MoveInput.x > 0)
{
tilt = _tiltAmount;
}
else if (inputManager.MoveOblique && inputManager.Running && inputManager.MoveInput.x < 0)
{
tilt = -_tiltAmount;
}
float tiltLerpSpeed = inputManager.MoveSideway
? _tiltLerpSpeed
: _tiltLerpReturn;
_currentTilt = Mathf.Lerp(_currentTilt, tilt, Time.deltaTime * tiltLerpSpeed);
float lerpSpeed = inputManager.RunForward ? _fovLerpSpeed : _fovLerpReturn;
float targetFov = inputManager.RunForward
? _defaultFov - _fovChangeOnRun
: _defaultFov;
_currentFov = Mathf.Lerp(_currentFov, targetFov, Time.deltaTime * lerpSpeed);
_camera.fieldOfView = _currentFov;
UpdateHeadBob(inputManager);
FirstPersonCharacter.Instance.transform.localRotation = Quaternion.Euler(0f, _yRotation, 0f);
transform.localRotation = Quaternion.Euler(_xRotation, _yRotation, _currentTilt);
}
private void UpdateHeadBob(PlayerInputManager inputManager)
{
if (inputManager.MoveInput != Vector2.zero)
{
float waveSlice = Mathf.Sin(Time.time * _bobSpeed);
float totalBob = waveSlice * _bobAmount;
transform.localPosition = new Vector3(
transform.localPosition.x,
FirstPersonCharacter.Instance.CamPositionTr.position.y + totalBob,
transform.localPosition.z);
}
}
}