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

Update Mouselook Script

parent dc49399e
...@@ -22,14 +22,13 @@ This allows users to use the mouse for looking around, with seperate sensitivite ...@@ -22,14 +22,13 @@ This allows users to use the mouse for looking around, with seperate sensitivite
![](images/screenshot.png) ![](images/screenshot.png)
1. Add a Empty with <kbd>Rightclick</kbd> + `Add Empty`. Rename it to something useful (we used `Player`) 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. 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. 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 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` 2. Drag the `SmoothMouseLook.cs`-script from the Assets onto the `Player`-Empty.
3. Select the `Capsule` Object
## Tweaking ## Tweaking
......
using System.Collections;
using System.Collections.Generic;
using UnityEngine; using UnityEngine;
[AddComponentMenu("Camera/Simple Smooth Mouse Look ")] [AddComponentMenu("SmoothMouseLook ")]
public class SmoothMouseLook : MonoBehaviour public class SmoothMouseLook : MonoBehaviour
{ {
Vector2 _mouseAbsolute; // The speed at which we turn (Mouse Sensitivity)
Vector2 _smoothMouse; // mouseSensitivity.x is for left <-> right
// mouseSensitivity.y is for up <-> down
[Tooltip("Limit the possible rotation to these values (Left/Right, Up/Down)")] [Tooltip("How fast to turn when moving the mouse (bigger=faster, X: left<->right, Y: up<->down).")]
public Vector2 clampInDegrees = new Vector2(360, 180); [SerializeField] Vector2 mouseSensitivity = new Vector2(70f, 60f);
[Tooltip("Hide/Display Cursor")]
public bool lockCursor; // How much smoothing goes on for each axis
[Tooltip("Mouse Sensitivity (Left/Right, Up/Down)")] [Tooltip("How smooth/mushy the mouse movement becomes (bigger=smoother, X: left<->right, Y: up<->down).")]
public Vector2 sensitivity = new Vector2(2, 2); [SerializeField] Vector2 smoothing = new Vector2(2f, 2f);
[Tooltip("Movement Smoothing (Left/Right, Up/Down)")]
public Vector2 smoothing = new Vector2(3, 3); // How far up the head can tilt, measured in angles from the horizon
[Tooltip("Set target direction to the camera's initial orientation.")] // Must be bigger than headLowerAngleLimit
public Vector2 targetDirection; [Tooltip("How many degrees the head can look up at max.")]
[Tooltip("Set target direction for the character body to its inital state.")] [SerializeField] float headUpperAngleLimit = 85f;
public Vector2 targetCharacterDirection;
// How far down the head can tilt, measured in angles from the horizon
// Assign this if there's a parent object controlling motion, such as a Character Controller. // Must be smaller than headUpperAngleLimit
// Yaw rotation will affect this object instead of the camera if set. [Tooltip("How many degrees the head can look down at max.")]
[Tooltip("Assign Parent Object if there is one (affects horizontal rotation around Y axis)")] [SerializeField] float headLowerAngleLimit = -80f;
public GameObject characterBody;
// 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() void Start()
{ {
// Set target direction to the camera's initial orientation. // Find the head – this returns the transform parameter of this objects
targetDirection = transform.localRotation.eulerAngles; // first Child of type Camera. If none is found head = null
head = GetComponentInChildren<Camera>().transform;
// Set target direction for the character body to its inital state.
if (characterBody) // Cache the orientation of body and head.
targetCharacterDirection = characterBody.transform.localRotation.eulerAngles; // 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:
// https://processing.org/examples/easing.html
private Vector2 EaseMouseDelta(Vector2 mouseDelta)
{ {
// Ensure the cursor is always locked when set // Scale input against the sensitivity setting and multiply that
if (lockCursor) // with the smoothing value.
{ mouseDelta *= mouseSensitivity.x * smoothing.x * Time.deltaTime;
Cursor.lockState = CursorLockMode.Locked; mouseDelta *= mouseSensitivity.y * smoothing.y * Time.deltaTime;
}
// Linear Interpolation ("Lerp") between the smoothed Delta from
// Allow the script to clamp based on a desired target value. // the last round/Frame and the actual mouse Position.
var targetOrientation = Quaternion.Euler(targetDirection); smoothedMouseDelta.x = Mathf.Lerp(smoothedMouseDelta.x, mouseDelta.x, 1f / smoothing.x);
var targetCharacterOrientation = Quaternion.Euler(targetCharacterDirection); smoothedMouseDelta.y = Mathf.Lerp(smoothedMouseDelta.y, mouseDelta.y, 1f / smoothing.y);
// Get raw mouse input for a cleaner reading on more sensitive mice. // 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")); 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. // Run the Smoothing-Function we defined above on the Mouse
mouseDelta = Vector2.Scale(mouseDelta, new Vector2(sensitivity.x * smoothing.x, sensitivity.y * smoothing.y)); // Vector we read before and return a smoothed one
smoothedMouseDelta = EaseMouseDelta(mouseDelta);
// Interpolate mouse movement over time to apply smoothing delta.
_smoothMouse.x = Mathf.Lerp(_smoothMouse.x, mouseDelta.x, 1f / smoothing.x); // Flip the vertical Control, if InvertAxisY is true
_smoothMouse.y = Mathf.Lerp(_smoothMouse.y, mouseDelta.y, 1f / smoothing.y); if (InvertAxisY) {
smoothedMouseDelta.y *= -1;
// 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;
} }
// 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