Search Unity

  1. Calling all beginners! Join the FPS Beginners Mods Challenge until December 13.
    Dismiss Notice
  2. It's Cyber Week at the Asset Store!
    Dismiss Notice

A Free Simple Smooth Mouselook

Discussion in 'Scripting' started by FatiguedArtist, Jan 7, 2011.

  1. FatiguedArtist

    FatiguedArtist

    Joined:
    Mar 3, 2010
    Posts:
    38
    Edits:

    1. After having a few people use the code on this page, I've decided to release a cleaner version below. Feel free to improve upon the design or contact me for information regarding its use.
    2. The script now accounts for initial orientation.
    3. You can now modify the intended origin of the script's clamp by modifying targetDirection at runtime. This is set to initial orientation at start.
    4. You can now specify a separate character body (such as a parent with Character Controller attached) for yaw rotation. This prevents pitch rotation of Character Controller colliders.
    5. Integrated Datates' clamping fix, changed character body rotation to be relative to world up and altered deprecated cursor lock code.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3.  
    4. [AddComponentMenu("Camera/Simple Smooth Mouse Look ")]
    5. public class SimpleSmoothMouseLook : MonoBehaviour
    6. {
    7.     Vector2 _mouseAbsolute;
    8.     Vector2 _smoothMouse;
    9.  
    10.     public Vector2 clampInDegrees = new Vector2(360, 180);
    11.     public bool lockCursor;
    12.     public Vector2 sensitivity = new Vector2(2, 2);
    13.     public Vector2 smoothing = new Vector2(3, 3);
    14.     public Vector2 targetDirection;
    15.     public Vector2 targetCharacterDirection;
    16.  
    17.     // Assign this if there's a parent object controlling motion, such as a Character Controller.
    18.     // Yaw rotation will affect this object instead of the camera if set.
    19.     public GameObject characterBody;
    20.  
    21.     void Start()
    22.     {
    23.         // Set target direction to the camera's initial orientation.
    24.         targetDirection = transform.localRotation.eulerAngles;
    25.  
    26.         // Set target direction for the character body to its inital state.
    27.         if (characterBody)
    28.             targetCharacterDirection = characterBody.transform.localRotation.eulerAngles;
    29.     }
    30.  
    31.     void Update()
    32.     {
    33.         // Ensure the cursor is always locked when set
    34.         if (lockCursor)
    35.         {
    36.             Cursor.lockState = CursorLockMode.Locked;
    37.         }
    38.  
    39.         // Allow the script to clamp based on a desired target value.
    40.         var targetOrientation = Quaternion.Euler(targetDirection);
    41.         var targetCharacterOrientation = Quaternion.Euler(targetCharacterDirection);
    42.  
    43.         // Get raw mouse input for a cleaner reading on more sensitive mice.
    44.         var mouseDelta = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));
    45.  
    46.         // Scale input against the sensitivity setting and multiply that against the smoothing value.
    47.         mouseDelta = Vector2.Scale(mouseDelta, new Vector2(sensitivity.x * smoothing.x, sensitivity.y * smoothing.y));
    48.  
    49.         // Interpolate mouse movement over time to apply smoothing delta.
    50.         _smoothMouse.x = Mathf.Lerp(_smoothMouse.x, mouseDelta.x, 1f / smoothing.x);
    51.         _smoothMouse.y = Mathf.Lerp(_smoothMouse.y, mouseDelta.y, 1f / smoothing.y);
    52.  
    53.         // Find the absolute mouse movement value from point zero.
    54.         _mouseAbsolute += _smoothMouse;
    55.  
    56.         // Clamp and apply the local x value first, so as not to be affected by world transforms.
    57.         if (clampInDegrees.x < 360)
    58.             _mouseAbsolute.x = Mathf.Clamp(_mouseAbsolute.x, -clampInDegrees.x * 0.5f, clampInDegrees.x * 0.5f);
    59.  
    60.         // Then clamp and apply the global y value.
    61.         if (clampInDegrees.y < 360)
    62.             _mouseAbsolute.y = Mathf.Clamp(_mouseAbsolute.y, -clampInDegrees.y * 0.5f, clampInDegrees.y * 0.5f);
    63.  
    64.         transform.localRotation = Quaternion.AngleAxis(-_mouseAbsolute.y, targetOrientation * Vector3.right) * targetOrientation;
    65.  
    66.         // If there's a character body that acts as a parent to the camera
    67.         if (characterBody)
    68.         {
    69.             var yRotation = Quaternion.AngleAxis(_mouseAbsolute.x, Vector3.up);
    70.             characterBody.transform.localRotation = yRotation * targetCharacterOrientation;
    71.         }
    72.         else
    73.         {
    74.             var yRotation = Quaternion.AngleAxis(_mouseAbsolute.x, transform.InverseTransformDirection(Vector3.up));
    75.             transform.localRotation *= yRotation;
    76.         }
    77.     }
    78. }
    79.  
     
    Last edited: Jun 1, 2017
  2. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    Is this intended to implement standard 'FPS-style' rotation, where pitch is always about the local side axis and yaw is always about the world up axis?

    If so, the method you're using is kind of roundabout, IMO. It looks like you're applying the rotation in local space, and then trying to 'correct' the rotation manually, which is kind of like deliberately breaking something just so you can fix it. (Also, it's not really that 'quaternions' are mucking up the orientation; rather, it's the rotation method you're using that's having that effect.)

    What I would do for something like this is simply to store pitch and yaw angles and manipulate those in response to mouse input. Then, each update (or fixed update or whatever), rebuild the orientation from those angles.

    (If I've misread or misinterpreted your code and that's not the type of motion you're intending to implement here, then ignore the above...)
     
  3. FatiguedArtist

    FatiguedArtist

    Joined:
    Mar 3, 2010
    Posts:
    38
    Yeah the rotation is intended to be FPS style, the rotation method used utilizes quaternions, which is why when I only modify the x and y values the z coordinates still get modified and slowly add to the final z result hence I manually change the z axis in euler angles after the rotation method is called.

    I see where you're getting at when you talk about the pitch/yaw values (I assume you're thinking in terms of eulers), though it's not as simple as associating a certain angle with a set mouse position; as the x and y axes only work incrementally, not in absolutes, so you have to add the movement, not rebuild it (and Screen.MousePosition only works in in-screen areas, preventing 360 degree mouse orientation). The beauty of using the transform.Rotate() function is because it uses Quaternions, as they prevent the additive rotations from gimble locking. * edit * (they lock because the rotations used in transforms by unity are stored as Quaternions)
     
  4. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    It's not really because you're using quaternions, no. It so happens that Unity uses quaternions to represent object orientations, but the reason you're having to correct for z rotation is simply that you're applying all rotations in local space (which would lead to the 'z rotation' problem even if, for example, matrices were used instead of quaternions).

    Again, the correct solution is to represent and update the orientation in such a way that no correction is necessary.

    Nobody said anything about associating angles with mouse positions. When representing the orientation using pitch and yaw angles, you'd still update them incrementally using mouse deltas, just as you're doing now.

    Incorrect. Whether or not you use quaternions has nothing to do with whether or not you're likely to encounter gimbal lock. Rather, it's how you construct and manipulate your rotations that determines whether gimbal lock may occur. Transform.Rotate() could be implemented using quaternions, matrices, or simple direction vectors, and it would still behave in exactly the same way.

    Also, gimbal lock isn't even a concern in the given context. Since you're only rotating about two axes (side and up), gimbal lock will not occur. Since gimbal lock is not an issue with this type of control scheme, there's no point in jumping through hoops trying to avoid it.

    Again, the method you're using is needlessly roundabout. If you want simple FPS-style controls, just work with pitch and yaw angles directly; it'll be more straightforward that way, and the results will be equivalent.
     
  5. FatiguedArtist

    FatiguedArtist

    Joined:
    Mar 3, 2010
    Posts:
    38
    Aah now I understand what you mean when you are saying i'm applying the rotations locally! Yeah sorry I thought you were suggesting something different to what you really meant, and by all means tell me I'm wrong when I'm wrong :p my understanding of quaternions was just that each axis affects the other so I thought the z was being modified by the x and y rotations when converting euler rotations. (and it was 4 in the morning my time).

    I've tested with adding straight to global euler values and it works just fine, i'll post a much better version shortly.
     
  6. FatiguedArtist

    FatiguedArtist

    Joined:
    Mar 3, 2010
    Posts:
    38
    EDIT: Please refer to the first post for the latest version of this script.

    Code (csharp):
    1.  
    2.  
    3. using UnityEngine;
    4. using System.Collections;
    5.  
    6. // Very simple smooth mouselook modifier for the MainCamera in Unity by FatiguedArtist
    7. //(Francis R. Griffiths-Keam) - www.fatiguedartist.com
    8.  
    9. [AddComponentMenu("Camera/Simple Smooth Mouse Look ")]
    10. public class SimpleSmoothMouseLook : MonoBehaviour {
    11.  
    12.     public bool lockCursor = false;
    13.  
    14.     public float sensitivity = 30;
    15.     public int smoothing = 10;
    16.  
    17.     float ymove;
    18.     float xmove;
    19.  
    20.     int iteration = 0;
    21.  
    22.     float xaggregate = 0;
    23.     float yaggregate = 0;
    24.  
    25.     //int Ylimit = 0;
    26.     public int Xlimit = 20;
    27.  
    28.     void Start()
    29.     {
    30.         // make the cursor invisible and locked?
    31.  
    32.         if (lockCursor)
    33.         {
    34.             Screen.lockCursor = true;
    35.         }
    36.     }
    37.  
    38.  
    39.     void FixedUpdate () {
    40.  
    41.         // ensure mouseclicks do not effect the screenlock
    42.  
    43.         if (lockCursor)
    44.         if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1))
    45.         {
    46.             Screen.lockCursor = true;
    47.         }
    48.  
    49.         float[] x = new float[smoothing];
    50.         float[] y = new float[smoothing];
    51.  
    52.         // reset the aggregate move values
    53.  
    54.         xaggregate = 0;
    55.         yaggregate = 0;
    56.  
    57.         // receive the mouse inputs
    58.  
    59.         ymove = Input.GetAxis("Mouse Y");
    60.         xmove = Input.GetAxis("Mouse X");
    61.  
    62.         // cycle through the float arrays and lop off the oldest value, replacing with the latest
    63.  
    64.         y[iteration % smoothing] = ymove;
    65.         x[iteration % smoothing] = xmove;
    66.  
    67.         iteration++;
    68.  
    69.         // determine the aggregates and implement sensitivity
    70.  
    71.         foreach (float xmov in x)
    72.         {
    73.             xaggregate += xmov;
    74.         }
    75.  
    76.         xaggregate = xaggregate / smoothing * sensitivity;
    77.  
    78.         foreach (float ymov in y)
    79.         {
    80.             yaggregate += ymov;
    81.         }
    82.  
    83.         yaggregate = yaggregate / smoothing * sensitivity;
    84.  
    85.         // turn the x start orientation to non-zero for clamp
    86.  
    87.         Vector3 newOrientation = transform.eulerAngles + new Vector3(-yaggregate, xaggregate, 0);
    88.  
    89.  
    90.         xclamp = Mathf.Clamp(newOrientation.x, Xlimit, 360-Xlimit)%360;
    91.  
    92.         // rotate the object based on axis input (note the negative y axis)
    93.        
    94.         transform.eulerAngles = newOrientation;
    95.        
    96.     }
    97. }
    98.  
    I think this is what you meant am I correct?
     
    Last edited: Aug 29, 2013
    LightingBox2 likes this.
  7. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    I'd have to look over it more carefully to be sure, but yes, that looks about right. (I didn't proof the clamping part though.)

    Note however that this:

    Code (csharp):
    1. transform.eulerAngles = new Vector3(newOrientation.x,newOrientation.y,newOrientation.z);
    Can simply be written as:

    Code (csharp):
    1. transform.eulerAngles = newOrientation;
     
  8. FatiguedArtist

    FatiguedArtist

    Joined:
    Mar 3, 2010
    Posts:
    38
    haha woops thanks, yeah I missed that when I was changing around the code :p

    * edit * i've corrected the code.

    * second edit * dammit, I tested clamping separately and clamping does work with negative values. I've got to test things properly before I go talking nonsense. I'll change that as well.
     
    Last edited: Jan 9, 2011
  9. Ronin-Ra

    Ronin-Ra

    Joined:
    Jul 7, 2012
    Posts:
    42
    Love the script, makes mouse movement very smooth :)

    But! There's always a but :p
    I have added an Input check to activate the mouselook and attached it to my main camera, but whenever I actually use it in the game (I use Right Mouse Button) the camera resets to 0,0,0 when the mouselook is activated.

    It looks like the script just resets whatever it's attached to to 0,0,0 instead of moving relative to the gameObjects (camera in my case) initial position.
    Any idea how I can avoid that from happening?
     
  10. FatiguedArtist

    FatiguedArtist

    Joined:
    Mar 3, 2010
    Posts:
    38
    @Ronin-Ra Thanks!

    From what I have read of your other thread regarding the script, it appears to be because I'm not accounting for initial orientation. Sorry about that, I'll fix it now. My tests were done in-editor, so it never lost mouse focus when I checked if it worked.
     
  11. Ronin-Ra

    Ronin-Ra

    Joined:
    Jul 7, 2012
    Posts:
    42
    Wow, so simple and yet so nice, it's perfect now!

    Thank you for taking the time to update your script :D
     
  12. FatiguedArtist

    FatiguedArtist

    Joined:
    Mar 3, 2010
    Posts:
    38
    Happy to help.
     
  13. Clara Weber

    Clara Weber

    Joined:
    Mar 16, 2013
    Posts:
    1
    I seem to have the same problem with the smoothed camera suddenly jumping into another coordinate position / coordinate system. Can you please provide the script you improved? Would be great. Thanks.
     
  14. FatiguedArtist

    FatiguedArtist

    Joined:
    Mar 3, 2010
    Posts:
    38
    @Clara The latest version of the script is located in the first post. Can you confirm the jumping issue only occurs when you first start the game?
     
  15. Mïglu

    Mïglu

    Joined:
    Jul 15, 2012
    Posts:
    1
    Thanks for this great script.
    I am using it to rotate a camera, and sometimes switch to another camera. When I return to the first camera, I want it to have the same rotation as when it was left, but instead it has the same rotation as where the second camera was left, even if I disable it while it is not being used. Could you suggest how the script should be modified to prevent this?
     
  16. FatiguedArtist

    FatiguedArtist

    Joined:
    Mar 3, 2010
    Posts:
    38
    @Mïglu:
    It sounds like you are only disabling the camera, not the attached mouse look script. Make sure to set your mouse look component to mouseLook.enabled = false; That should lock the current mouse look orientation in place.
     
  17. Zeblote

    Zeblote

    Joined:
    Feb 8, 2013
    Posts:
    1,102
    Wait, components don't get deactivated if the gameobject they are attached to is deactivated?
     
  18. FatiguedArtist

    FatiguedArtist

    Joined:
    Mar 3, 2010
    Posts:
    38
    @Zeblote:
    The Camera itself is a component. Yes setting a GameObject to inactive will disable all scripts on that object, but the behaviour described by Mïglu suggests they are only disabling the Camera, not its GameObject. Because this script relies on the Update method to modify orientation values, any behaviour where those values change would suggest the component is still enabled.

    I would not suggest straight away to just set the Camera's GameObject to inactive as a solution, in case there are any child objects which may be affected by that change, as a GameObject's active state affects its children as well.
     
  19. crusherxman

    crusherxman

    Joined:
    Mar 2, 2013
    Posts:
    2
    I'm getting this error:

    Assets/SmoothMouseLook.cs(88,9): error CS0103: The name `xclamp' does not exist in the current context
     
  20. FatiguedArtist

    FatiguedArtist

    Joined:
    Mar 3, 2010
    Posts:
    38
    Crusherxman, the version of the script you have quoted is an old one. Please refer to the first post for the latest version of the script. If you experience issues with that version, let me know.
     
  21. newb_quest

    newb_quest

    Joined:
    Oct 4, 2013
    Posts:
    22
    hey there,

    Just wanted to say, what a great script! Really added a lot to a project I'm working on so just wanted to say a big THANK YOU!

    This may be a little wacky but I've added this script to a 3rd person game in which the camera follows the player who is flying around in 3d space. It all works very well generally. The thing I am trying to add to it is to allow the player to do 'loop the loops' in the air and make 360 degree turns in all axes. This works when I set both clamping values to 360, however when the player is flying upside down the left and right mouse looks are inverted so left looks right, etc. When you revert to flying upright the controls return to normal.

    I am very new to programming so I'm really just hacking and chopping my way through with lots of copying and pasting of other people's excellent work (like yours!) but what I was thinking was that maybe I should put in some kind of check for if the player has turned upside down and then invert the x axis rotation or something? Grasping at straws a bit there.

    If you've got a second to point me in the right direction it'd be much appreciated! Thanks in advance.
     
  22. Louthskater

    Louthskater

    Joined:
    Jul 25, 2013
    Posts:
    1
    Is this script free and open source?
     
  23. asdx

    asdx

    Joined:
    Jun 3, 2013
    Posts:
    18
    I tried the MouseLook version from Unity Standard Assets and this version(the one in the first post) but I still have a problem with the camera jumping. The starting position for my camera is top-down(RTS game), but when i try to use the mouselook it jumps to 0. What should I do?

    EDIT: ok, the script works.. But I use Unity serializer for saving and loading, so I need to adapt this to use the cameras position at save-point.
     
    Last edited: Nov 24, 2013
  24. asdx

    asdx

    Joined:
    Jun 3, 2013
    Posts:
    18
    Found out how to make serializer work. Just make _mouseAbsolute and _smoothMouse public.

    Forgot that Serializer saves only public variables unless specified otherwise. Reference is in the getting started guide at controlling what gets saved (Link)
     
    Last edited: Nov 24, 2013
  25. FatiguedArtist

    FatiguedArtist

    Joined:
    Mar 3, 2010
    Posts:
    38
    @asdx
    I'm glad you were able to sort that out. There is also the SerializeField attribute which may be of use and does not require you to make fields public.

    @newb_quest
    Sorry to reply so long after your post. I used to get e-mails when a post was made to this thread so I assumed it wasn't active. This script isn't designed to operate with a variable ground plane, though it could be possible to rewire targetDirection to account for all 3 axes.

    @Louthskater
    Yes this script is free and open source for commercial and non-commercial use alike so long as I am accredited somehow.
     
    Last edited: Dec 1, 2013
  26. sruthidivakar

    sruthidivakar

    Joined:
    Apr 8, 2013
    Posts:
    3
    I am developing a third person shooter game for mobiles.
    When i drag on the screen camera smoothly rotate. But the issue is when click after the fire button, users finger is at the left end of the device and is touched there, camera suddenly switch to the left touched position without considering the Lerp values. This will happen rarely. please help me to findout the issue

    I expect an output like Frontline Commando2

    Thanks in advance..
     
  27. h8crew

    h8crew

    Joined:
    Jul 15, 2013
    Posts:
    2
    Sorry for bringing back the dead, but can I say that this is the best Smooth Mouse Look script I have found? It feels amazing! All of the other ones available online that I've seen have a nasty, sloppy smoothing effect after you've stopped moving your mouse. Great job, but I did have to make one slight edit.

    I am using a parent GameObject for my character and I was having issues with the character spinning around violently around the scene. (Maybe because of the RigidBody on it? Not sure). He was literally turning into a helicopter and flying around the scene (was hilarious to watch). So if anyone else stumbles across this problem in the future just change this line:

    var yRotation = Quaternion.AngleAxis(_mouseAbsolute.x, characterBody.transform.up);

    To:

    var yRotation = Quaternion.AngleAxis(_mouseAbsolute.x, Vector3.up);

    I haven't tested this theory, but I think what was happening was the rigid body was lilting the character ever so slightly and this script was overriding the up vector so they started to not play nicely with each other. For me keeping the character parent aligned with the world was fine.
     
    Soos621 likes this.
  28. xarbn

    xarbn

    Joined:
    Oct 13, 2013
    Posts:
    8
    My player isn't turning! Everything else works fine
     
  29. Pyroglyph

    Pyroglyph

    Joined:
    Aug 8, 2014
    Posts:
    1
    I'm getting the same problem. It worked fine with a test capsule but when I transferred everything over to my new player model, there is no change int he X angle of the camera being made anymore. Y works fine.
     
  30. Mack7n

    Mack7n

    Joined:
    Sep 26, 2014
    Posts:
    1
    "The referenced script on this Behaviour is missing!" I'm new to Unity/Scripting. Just messing around with it for now, and trying to learn by trial and error. When I pasted your code into the MouseLook on the camera, I am getting this error. Not quite sure how to fix it. I've been googling every combination I can think of to hopefully find an answer, and came up with nothing, so figured I would finally cave and make a post here. :-(
     
  31. FatiguedArtist

    FatiguedArtist

    Joined:
    Mar 3, 2010
    Posts:
    38
    First of all, sorry everyone for the belated response. I don't get e-mails when anyone posts in this thread for some reason.

    @h8crew: Good catch! Yes it was probably a floating point error building up over time. I might have a review of the code to see if I can find an elegant solution.

    @dubstaphone + @Pyroglyph: If you have a simple example scene that demonstrates the problem you're having I could find some time to look into what's causing your problem. I think it's related to the characterBody you've assigned when changing the root object.

    @Mack7n: This script is intended to be placed in a new .cs file called SimpleSmoothMouseLook.cs MonoBehaviours like to be placed in files of the same name. Replacing the MouseLook script will have caused references in your scene to the 'Mouse Look' component to break, since that class no longer exists.
     
  32. ronjart

    ronjart

    Joined:
    May 16, 2013
    Posts:
    94
    Thank you for this Asset. Really appreciate it!
     
  33. sisisis

    sisisis

    Joined:
    Mar 25, 2015
    Posts:
    1
    How do i use this script with a rigidbody
     
  34. Johaneto

    Johaneto

    Joined:
    Apr 2, 2015
    Posts:
    4
    hi ppl, this code does not work for Unity 5

    this part needs to be changed cuz is depresiated
    Code (CSharp):
    1. Screen.lockCursor = lockCursor;
    for this1

    Code (CSharp):
    1. Cursor.lockState = CursorLockMode.Locked;
    but then it says that "The referenced script on this Behaviour is missing!" and that's it end of the road it does not work
     
  35. Datates

    Datates

    Joined:
    Oct 23, 2013
    Posts:
    2
    Great script - have found a minor issue with the clamping though.

    Starting at line 55 you currently have the following checks:
    Code (csharp):
    1. // Clamp and apply the local x value first, so as not to be affected by world transforms.
    2. if (clampInDegrees.x < 360)
    3.  _mouseAbsolute.x = Mathf.Clamp(_mouseAbsolute.x, -clampInDegrees.x * 0.5f, clampInDegrees.x * 0.5f);
    4.  
    5. var xRotation = Quaternion.AngleAxis(-_mouseAbsolute.y, targetOrientation * Vector3.right);
    6. transform.localRotation = xRotation;
    7.  
    8. // Then clamp and apply the global y value.
    9. if (clampInDegrees.y < 360)
    10.  _mouseAbsolute.y = Mathf.Clamp(_mouseAbsolute.y, -clampInDegrees.y * 0.5f, clampInDegrees.y * 0.5f);
    11.  
    12. transform.localRotation *= targetOrientation;
    You clamp the x-value, set the xRotation variable (which is dependant on mouseAbsolute.y), and then clamp the y-value. This makes it possible for the y-value to exceed the given clamp value.

    Simply moving the y-clamp check up immediately after x-clamp will fix it all, like this:
    Code (csharp):
    1. // Clamp and apply the local x value first, so as not to be affected by world transforms.
    2. if (clampInDegrees.x < 360)
    3.  _mouseAbsolute.x = Mathf.Clamp(_mouseAbsolute.x, -clampInDegrees.x * 0.5f, clampInDegrees.x * 0.5f);
    4.  
    5. // Then clamp and apply the global y value.
    6. if (clampInDegrees.y < 360)
    7.  _mouseAbsolute.y = Mathf.Clamp(_mouseAbsolute.y, -clampInDegrees.y * 0.5f, clampInDegrees.y * 0.5f);
    8.  
    9. var xRotation = Quaternion.AngleAxis(-_mouseAbsolute.y, targetOrientation * Vector3.right);
    10. transform.localRotation = xRotation * targetOrientation;
     
    WILEz1975 likes this.
  36. Alex_1_1

    Alex_1_1

    Joined:
    Jun 22, 2015
    Posts:
    1
    Thanks so much for this code you saved our Year 11 IPT assignment! :)
     
  37. Elrond89

    Elrond89

    Joined:
    Aug 27, 2015
    Posts:
    1
    Thank you very much for this code, it worked very well.
     
  38. danny7

    danny7

    Joined:
    Jan 27, 2014
    Posts:
    2
    @FatiguedArtist Thank you so much for this script, I've been looking everywhere for a MouseLook that uses a parent object for it also, and this instantly fixed my problem.
     
  39. superme2012

    superme2012

    Joined:
    Nov 5, 2012
    Posts:
    207
    also thanks for the script,

    I needed to know the x rotation value so that I could use it to move an object..
    I added this line under line 63:

    mouseX=Mathf.RoundToInt(xRotation.x*10); //Used with int mouseX

    Result is a 7 for down and -7 for up... Handy ;p
     
  40. David_Ongenaert

    David_Ongenaert

    Joined:
    May 5, 2016
    Posts:
    1
    I'm relatively new to unity too, so this is probably not the best solution. It works though :)

    Code (CSharp):
    1. // Ensure the cursor is always locked when set
    2. if (lockCursor == true)
    3.      Cursor.lockState = CursorLockMode.Locked;
     
    Last edited: May 5, 2016
  41. Zyxil

    Zyxil

    Joined:
    Nov 23, 2009
    Posts:
    111
    My take on this. Added movement for free flight, cleaned out the accelleration and slow features. Toggled by LeftShift.

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. // Very simple smooth mouselook modifier for the MainCamera in Unity
    4. // by Francis R. Griffiths-Keam - www.runningdimensions.com
    5. // http://forum.unity3d.com/threads/a-free-simple-smooth-mouselook.73117/
    6.  
    7.  
    8. public class MouseLook : MonoBehaviour
    9. {
    10.     Vector2 _mouseAbsolute;
    11.     Vector2 _smoothMouse;
    12.  
    13.     public Vector2 clampInDegrees = new Vector2(360, 180);
    14.     public Vector2 sensitivity = new Vector2(2, 2);
    15.     public Vector2 smoothing = new Vector2(3, 3);
    16.     public Vector2 targetDirection;
    17.     public Vector2 targetCharacterDirection;
    18.  
    19.     // Assign this if there's a parent object controlling motion, such as a Character Controller.
    20.     // Yaw rotation will affect this object instead of the camera if set.
    21.     public GameObject characterBody;
    22.  
    23.     private Background _background;
    24.     private bool _mouselookEnabled = false;
    25.     private bool _shifted = false;
    26.     public float flySpeed = 0.5f;
    27.     public GameObject defaultCamera;
    28.  
    29.  
    30.     void Start()
    31.     {
    32.         // Set target direction to the camera's initial orientation.
    33.         targetDirection = transform.localRotation.eulerAngles;
    34.  
    35.         // Set target direction for the character body to its inital state.
    36.         if (characterBody)
    37.             targetCharacterDirection = characterBody.transform.localRotation.eulerAngles;
    38.  
    39.         _background = GameObject.FindGameObjectWithTag("Background").GetComponent<Background>();
    40.     }
    41.  
    42.     void Update()
    43.     {
    44.         if (_background.InLobby)
    45.             return;
    46.  
    47.         if (Input.GetKeyUp(KeyCode.LeftShift) & _shifted)
    48.             _shifted = false;
    49.  
    50.         if ((Input.GetKeyDown(KeyCode.LeftShift) & !_shifted) |
    51.             (Input.GetKeyDown(KeyCode.Escape) & _mouselookEnabled))
    52.         {
    53.             _shifted = true;
    54.  
    55.             if (!_mouselookEnabled)
    56.             {
    57.                 _mouselookEnabled = true;
    58.                 Cursor.lockState = CursorLockMode.Locked;
    59.                 Cursor.visible = false;
    60.             }
    61.             else
    62.             {
    63.                 if (Input.GetKeyDown(KeyCode.Escape))
    64.                     _shifted = false;
    65.                    
    66.                 _mouselookEnabled = false;
    67.                 Cursor.lockState = CursorLockMode.None;
    68.                 Cursor.visible = true;
    69.             }
    70.         }
    71.  
    72.         if (!_mouselookEnabled)
    73.             return;
    74.  
    75.         //ensure these stay this way
    76.         Cursor.lockState = CursorLockMode.Locked;
    77.         Cursor.visible = false;
    78.  
    79.         // Allow the script to clamp based on a desired target value.
    80.         var targetOrientation = Quaternion.Euler(targetDirection);
    81.         var targetCharacterOrientation = Quaternion.Euler(targetCharacterDirection);
    82.  
    83.         // Get raw mouse input for a cleaner reading on more sensitive mice.
    84.         var mouseDelta = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));
    85.  
    86.         // Scale input against the sensitivity setting and multiply that against the smoothing value.
    87.         mouseDelta = Vector2.Scale(mouseDelta, new Vector2(sensitivity.x * smoothing.x, sensitivity.y * smoothing.y));
    88.  
    89.         // Interpolate mouse movement over time to apply smoothing delta.
    90.         _smoothMouse.x = Mathf.Lerp(_smoothMouse.x, mouseDelta.x, 1f / smoothing.x);
    91.         _smoothMouse.y = Mathf.Lerp(_smoothMouse.y, mouseDelta.y, 1f / smoothing.y);
    92.  
    93.         // Find the absolute mouse movement value from point zero.
    94.         _mouseAbsolute += _smoothMouse;
    95.  
    96.         // Clamp and apply the local x value first, so as not to be affected by world transforms.
    97.         if (clampInDegrees.x < 360)
    98.             _mouseAbsolute.x = Mathf.Clamp(_mouseAbsolute.x, -clampInDegrees.x * 0.5f, clampInDegrees.x * 0.5f);
    99.  
    100.         // Then clamp and apply the global y value.
    101.         if (clampInDegrees.y < 360)
    102.             _mouseAbsolute.y = Mathf.Clamp(_mouseAbsolute.y, -clampInDegrees.y * 0.5f, clampInDegrees.y * 0.5f);
    103.  
    104.         var xRotation = Quaternion.AngleAxis(-_mouseAbsolute.y, targetOrientation * Vector3.right);
    105.         transform.localRotation = xRotation * targetOrientation;
    106.  
    107.         // If there's a character body that acts as a parent to the camera
    108.         if (characterBody)
    109.         {
    110.             var yRotation = Quaternion.AngleAxis(_mouseAbsolute.x, characterBody.transform.up);
    111.             characterBody.transform.localRotation = yRotation;
    112.             characterBody.transform.localRotation *= targetCharacterOrientation;
    113.         }
    114.         else
    115.         {
    116.             var yRotation = Quaternion.AngleAxis(_mouseAbsolute.x, transform.InverseTransformDirection(Vector3.up));
    117.             transform.localRotation *= yRotation;
    118.         }
    119.  
    120.         //movement
    121.         if (Input.GetAxis("Vertical") != 0)
    122.         {
    123.             transform.Translate(defaultCamera.transform.forward * flySpeed * Input.GetAxis("Vertical"), Space.World);
    124.         }
    125.         if (Input.GetAxis("Horizontal") != 0)
    126.         {
    127.             transform.Translate(defaultCamera.transform.right * flySpeed * Input.GetAxis("Horizontal"), Space.World);
    128.         }
    129.         if (Input.GetKey(KeyCode.R))
    130.         {
    131.             transform.Translate(Vector3.up * flySpeed * 0.5f, Space.World);
    132.         }
    133.         else if (Input.GetKey(KeyCode.W))
    134.         {
    135.             transform.Translate(-Vector3.up * flySpeed * 0.5f, Space.World);
    136.         }
    137.     }
    138. }
     
  42. TheMoonwalls

    TheMoonwalls

    Joined:
    Nov 18, 2013
    Posts:
    31
    Hi!
    Does anyone managed to implement something like this into this mouse look? Can't get this to work.
    void OnEnable() {
    rotArrayX.Clear();
    rotArrayY.Clear();
    rotAverageX = rotAverageY = rotationX = rotationY = 0;

    originalRotation = transform.localRotation;
    }
     
  43. rblkwa

    rblkwa

    Joined:
    Jun 20, 2013
    Posts:
    61
    I needed to use a LookAt after making a teleport to a new location.

    If anyone is interested, this is how you set the angle and do a lookat:

    From my teleporter trigger:
    Code (CSharp):
    1.      
    2.  void OnTriggerEnter(Colliderother) {
    3.  
    4. if (other.transform.parent != null)
    5. return;
    6.  
    7. audioBase.Play ();
    8. other.transform.position = teleportTarget.position;
    9.  
    10. if (other.transform.tag != "Player")
    11. return;
    12.  
    13. SimpleSmoothMouseLook camera = other.GetComponentInChildren<SimpleSmoothMouseLook> ();
    14. camera.enabled = false; //disable the script
    15. camera.transform.rotation = teleportTarget.rotation; // set the wanted rotation
    16. camera.enabled = true; //enable the script again
    17.  
    18. }
    19.  
    Adjust the SimpleSmoothMouseLook script by adding OnEnable method:

    Code (CSharp):
    1.     void OnEnable() {
    2.         float angle = 0.0f;
    3.         Vector3 axis = Vector3.zero;
    4.         transform.rotation.ToAngleAxis (out angle, out axis); // get the axis and angle from our rotation
    5.         _mouseAbsolute.x = angle; // set the angle
    6.     }
     
  44. WILEz1975

    WILEz1975

    Joined:
    Mar 23, 2013
    Posts:
    301
    Thank you, it was a problem. ;)
     
  45. stompi

    stompi

    Joined:
    Mar 11, 2017
    Posts:
    1
    It did solve the problem thank you very much
     
  46. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    6,877
    To anyone who's thinking of using this script: this is not a good script. It makes several rookie mistakes, chief among which is using Euler angles (they're awful, don't use them). I personally have seen at least two threads from people who have ultimately traced their problems down to this script.

    Consider yourself warned.
     
    Beansolder likes this.
  47. FatiguedArtist

    FatiguedArtist

    Joined:
    Mar 3, 2010
    Posts:
    38
    @StarManta Were you referring to the script present in the first post, which was updated in August 2013 to predominantly use quaternions in the update method body, or to older versions of the script present elsewhere in this thread? I'm not against criticism of a script I initially wrote 6.5 years ago, which I should probably update and improve but I would like to know to what you refer. I also humbly request that, in the fashion of other contributors to this thread, you propose solutions (or even a better script) if you can in a way that may benefit members of the community on this forum. Also, if you could provide links to the threads where people are experiencing issues, that would also be most helpful.
     
    DYLEE93, indevious and rblkwa like this.
  48. RagoVK

    RagoVK

    Joined:
    May 16, 2017
    Posts:
    2
    Simple and great Script that works fine.
    I was searching for something like this to have a Base for a simple, but yet comfortable MouseLook, which I can extend easy, so that I can move through my Projects. With the Exception of the Lines for the parented Object, I just copied and pasted the Code and it works 'out of the Box' as expected (Unity 5.6.0).
    Thank You very much.
    :)
     
  49. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,383
    Here's one I modified from elsewhere, but there's no pitch limiting yet:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. // http://forum.unity3d.com/threads/really-need-some-help-with-mouselook-s.49243/
    6. public class MouseLookAveragedS : MonoBehaviour {
    7.  
    8.     [Header("Info")]
    9.     private List<float> _rotArrayX = new List<float>();
    10.     private List<float> _rotArrayY = new List<float>();
    11.     private float rotAverageX;
    12.     private float rotAverageY;
    13.     private float mouseDeltaX;
    14.     private float mouseDeltaY;
    15.  
    16.     [Header("Settings")]
    17.     public float _sensitivityX = 1.5f;
    18.     public float _sensitivityY = 1.5f;
    19.     [Tooltip("The more steps, the smoother it will be.")]
    20.     public int _averageFromThisManySteps = 3;
    21.  
    22.     [Header("References")]
    23.     [Tooltip("Object to be rotated when mouse moves left/right.")]
    24.     public Transform _playerRootT;
    25.     [Tooltip("Object to be rotated when mouse moves up/down.")]
    26.     public Transform _cameraT;
    27.  
    28.     //============================================
    29.     // FUNCTIONS (UNITY)
    30.     //============================================
    31.  
    32.     void Update()
    33.     {
    34.         MouseLookAveraged();
    35.     }
    36.  
    37.     //============================================
    38.     // FUNCTIONS (CUSTOM)
    39.     //============================================
    40.  
    41.     void MouseLookAveraged()
    42.     {
    43.         rotAverageX = 0f;
    44.         rotAverageY = 0f;
    45.         mouseDeltaX = 0f;
    46.         mouseDeltaY = 0f;
    47.  
    48.         mouseDeltaX += Input.GetAxis("Mouse X") * _sensitivityX;
    49.         mouseDeltaY += Input.GetAxis("Mouse Y") * _sensitivityY;
    50.  
    51.         // Add current rot to list, at end
    52.         _rotArrayX.Add(mouseDeltaX);
    53.         _rotArrayY.Add(mouseDeltaY);
    54.  
    55.         // Reached max number of steps? Remove oldest from list
    56.         if (_rotArrayX.Count >= _averageFromThisManySteps)
    57.             _rotArrayX.RemoveAt(0);
    58.  
    59.         if (_rotArrayY.Count >= _averageFromThisManySteps)
    60.             _rotArrayY.RemoveAt(0);
    61.  
    62.         // Add all of these rotations together
    63.         for (int i_counterX = 0; i_counterX < _rotArrayX.Count; i_counterX++)
    64.             rotAverageX += _rotArrayX[i_counterX];
    65.  
    66.         for (int i_counterY = 0; i_counterY < _rotArrayY.Count; i_counterY++)
    67.             rotAverageY += _rotArrayY[i_counterY];
    68.  
    69.         // Get average
    70.         rotAverageX /= _rotArrayX.Count;
    71.         rotAverageY /= _rotArrayY.Count;
    72.  
    73.         // Apply
    74.         _playerRootT.Rotate(0f, rotAverageX, 0f, Space.World);
    75.         _cameraT.Rotate(-rotAverageY, 0f, 0f, Space.Self);
    76.     }
    77.  
    78. }
     
    Last edited: Jul 14, 2017
  50. AdamGoodrich

    AdamGoodrich

    Joined:
    Feb 12, 2013
    Posts:
    3,644
    Nice script! Is it open source ?