Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Really need some help with Mouselook :S

Discussion in 'Scripting' started by Fourthings, May 18, 2010.

  1. Fourthings

    Fourthings

    Joined:
    Feb 15, 2010
    Posts:
    313
    Heyo, I'm trying to remove the jittery jagged movement of the mouselook script that comes with Unity. It's not a performance or machine problem.

    I think I need to average the movement between the most recent and current frame? Maybe with a Quaternion.Lerp?

    But I have no idea how to do that, basically I just want a nice smooth mouselook for an fps, something like Avert Fate.
    I've been all over the forums and google tryna find a solution to this, and found bits here and there.

    But what I really need is a clear explanation of the process of coding a nice smooth fps mouselook

    I found a js version of the mouselook script I'm working with, I figure it's prolly best I stick to js until I get a good understanding of it, before I venture into c#

    Here's what I have, right now it says it needs a semicolon on the 4th line(2nd line of text here) I'm kinda at me wits end with it, and it's pretty much a hacked script from some C# examples I've found, I don't fully understand what it's doing

    Code (csharp):
    1.  
    2.  
    3. enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 };
    4. var RotationAxes axis = (RotationAxes.MouseXAndY);
    5.  
    6. var sensitivityX = 15;
    7. var sensitivityY = 15;
    8.  
    9. var minimumX = -360;
    10. var maximumX = 360;
    11.  
    12. var minimumY = -60;
    13. var maximumY = 60;
    14.  
    15. var rotationX = 0;
    16. var rotationY = 0;
    17.  
    18. var xInput = 0;
    19. var yInput = 0;
    20.    
    21. var xInputOld = 0;
    22. var yInputOld = 0;
    23.    
    24. var averageXInput = 0;
    25. var averageYInput = 0;
    26.    
    27. var rotationX = 0;
    28. var rotationY = 0;
    29.    
    30. var originalRotation : Quaternion;
    31.  
    32.  
    33. /////////////////////////////////////////
    34. ////////////////////////////////////////
    35.  
    36.  
    37.  
    38. function FixedUpdate ()
    39. {      
    40.     if (axes == RotationAxes.MouseXAndY)
    41.       {  
    42.          // Pass inputs to inputOlds first...
    43.          xInputOld=xInput;
    44.          yInputOld=yInput;
    45.      
    46.          // Read the mouse input axis
    47.          xInput = Input.GetAxis("Mouse X") * sensitivityX;
    48.          yInput = Input.GetAxis("Mouse Y") * sensitivityY;
    49.          
    50.          //Average new inputs with old
    51.          averageXInput = xInput + xInputOld;
    52.          averageYInput = yInput + yInputOld;
    53.          averageXInput *= 0.5;
    54.          averageYInput *= 0.5;
    55.          
    56.          rotationX += averageXInput;
    57.          rotationY += averageYInput;
    58.          
    59.          rotationX = ClampAngle (rotationX, minimumX, maximumX);
    60.          rotationY = ClampAngle (rotationY, minimumY, maximumY);
    61.          
    62.          var xQuaternion : Quaternion = Quaternion.AngleAxis (rotationX, Vector3.up);
    63.          var yQuaternion : Quaternion = Quaternion.AngleAxis (rotationY, Vector3.left);
    64.          
    65.          transform.localRotation = originalRotation * xQuaternion * yQuaternion;
    66.       }
    67.       else if (axes == RotationAxes.MouseX)
    68.       {
    69.          // Pass inputs to inputOlds first...
    70.          xInputOld=xInput;
    71.      
    72.          // Read the mouse input axis
    73.          xInput = Input.GetAxis("Mouse X") * sensitivityX;
    74.          
    75.          //Average new inputs with old
    76.          averageXInput = xInput + xInputOld;
    77.          averageXInput *= 0.5;
    78.          
    79.          rotationX += averageXInput;
    80.          rotationX = ClampAngle (rotationX, minimumX, maximumX);
    81.  
    82.          var xQuaternion : Quaternion = Quaternion.AngleAxis (rotationX, Vector3.up);
    83.          transform.localRotation = originalRotation * xQuaternion;
    84.       }
    85.       else
    86.       {
    87.          // Pass inputs to inputOlds first...
    88.          yInputOld=yInput;
    89.      
    90.          // Read the mouse input axis
    91.          yInput = Input.GetAxis("Mouse Y") * sensitivityY;
    92.          
    93.          //Average new inputs with old
    94.          averageYInput = yInput + yInputOld;
    95.          averageYInput *= 0.5;
    96.          
    97.          rotationY += averageYInput;
    98.          
    99.          rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
    100.          rotationY = ClampAngle (rotationY, minimumY, maximumY);
    101.  
    102.          var yQuaternion : Quaternion = Quaternion.AngleAxis (rotationY, Vector3.left);
    103.          transform.localRotation = originalRotation * yQuaternion;
    104.       }
    105.  
    106. }
    107.  
    108.  
    109.  
    110.  
    111. ////////////////////////////////////////
    112. ////////////////////////////////////////
    113.  
    114. function Start ()
    115. {
    116.     // Make the rigid body not change rotation
    117.     if (rigidbody)
    118.         rigidbody.freezeRotation = true;
    119.     originalRotation = transform.localRotation;
    120. }
    121.  
    122.  
    123. function ClampAngle (angle, min, max)
    124. {
    125.     if (angle < -360)
    126.         angle += 360;
    127.     if (angle > 360)
    128.         angle -= 360;
    129.     return Mathf.Clamp (angle, min, max);
    130. }
    131.  
    So cut me a break here guys, can anyone out there finally put this much asked question to rest? Or link me to the resources I need?
    If there's a post out there that's already cleared this up, it's impossible to find...

    Thanks for reading
     
  2. Ramen Sama

    Ramen Sama

    Joined:
    Mar 28, 2009
    Posts:
    561
    your error is cause you have a space in the variable name

    RotationAxes axis
     
  3. Fourthings

    Fourthings

    Joined:
    Feb 15, 2010
    Posts:
    313
    Thanks for your reply, and yeah the script is made up of bits of other code here and there, once I fixed that error I got these to new ones

    Code (csharp):
    1. Assets/MouseControl.js(28,5): BCE0089: Type 'MouseControl' already has a definition for 'rotationY'.
    2. Assets/MouseControl.js(28,5): BCE0089: Type 'MouseControl' already has a definition for 'rotationx'.
    3.  
    The problem here really is that I don't understand the process, I really need someone to explain it to me, as it's impossible to find info on how to attain a nice smooth fps controller for unity mouselook, at least in layman's terms anyway.
     
  4. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,398
    I think the main problem is that you have the code in FixedUpdate instead of Update.

    --Eric
     
  5. Fourthings

    Fourthings

    Joined:
    Feb 15, 2010
    Posts:
    313
    Hmm, well when I removed the Fixed part of the update function the two errors still remain, I read somewhere to always use Fixed updates with mouselook for smooth results.

    Again tho the problem here really is I don't understand the process, I'm kinda lost in this mess of info and code from all over the net. So I need someone to guide me through the process of creating a smooth fps mouselook. Such as Avert Fate.
     
  6. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,398
    Maybe you should just use the standard MouseLook script. If you use FixedUpdate, then the camera will only update some frames and not others, so naturally it won't look smooth. I'm not sure why anyone would have suggested otherwise.

    --Eric
     
  7. Fourthings

    Fourthings

    Joined:
    Feb 15, 2010
    Posts:
    313
    Well my original problem is that the standard mouselook is to jittery and choppy, you can't get fine smooth precise movement with it, as you would need for say long range sniping. So I figured I'd have to hack it up, so in order to do that in a way I somewhat I understand I found a js version of it, and then scathed the net literally all day looking for various methods on how to accomplish this, and ended up with this mutant script, that I barely understand.
     
  8. Fourthings

    Fourthings

    Joined:
    Feb 15, 2010
    Posts:
    313
    Can anyone even link me in the right direction?
     
  9. SoDoomed

    SoDoomed

    Joined:
    May 28, 2010
    Posts:
    6
  10. SoDoomed

    SoDoomed

    Joined:
    May 28, 2010
    Posts:
    6
    Turns out the smoother movement I felt was just a change in mouse sensitivity.

    Unity just defaults a bit high for me. So I went into Edit/project settings/input and changed the X and Y values from 0.1 to 0.02 (demo was at 0.009). That made a huge difference in how it feels wandering around the level, felt more like a traditional fps.

    So if that wasn't what you were asking, I have no idea.

    <-- Dumbass sorry
    :D
     
  11. Fourthings

    Fourthings

    Joined:
    Feb 15, 2010
    Posts:
    313
    What I ended up doing was storing the mouse rotation angles for 20 frames in an array and then averaging them and using the output average to drive the mouselook.

    Also, what I did was put this mouselook script on a sphere (could be an empty or whatever) and parent a cross hair to it.

    I put the camera in the same place as the sphere, wrote a script so the sphere and camera would always maintain the same transform. And put a smooth look at script on the camera, with the crosshair as the target.

    Oh yeah, there's an aim assist script in there too, when the crosshair passes over an object tagged Player the sensitivity slows down.

    There's the beginnings of a script for switching between 1st and 3rd person too

    The result is very smooth and natural feeling
    Here's the script
    Code (csharp):
    1.  
    2. public var sensitivityX : float = 2;        //Mouse look sensitivity
    3. public var sensitivityY : float = 2;
    4. public var defaultSensX : float = 2;        //Default mouse sensitivity
    5. public var defaultSensY : float = 2;
    6. public var aimSensitivityX : float = 0.3;   //Aim-assist sensitivity
    7. public var aimSensitivityY : float = 0.3;
    8.  
    9. //public var minimumX : float = -360;
    10. //public var maximumX : float = 360;
    11.  
    12. public var minimumY : float = -60;          //Minimum angle you can look up
    13. public var maximumY : float = 60;
    14.  
    15. public var aimFarthestPoint : int = 100;    //The farthest distance the aim-assist will function
    16. public var aimNearestPoint : int = 15;      //Closest distance the aim-assist will function
    17.  
    18. public var frameCounterX : int = 20;        //You can vary this in the Inspector if you want to
    19. public var frameCounterY : int = 20;        //for sharper/smoother mouselook feel
    20.  
    21. private var rotArrayX = new Array ();       //array of rotations to be averaged
    22. private var rotArrayY = new Array ();
    23.  
    24. private var rotationX : float = 0;          //Mouse roation input
    25. private var rotationY : float = 0;
    26.  
    27. private var xQuaternion : Quaternion;       //Used to calculate the roation of this object
    28. private var yQuaternion : Quaternion;
    29. private var originalRotation : Quaternion;
    30.  
    31. var camera1 : Camera;                       //Used for Switching between 1st/3rd person view
    32. var camera2 : Camera;
    33. /////
    34.  
    35. function Start ()
    36. {
    37.     Screen.lockCursor = true;
    38.     if (rigidbody) rigidbody.freezeRotation = true;
    39.         originalRotation = transform.localRotation;
    40. }
    41.  
    42. /////
    43.  
    44. function Update()
    45. {
    46. //If Button is pressed switch between 1st/3rd person view
    47.     if ( Input.GetKeyDown(KeyCode.C))
    48.     {
    49.         camera1.camera.enabled = true;
    50.         camera2.camera.enabled = false;
    51.     }
    52.     if ( Input.GetKeyDown(KeyCode.V))
    53.     {
    54.         camera1.camera.enabled = false;
    55.         camera2.camera.enabled = true;
    56.     }
    57. //Aim-assist: If Ray collides with object tagged Player within 15 and 100 units from this object
    58. //then lower aim sensitivity, else, don't
    59.     var hit : RaycastHit;
    60.     var fwd = transform.TransformDirection(Vector3.forward);
    61.    
    62.     if (Physics.Raycast(this.transform.position, fwd, hit, aimFarthestPoint))
    63.     {
    64.         if ((hit.collider.gameObject.tag =="Player")  (hit.distance >= aimNearestPoint))
    65.         {
    66.             sensitivityX = aimSensitivityX;
    67.             sensitivityY = aimSensitivityY;
    68.         }
    69.         else
    70.         { //If Ray hits an object not tagged Player, return to default
    71.             sensitivityX = defaultSensX;
    72.             sensitivityY = defaultSensY;
    73.         }
    74.     }   else
    75.     { //If Ray hits nothing return to default
    76.         sensitivityX = defaultSensX;
    77.         sensitivityY = defaultSensY;
    78.     }  
    79.  
    80. // Average rotationX for smooth mouselook
    81.     var rotAverageX : float = 0;
    82.    
    83.     rotationX += Input.GetAxis("Mouse X") * sensitivityX;
    84.    
    85.     //Add the current rotation to the array, at the last position
    86.     rotArrayX[rotArrayX.length] = rotationX;
    87.  
    88.     //Reached max number of steps?  Remove the oldest rotation from the array
    89.     if (rotArrayX.length >= frameCounterX)
    90.     {
    91.         rotArrayX.RemoveAt(0);
    92.     }
    93.  
    94.     //Add all of these rotations together
    95.     for (var i_counterX = 0; i_counterX < rotArrayX.length; i_counterX++)
    96.     { //Loop through the array
    97.         rotAverageX += rotArrayX[i_counterX];
    98.     }
    99.  
    100.     //Now divide by the number of rotations by the number of elements to get the average
    101.     rotAverageX /= rotArrayX.length;
    102.    
    103. // Average rotationY, same process as above
    104.     var rotAverageY : float = 0;
    105.    
    106.     rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
    107.    
    108.     rotArrayY[rotArrayY.length] = rotationY;
    109.  
    110.     if (rotArrayY.length >= frameCounterY)
    111.     {
    112.         rotArrayY.RemoveAt(0);
    113.     }
    114.  
    115.     for (var i_counterY = 0; i_counterY < rotArrayY.length; i_counterY++)
    116.     {
    117.         rotAverageY += rotArrayY[i_counterY];
    118.     }
    119.     rotAverageY /= rotArrayY.length;
    120.    
    121. // Set Rotation Limits for horizontal (Not needed in our case)
    122.     //if ((rotAverageX >= -360)  (rotAverageX <= 360))
    123.     //{
    124.     //    rotAverageX = Mathf.Clamp (rotAverageX, minimumX, maximumX);
    125.     //}
    126.     //else if (rotAverageX < -360)
    127.     //{
    128.     //    rotAverageX = Mathf.Clamp (rotAverageX+360, minimumX, maximumX);
    129.     //}
    130.     //else
    131.     //{
    132.     //    rotAverageX = Mathf.Clamp (rotAverageX-360, minimumX, maximumX);
    133.     //}
    134.  
    135. // Set Rotation Limits for vertical    
    136.     if ((rotAverageY >= -360)  (rotAverageY <= 360))
    137.     {
    138.         rotAverageY = Mathf.Clamp (rotAverageY, minimumY, maximumY);
    139.     }
    140.     else if (rotAverageY < -360)
    141.     {
    142.         rotAverageY = Mathf.Clamp (rotAverageY+360, minimumY, maximumY);
    143.     }
    144.     else
    145.     {
    146.         rotAverageY = Mathf.Clamp (rotAverageY-360, minimumY, maximumY);
    147.     }
    148.  
    149. //Apply and rotate this object
    150.     xQuaternion = Quaternion.AngleAxis (rotAverageX, Vector3.up);
    151.     yQuaternion = Quaternion.AngleAxis (rotAverageY, Vector3.left);
    152.  
    153.     transform.localRotation = originalRotation * xQuaternion * yQuaternion;
    154. }
    155.  
    156.  
     
  12. asteins

    asteins

    Joined:
    Sep 21, 2010
    Posts:
    2
    Thanks a lot! Your solution was exactly what I was looking for.

    I applied it to the standard MouseLook script included in Unity's Standard Assets.

    Here it goes:

    SmoothMouseLook.cs

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. [AddComponentMenu("Camera-Control/Smooth Mouse Look")]
    6. public class SmoothMouseLook : MonoBehaviour {
    7.  
    8.     public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 }
    9.     public RotationAxes axes = RotationAxes.MouseXAndY;
    10.     public float sensitivityX = 15F;
    11.     public float sensitivityY = 15F;
    12.  
    13.     public float minimumX = -360F;
    14.     public float maximumX = 360F;
    15.  
    16.     public float minimumY = -60F;
    17.     public float maximumY = 60F;
    18.  
    19.     float rotationX = 0F;
    20.     float rotationY = 0F;
    21.    
    22.     private List<float> rotArrayX = new List<float>();
    23.     float rotAverageX = 0F;
    24.    
    25.     private List<float> rotArrayY = new List<float>();
    26.     float rotAverageY = 0F;
    27.    
    28.     public float frameCounter = 20;
    29.    
    30.     Quaternion originalRotation;
    31.  
    32.     void Update ()
    33.     {
    34.         if (axes == RotationAxes.MouseXAndY)
    35.         {          
    36.             rotAverageY = 0f;
    37.             rotAverageX = 0f;
    38.            
    39.             rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
    40.             rotationX += Input.GetAxis("Mouse X") * sensitivityX;
    41.            
    42.             rotArrayY.Add(rotationY);
    43.             rotArrayX.Add(rotationX);
    44.            
    45.             if (rotArrayY.Count >= frameCounter) {
    46.                 rotArrayY.RemoveAt(0);
    47.             }
    48.             if (rotArrayX.Count >= frameCounter) {
    49.                 rotArrayX.RemoveAt(0);
    50.             }
    51.            
    52.             for(int j = 0; j < rotArrayY.Count; j++) {
    53.                 rotAverageY += rotArrayY[j];
    54.             }
    55.             for(int i = 0; i < rotArrayX.Count; i++) {
    56.                 rotAverageX += rotArrayX[i];
    57.             }
    58.            
    59.             rotAverageY /= rotArrayY.Count;
    60.             rotAverageX /= rotArrayX.Count;
    61.            
    62.             rotAverageY = ClampAngle (rotAverageY, minimumY, maximumY);
    63.             rotAverageX = ClampAngle (rotAverageX, minimumX, maximumX);
    64.  
    65.             Quaternion yQuaternion = Quaternion.AngleAxis (rotAverageY, Vector3.left);
    66.             Quaternion xQuaternion = Quaternion.AngleAxis (rotAverageX, Vector3.up);
    67.            
    68.             transform.localRotation = originalRotation * xQuaternion * yQuaternion;
    69.         }
    70.         else if (axes == RotationAxes.MouseX)
    71.         {          
    72.             rotAverageX = 0f;
    73.            
    74.             rotationX += Input.GetAxis("Mouse X") * sensitivityX;
    75.            
    76.             rotArrayX.Add(rotationX);
    77.            
    78.             if (rotArrayX.Count >= frameCounter) {
    79.                 rotArrayX.RemoveAt(0);
    80.             }
    81.             for(int i = 0; i < rotArrayX.Count; i++) {
    82.                 rotAverageX += rotArrayX[i];
    83.             }
    84.             rotAverageX /= rotArrayX.Count;
    85.            
    86.             rotAverageX = ClampAngle (rotAverageX, minimumX, maximumX);
    87.  
    88.             Quaternion xQuaternion = Quaternion.AngleAxis (rotAverageX, Vector3.up);
    89.             transform.localRotation = originalRotation * xQuaternion;          
    90.         }
    91.         else
    92.         {          
    93.             rotAverageY = 0f;
    94.            
    95.             rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
    96.            
    97.             rotArrayY.Add(rotationY);
    98.            
    99.             if (rotArrayY.Count >= frameCounter) {
    100.                 rotArrayY.RemoveAt(0);
    101.             }
    102.             for(int j = 0; j < rotArrayY.Count; j++) {
    103.                 rotAverageY += rotArrayY[j];
    104.             }
    105.             rotAverageY /= rotArrayY.Count;
    106.            
    107.             rotAverageY = ClampAngle (rotAverageY, minimumY, maximumY);
    108.  
    109.             Quaternion yQuaternion = Quaternion.AngleAxis (rotAverageY, Vector3.left);
    110.             transform.localRotation = originalRotation * yQuaternion;
    111.         }
    112.     }
    113.    
    114.     void Start ()
    115.     {          
    116.         if (rigidbody)
    117.             rigidbody.freezeRotation = true;
    118.         originalRotation = transform.localRotation;
    119.     }
    120.    
    121.     public static float ClampAngle (float angle, float min, float max)
    122.     {
    123.         angle = angle % 360;
    124.         if ((angle >= -360F)  (angle <= 360F)) {
    125.             if (angle < -360F) {
    126.                 angle += 360F;
    127.             }
    128.             if (angle > 360F) {
    129.                 angle -= 360F;
    130.             }          
    131.         }
    132.         return Mathf.Clamp (angle, min, max);
    133.     }
    134. }
     
    Last edited: Oct 21, 2010
  13. ravsters

    ravsters

    Joined:
    Jan 18, 2008
    Posts:
    30
    Hey guys! So I'm trying to apply this to my game, BUT! It only allows me to look up and down. :eek: I suck at programming. I figured it would have been an east copy and paste.