diff --git a/SmoothMouseLook.cs b/SmoothMouseLook.cs new file mode 100644 index 0000000000000000000000000000000000000000..6fd803637215c89a6e42850f5f4754c7f608bbc8 --- /dev/null +++ b/SmoothMouseLook.cs @@ -0,0 +1,86 @@ +using UnityEngine; + + +[AddComponentMenu("Camera/Simple Smooth Mouse Look ")] +public class SmoothMouseLook : MonoBehaviour +{ + Vector2 _mouseAbsolute; + Vector2 _smoothMouse; + + [Tooltip("Limit the possible rotation to these values (Left/Right, Up/Down)")] + public Vector2 clampInDegrees = new Vector2(360, 180); + [Tooltip("Hide/Display Cursor")] + public bool lockCursor; + [Tooltip("Mouse Sensitivity (Left/Right, Up/Down)")] + public Vector2 sensitivity = new Vector2(2, 2); + [Tooltip("Movement Smoothing (Left/Right, Up/Down)")] + public Vector2 smoothing = new Vector2(3, 3); + [Tooltip("Set target direction to the camera's initial orientation.")] + public Vector2 targetDirection; + [Tooltip("Set target direction for the character body to its inital state.")] + public Vector2 targetCharacterDirection; + + // Assign this if there's a parent object controlling motion, such as a Character Controller. + // Yaw rotation will affect this object instead of the camera if set. + [Tooltip("Assign Parent Object if there is one (affects horizontal rotation around Y axis)")] + public GameObject characterBody; + + void Start() + { + // Set target direction to the camera's initial orientation. + targetDirection = transform.localRotation.eulerAngles; + + // Set target direction for the character body to its inital state. + if (characterBody) + targetCharacterDirection = characterBody.transform.localRotation.eulerAngles; + } + + void Update() + { + // Ensure the cursor is always locked when set + if (lockCursor) + { + Cursor.lockState = CursorLockMode.Locked; + } + + // Allow the script to clamp based on a desired target value. + var targetOrientation = Quaternion.Euler(targetDirection); + var targetCharacterOrientation = Quaternion.Euler(targetCharacterDirection); + + // Get raw mouse input for a cleaner reading on more sensitive mice. + var mouseDelta = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y")); + + // Scale input against the sensitivity setting and multiply that against the smoothing value. + mouseDelta = Vector2.Scale(mouseDelta, new Vector2(sensitivity.x * smoothing.x, sensitivity.y * smoothing.y)); + + // Interpolate mouse movement over time to apply smoothing delta. + _smoothMouse.x = Mathf.Lerp(_smoothMouse.x, mouseDelta.x, 1f / smoothing.x); + _smoothMouse.y = Mathf.Lerp(_smoothMouse.y, mouseDelta.y, 1f / smoothing.y); + + // Find the absolute mouse movement value from point zero. + _mouseAbsolute += _smoothMouse; + + // Clamp and apply the local x value first, so as not to be affected by world transforms. + if (clampInDegrees.x < 360) + _mouseAbsolute.x = Mathf.Clamp(_mouseAbsolute.x, -clampInDegrees.x * 0.5f, clampInDegrees.x * 0.5f); + + // Then clamp and apply the global y value. + if (clampInDegrees.y < 360) + _mouseAbsolute.y = Mathf.Clamp(_mouseAbsolute.y, -clampInDegrees.y * 0.5f, clampInDegrees.y * 0.5f); + + transform.localRotation = Quaternion.AngleAxis(-_mouseAbsolute.y, targetOrientation * Vector3.right) * targetOrientation; + + // If there's a character body that acts as a parent to the camera + if (characterBody) + { + var yRotation = Quaternion.AngleAxis(_mouseAbsolute.x, Vector3.up); + characterBody.transform.localRotation = yRotation * targetCharacterOrientation; + } + else + { + var yRotation = Quaternion.AngleAxis(_mouseAbsolute.x, transform.InverseTransformDirection(Vector3.up)); + transform.localRotation *= yRotation; + } + } +} + \ No newline at end of file