Commit b3ca5151 authored by David Huss's avatar David Huss 💬

Update Mouselook Script

parent dc49399e
......@@ -22,14 +22,13 @@ This allows users to use the mouse for looking around, with seperate sensitivite
1. Add a Empty with <kbd>Rightclick</kbd> + `Add Empty`. Rename it to something useful (we used `Player`)
2. Make sure the `Main Camera` is at the coordinates `0, 1.7, 0` and then drag the `Main Camera` onto the `Player`-Empty. This makes `Player` the parent of `Main Camera`
2. Make sure the `Main Camera` is at the coordinates `(0, 1.7, 0)` and rotated right and then drag the `Main Camera` onto the `Player`-Empty. This makes `Player` the parent of `Main Camera`
3. Create a Capsule that represents the Player-Body (for collisions and such) with <kbd>Rightclick</kbd> + `3D Object` > `Capsule`. Drag it onto the `Player`-Empty as well.
Now things should look like in the picture above (highlighted in blue). Next we can add the Scripts.
1. Drag the `FPSController.cs`-script from the Assets onto the `Player`-Empty
2. Drag the `SmoothMouseLook.cs`-script from the Assets onto the `Main Camera` Object. And in the Script options (right sidebar) change the value for _Character Body_ to `Player`
3. Select the `Capsule` Object
2. Drag the `SmoothMouseLook.cs`-script from the Assets onto the `Player`-Empty.
## Tweaking
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[AddComponentMenu("Camera/Simple Smooth Mouse Look ")]
[AddComponentMenu("SmoothMouseLook ")]
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;
// The speed at which we turn (Mouse Sensitivity)
// mouseSensitivity.x is for left <-> right
// mouseSensitivity.y is for up <-> down
[Tooltip("How fast to turn when moving the mouse (bigger=faster, X: left<->right, Y: up<->down).")]
[SerializeField] Vector2 mouseSensitivity = new Vector2(70f, 60f);
// How much smoothing goes on for each axis
[Tooltip("How smooth/mushy the mouse movement becomes (bigger=smoother, X: left<->right, Y: up<->down).")]
[SerializeField] Vector2 smoothing = new Vector2(2f, 2f);
// How far up the head can tilt, measured in angles from the horizon
// Must be bigger than headLowerAngleLimit
[Tooltip("How many degrees the head can look up at max.")]
[SerializeField] float headUpperAngleLimit = 85f;
// How far down the head can tilt, measured in angles from the horizon
// Must be smaller than headUpperAngleLimit
[Tooltip("How many degrees the head can look down at max.")]
[SerializeField] float headLowerAngleLimit = -80f;
// Invert the Y Axis of the Mouse if true
[Tooltip("Invert Mouse Control for up<->down.")]
[SerializeField] bool InvertAxisY = true;
// Our current rotation from start in degrees
float yaw = 0f;
float pitch = 0f;
// Stores the orientations of the head and body when the game started
// We'll derive new orientations by combining these with the variables yaw
// and pitch
Quaternion bodyStartOrientation;
Quaternion headStartOrientation;
// A reference to the head object (the object that will rotate up and down)
// The body is the current (this) object, so there is no variable needed.
// We don't want to expose this to the interface. Instead we just look for a
// Child object with type Camera, when the game starts.
Transform head;
// Two 2D-Vectors that store both axis of the mouse
private Vector2 smoothedMouseDelta;
// Start is called before the first frame update
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;
// Find the head – this returns the transform parameter of this objects
// first Child of type Camera. If none is found head = null
head = GetComponentInChildren<Camera>().transform;
// Cache the orientation of body and head.
// This errors if head (Camera Child) was not found
bodyStartOrientation = transform.localRotation;
headStartOrientation = head.transform.localRotation;
// Lock and hide the cursor
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
void Update()
// A Easing function that smooths the mouse-movement. This is beeing
// done by making the head follow the mouse not exactly, but
// with some sort of a lag. The further away the heads point of focus
// is compared to the mouse, the faster it will move, once it comes
// closer, it slows down – this is called Easing.
// For an intuitive Explaination look here:
private Vector2 EaseMouseDelta(Vector2 mouseDelta)
// 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.
// Scale input against the sensitivity setting and multiply that
// with the smoothing value.
mouseDelta *= mouseSensitivity.x * smoothing.x * Time.deltaTime;
mouseDelta *= mouseSensitivity.y * smoothing.y * Time.deltaTime;
// Linear Interpolation ("Lerp") between the smoothed Delta from
// the last round/Frame and the actual mouse Position.
smoothedMouseDelta.x = Mathf.Lerp(smoothedMouseDelta.x, mouseDelta.x, 1f / smoothing.x);
smoothedMouseDelta.y = Mathf.Lerp(smoothedMouseDelta.y, mouseDelta.y, 1f / smoothing.y);
// Return the smoothed 2D-Vector
return smoothedMouseDelta;
// Every time Physics updates, update the movemnent of this object.
// Do this in FixedUpdate to keep pace with physically simulated Objects
void FixedUpdate()
// Read the Position-Change between this Frame and the last
// Note: GetRawAxis gives more sensitivity
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;
var yRotation = Quaternion.AngleAxis(_mouseAbsolute.x, transform.InverseTransformDirection(Vector3.up));
transform.localRotation *= yRotation;
// Run the Smoothing-Function we defined above on the Mouse
// Vector we read before and return a smoothed one
smoothedMouseDelta = EaseMouseDelta(mouseDelta);
// Flip the vertical Control, if InvertAxisY is true
if (InvertAxisY) {
smoothedMouseDelta.y *= -1;
// Add the mouse movements to the current value of yaw and pitch
yaw += smoothedMouseDelta.x;
pitch += smoothedMouseDelta.y;
// Clamp pitch so that we can't look directly down or up
pitch = Mathf.Clamp(pitch, headLowerAngleLimit, headUpperAngleLimit);
// Compute rotations by rotating around a fixed axis (rotate yaw-degrees
// around the up direction for the body, and pitch degrees around the
// right direction for the head).
var bodyRotation = Quaternion.AngleAxis(yaw, Vector3.up);
var headRotation = Quaternion.AngleAxis(pitch, Vector3.right);
// Finally combine the rotations for body and head with the start rotations
transform.localRotation = bodyRotation * bodyStartOrientation;
head.localRotation = headRotation * headStartOrientation;
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment