Search Unity

orbit,pan,zoom in one script

Discussion in 'Scripting' started by aswinindra, May 30, 2008.

  1. aswinindra

    aswinindra

    Joined:
    Oct 24, 2007
    Posts:
    38
    Dear all,
    I try to figure out one of my user interface for my project. I would like to use mouse to :
    1. orbit - with mouse movement
    2. zoom - with mouse scroll
    3. pan - with mouse click-drag

    It's like Sketch-Up -UI if you familiar with.

    After combine some scripts in this forum, no.1 and 2 has been solved. No.3 always failed.
    Anyone has this experience? Any help is
    greatly appreciated.

    Thank you.
     
  2. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Something like:

    Code (csharp):
    1. var moveSpeed : float = .5;
    2.  
    3. function Update () {
    4.     if (Input.GetMouseButton(0)) {
    5.         transform.Translate(Vector3.right * -Input.GetAxis("Mouse X") * moveSpeed);
    6.         transform.Translate(transform.up * -Input.GetAxis("Mouse Y") * moveSpeed, Space.World);
    7.     }
    8. }
    --Eric
     
  3. aswinindra

    aswinindra

    Joined:
    Oct 24, 2007
    Posts:
    38
    Thanks Erich,
    But it still doesn't work. It seems that mouse movement and click_drag movement have the same effect : orbit movement. I want to disable click_drag from orbital movement. Is it possible?
     
  4. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Sure; you'd want to check for a mouse click and only allow the orbit code if there isn't one, probably like:

    Code (csharp):
    1.    if (Input.GetMouseButton(0)) {
    2.       // Pan code here
    3.    }
    4.    else {
    5.       // Orbit code here
    6.    }
    --Eric
     
  5. aswinindra

    aswinindra

    Joined:
    Oct 24, 2007
    Posts:
    38
    Thank you again,
    One little problem. Why after panning, camera goes back to original position?
    ( :oops: )
     
  6. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Probably some other code is making it do that. Post your script?

    --Eric
     
  7. aswinindra

    aswinindra

    Joined:
    Oct 24, 2007
    Posts:
    38
    Thanks again, this is the script : (sorry, it might look mess, but it works - at least, orbit and zoom)
    Code (csharp):
    1.  
    2. var target : Transform;
    3. var distance = 10.0;
    4. var xSpeed = 250.0;
    5. var ySpeed = 120.0;
    6. var yMinLimit = -20;
    7. var yMaxLimit = 80;
    8. var zoomRate = 2;
    9. var moveSpeed : float = 1;
    10.  
    11. private var x = 0.0;
    12. private var y = 0.0;
    13.  
    14. @script AddComponentMenu("Camera-Control/Mouse Orbit")
    15.  
    16. function Start () {
    17.     var angles = transform.eulerAngles;
    18.     x = angles.y;
    19.     y = angles.x;
    20. }
    21.    
    22. function LateUpdate () {
    23.     if (!Input.GetMouseButton(0)){
    24.                
    25.  
    26.     if (target) {
    27.         x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
    28.         y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
    29.        
    30.         distance += -(Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime) * zoomRate * Mathf.Abs(distance);
    31.      
    32.            
    33.         y = ClampAngle(y, yMinLimit, yMaxLimit);
    34.                
    35.         var rotation = Quaternion.Euler(y, x, 0);
    36.         var position = rotation * Vector3(0.0, 0.0, -distance) + target.position;
    37.        
    38.         transform.rotation = rotation;
    39.         transform.position = position;
    40.          
    41.     }
    42.    
    43. }
    44. }
    45.  
    46. function Update () {
    47.    if (Input.GetMouseButton(0)) {
    48.       transform.Translate(Vector3.right * -Input.GetAxis("Mouse X") * moveSpeed);
    49.       transform.Translate(transform.up * -Input.GetAxis("Mouse Y") * moveSpeed, Space.World);
    50.                  
    51.  
    52.     }
    53. }
    54.  
    55. static function ClampAngle (angle : float, min : float, max : float) {
    56.     if (angle < -360)
    57.         angle += 360;
    58.     if (angle > 360)
    59.         angle -= 360;
    60.     return Mathf.Clamp (angle, min, max);
    61. }
    62.  
     
  8. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Yeah, the orbit code is setting the position explicitly, so as soon as you let up on the mouse button and the orbit code takes over, it just puts everything back again. Probably the easiest thing to do at this point is to make two separate objects.

    First, remove the "var moveSpeed" line and the Update function from the script you posted. Replace the LateUpdate function with this:

    Code (csharp):
    1. var mover : Transform;
    2. function LateUpdate () {
    3.     if (!target) {return;}
    4.    
    5.     if (!Input.GetMouseButton(0)) {
    6.         x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
    7.         y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
    8.     }
    9.        
    10.     distance += -Input.GetAxis("Mouse ScrollWheel") * zoomRate * Mathf.Abs(distance);  
    11.     y = ClampAngle(y, yMinLimit, yMaxLimit);
    12.  
    13.     var rotation = Quaternion.Euler(y, x, 0);
    14.     var position = rotation * Vector3(0.0, 0.0, -distance) + target.position;
    15.    
    16.     transform.rotation = rotation;
    17.     transform.position = position + mover.position;  
    18. }
    Make a new empty GameObject in the scene, and call it Mover (or something). Make sure it's at position 0,0,0. Add this script to it:

    Code (csharp):
    1. var moveSpeed : float = 1;
    2. var cam : Transform;
    3.  
    4. function Update () {
    5.     if (Input.GetMouseButton(0)) {
    6.         transform.rotation = cam.rotation;
    7.         transform.Translate(Vector3.right * -Input.GetAxis("Mouse X") * moveSpeed);
    8.         transform.Translate(transform.up * -Input.GetAxis("Mouse Y") * moveSpeed, Space.World);
    9.     }
    10. }
    In the Inspector for the camera, drag the Mover object onto the Mover slot in your new script. In the Inspector for the Mover object, drag the camera onto the Cam slot in the script. That should do it.

    (I took out the * Time.deltaTime for the mousewheel code, because mouse axes, like movement and the wheel, are already framerate-independent, since they depend on how fast you move them. So multiplying by Time.deltaTime actually makes them framerate-dependent, ironically. Therefore you might need to adjust the ZoomRate variable.)

    --Eric
     
  9. aswinindra

    aswinindra

    Joined:
    Oct 24, 2007
    Posts:
    38
    Thank you Erich,

    It works like a charm. Just want to know, what is the difference between :
    Code (csharp):
    1.  if (!Input.GetMouseButton(0)) {
    and
    Code (csharp):
    1.  if (Input.GetMouseButton(0)) {
    Again, thank you.
     
  10. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    "!" means "not", so the first line means "If the left mouse button is not pressed".

    --Eric
     
  11. xemplifly

    xemplifly

    Joined:
    Nov 23, 2007
    Posts:
    27
    Sorry to bump this post.

    I'm having an issue with trying to rotate an object to the same y rotation as the camera. It seems to work for the first 180 degrees but starts to wander afterwards. Here's the edited code.

    Code (csharp):
    1.  
    2. var target : Transform;
    3. var mover : Transform;
    4. var distance = 10.0;
    5. var xSpeed = 250.0;
    6. var ySpeed = 120.0;
    7. var yMinLimit = -20;
    8. var yMaxLimit = 80;
    9. var zoomRate = 2;
    10. var minZoom = 4;
    11. var maxZoom = 100;
    12.  
    13. private var x = 0.0;
    14. private var y = 0.0;
    15.  
    16. @script AddComponentMenu("Camera-Control/Mouse Orbit")
    17.  
    18. function Start () {
    19.     var angles = transform.eulerAngles;
    20.     x = angles.y;
    21.     y = angles.x;
    22. }
    23.    
    24. function LateUpdate () {
    25.     if (!target) {return;}
    26.    
    27.     if (Input.GetMouseButton(1)) {
    28.         x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
    29.         y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
    30.     }
    31.        
    32.     distance += -Input.GetAxis("Mouse ScrollWheel") * zoomRate * Mathf.Abs(distance);
    33.     distance = Mathf.Clamp(distance, minZoom, maxZoom);
    34.    
    35.     y = ClampAngle(y, yMinLimit, yMaxLimit);
    36.    
    37.  
    38.     var rotation = Quaternion.Euler(y, x, 0);
    39.    
    40.     target.rotation.y = rotation.y;  //<<THIS IS WHERE I'M HAVING A PROBLEM<<
    41.    
    42.     var position = rotation * Vector3(0.0, 0.0, -distance) + target.position;
    43.  
    44.     transform.rotation = rotation;
    45.     transform.position = position + mover.position;  
    46. }
    47.  
    48. static function ClampAngle (angle : float, min : float, max : float) {
    49.    if (angle < -360)
    50.       angle += 360;
    51.    if (angle > 360)
    52.       angle -= 360;
    53.    return Mathf.Clamp (angle, min, max);
    54. }
    55.  
     
  12. wuwu

    wuwu

    Joined:
    Jun 17, 2008
    Posts:
    72
    Hello, im using this particular script for one of my cameras where the player is looking at a map right below it, i would like to be able to give a rotation/orbit on the Y axis and what happens is when I do such thing and zoom in via the middle mouse button, i can not pan around because when i pan around backwards my camera also tranforms on the Y axis as well.. :(

    what to do ? or did i explain it correctly>

    thanks
     
  13. lesfundi

    lesfundi

    Joined:
    Jan 10, 2009
    Posts:
    628
    aswinindra,


    could you post the 2 final script there? I am trying to get the pan to work. All the rest works.

    carl
     
  14. tobydog20

    tobydog20

    Joined:
    Jul 31, 2008
    Posts:
    71
    hey guys,

    I tried using the corrected script mentioned in the beginning posts of this thread, but can't seem to get them to work.

    I'm orbiting fine, but I think that's b/c of the existing MouseOrbit script.

    I have a game object that I want to the player to be able to zoom, orbit, and pan about.
    Then I have the following:

    Parent - First Person Controller
    has: rigidbody, Mouse Orbit script

    Child - Main Camera
    has: the corrected camera script from Eric and aswinindra, with the Mover object in the Mover slot; no target object

    Child - Mover
    has: the Mover script, with the Main Camera in the Cam slot

    I cannot get my scroll wheel to produce any results. I'm very new at this, so please excuse my ignorance. I plan on studying javascript beginning tomorrow, but thought I'd give it an amateurish shot.

    Meena :eek:
     
  15. davebuchhofer

    davebuchhofer

    Joined:
    Nov 9, 2007
    Posts:
    126
    Here's another version of a combined 'editor' type script modeled vaguely after the 3dsmax camera controls, taking parts from the Wow camera script at http://forum.unity3d.com/viewtopic.php?t=18073 and trimming out the collision detection

    Code (csharp):
    1.  
    2. //In a file MaxCamera.cs
    3. using UnityEngine;
    4. using System.Collections;
    5.  
    6. public class MaxCamera : MonoBehaviour
    7. {
    8.     public Transform target;
    9.  
    10.     public Vector3 targetOffset;
    11.     public float distance = 5.0f;
    12.  
    13.     public float maxDistance = 20;
    14.     public float minDistance = .6f;
    15.  
    16.     public float xSpeed = 200.0f;
    17.     public float ySpeed = 200.0f;
    18.  
    19.     public int yMinLimit = -80;
    20.     public int yMaxLimit = 80;
    21.  
    22.     public int zoomRate = 40;
    23.  
    24.     public float panSpeed = 0.3f;
    25.  
    26.     public float zoomDampening = 5.0f;
    27.  
    28.     private float xDeg = 0.0f;
    29.     private float yDeg = 0.0f;
    30.     private float currentDistance;
    31.     private float desiredDistance;
    32.  
    33.     void Start()
    34.     {
    35.         Vector3 angles = transform.eulerAngles;
    36.         xDeg = angles.x;
    37.         yDeg = angles.y;
    38.  
    39.         currentDistance = distance;
    40.         desiredDistance = distance;
    41.     }
    42.  
    43.     /**
    44.      * Camera logic on LateUpdate to only update after all character movement logic has been handled.
    45.      */
    46.     void LateUpdate()
    47.     {
    48.         // Don't do anything if target is not defined
    49.         if (!target)
    50.             return;
    51.  
    52.         // If Control and Alt and Middle button? ZOOM!
    53.         if (Input.GetMouseButton(2)  Input.GetKey(KeyCode.LeftAlt)  Input.GetKey(KeyCode.LeftControl))
    54.         {
    55.             desiredDistance -= Input.GetAxis("Mouse Y") * Time.deltaTime * zoomRate*0.125f * Mathf.Abs(desiredDistance);
    56.         }
    57.         // If middle mouse and left alt are selected? ORBIT
    58.         else if (Input.GetMouseButton(2)  Input.GetKey(KeyCode.LeftAlt))
    59.         {
    60.             xDeg += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
    61.             yDeg -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
    62.         }
    63.         // otherwise if middle mouse is selected, we pan by way of transforming the target in screenspace
    64.         else if (Input.GetMouseButton(2))
    65.         {
    66.             //grab the rotation of the camera
    67.             target.rotation = transform.rotation;
    68.             target.Translate(Vector3.right * -Input.GetAxis("Mouse X") * panSpeed);
    69.             target.Translate(transform.up * -Input.GetAxis("Mouse Y") * panSpeed, Space.World);
    70.         }
    71.  
    72.         // affect the desired Zoom distance if we roll the scrollwheel
    73.         desiredDistance -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs(desiredDistance);
    74.  
    75.         //clamp the zoom min/max
    76.         desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
    77.  
    78.         //Clamp the vertical axis for the orbit
    79.         yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
    80.  
    81.         // set camera rotation
    82.         Quaternion rotation = Quaternion.Euler(yDeg, xDeg, 0);
    83.  
    84.         // For smoothing of the zoom, lerp distance
    85.         currentDistance = Mathf.Lerp(currentDistance, desiredDistance, Time.deltaTime * zoomDampening);
    86.  
    87.         // keep within legal limits
    88.         currentDistance = Mathf.Clamp(currentDistance, minDistance, maxDistance);
    89.  
    90.         // calculate position based on the new currentDistance
    91.         Vector3 position = target.position - (rotation * Vector3.forward * currentDistance + targetOffset);
    92.  
    93.         transform.rotation = rotation;
    94.         transform.position = position;
    95.     }
    96.  
    97.     private static float ClampAngle(float angle, float min, float max)
    98.     {
    99.         if (angle < -360)
    100.             angle += 360;
    101.         if (angle > 360)
    102.             angle -= 360;
    103.         return Mathf.Clamp(angle, min, max);
    104.     }
    105. }
    106.  
     
  16. tobydog20

    tobydog20

    Joined:
    Jul 31, 2008
    Posts:
    71
    Hi all,

    I've used a slight modification of the orbit/pan/zoom script posted by Eric5h5 and Aswinindra (using a Mover object as well) and am having some problems. In addition to using the mouse input buttons, I'd like to use GUI buttons to control the camera movements mentioned above (note - I've used the terms orbit and rotate interchangeably).

    The problem I'm having is twofold:

    1. Each time I switch to a different GUI button, the camera goes back to it's starting position for that specific GUI button. So for example, if I start rotating the game object using its GUI button, and then switch to the GUI pan button, the camera movement repositions to its panning beginning coordinates. But then if I go back to "rotate/orbit," the camera repositions itself where it left off last within the rotate movement before a different GUI button was pressed.

    2. If either the pan or the rotate GUI button is pressed, after I press the corresponding mouse button, the position of the camera changes slightly.

    My set up is similar to the posted scripts above, in that I've created a separate Mover game object with the following script attached to it:

    Code (csharp):
    1. var moveSpeed : float = 1;
    2. var cam : Transform;
    3.  
    4. function Update () {
    5.     //pan
    6.     if (Input.GetMouseButton(1)) {
    7.         transform.rotation = cam.rotation;
    8.         transform.Translate(Vector3.right * -Input.GetAxis("Mouse X") * moveSpeed);
    9.         transform.Translate(transform.up * -Input.GetAxis("Mouse Y") * moveSpeed, Space.World);
    10.     }
    11. }
    12.  
    and then the camera has this script attached to it:
    Code (csharp):
    1. var toolbarInt = 0;
    2. var toolbarStrings : String[] = ["Select","Rotate", "Zoom", "Pan"];
    3.  
    4.  
    5. function OnGUI () {
    6.    toolbarInt = GUI.Toolbar (Rect (20, 165, 180, 30), toolbarInt, toolbarStrings);
    7. }
    8.  
    9. var target : Transform;
    10. var distance = 10.0;
    11. var xSpeed = 250.0;
    12. var ySpeed = 120.0;
    13. var yMinLimit = -20;
    14. var yMaxLimit = 80;
    15. var zoomRate = 2;
    16.  
    17.  
    18. private var x = 0.0;
    19. private var y = 0.0;
    20.  
    21. @script AddComponentMenu("Camera-Control/Mouse Orbit")
    22.  
    23. function Start () {
    24.     var angles = transform.eulerAngles;
    25.     x = angles.y;
    26.     y = angles.x;
    27.    
    28.      if (rigidbody)
    29.      rigidbody.freezeRotation = true;
    30. }
    31.    
    32. var mover : Transform;
    33. function LateUpdate () {
    34.     if (toolbarStrings[toolbarInt] == "Select") {return;}
    35.    
    36.     if (toolbarStrings[toolbarInt] == "Rotate"  Input.GetMouseButton(0)) {
    37.        
    38.         x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
    39.         y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
    40.        
    41.         y = ClampAngle(y, yMinLimit, yMaxLimit);
    42.        
    43.        var rotation = Quaternion.Euler(y, x, 0);
    44.        var position = rotation * Vector3(0.0, 0.0, -distance) + target.position;
    45.        
    46.         transform.rotation = rotation;
    47.        transform.position = position;
    48.     }
    49.        
    50.     if (toolbarStrings[toolbarInt] == "Zoom") {
    51.        
    52.        x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
    53.         y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
    54.        
    55.        y = ClampAngle(y, yMinLimit, yMaxLimit);
    56.        
    57.        distance += -Input.GetAxis("Mouse ScrollWheel") * zoomRate * Mathf.Abs(distance);
    58.        
    59.        position = rotation * Vector3(0.0, 0.0, -distance) + target.position;
    60.        
    61.        transform.rotation = rotation;
    62.        transform.position = position;
    63.        
    64.    }
    65.      
    66.     if (toolbarStrings[toolbarInt] == "Pan"  Input.GetMouseButton(1)) {
    67.        
    68.        x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
    69.         y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
    70.        
    71.        y = ClampAngle(y, yMinLimit, yMaxLimit);
    72.        
    73.        position = rotation * Vector3(0.0, 0.0, -distance) + target.position;
    74.        
    75.        transform.rotation = rotation;
    76.        transform.position = position + mover.position;
    77.     }
    78. }
    79.  
    80. static function ClampAngle (angle : float, min : float, max : float) {
    81.    if (angle < -360)
    82.       angle += 360;
    83.    if (angle > 360)
    84.       angle -= 360;
    85.    return Mathf.Clamp (angle, min, max);
    86. }
    I would love it if somebody could help me or even guide me in a certain direction, but if you can't I understand... thanks so much in advance.
     
  17. davebuchhofer

    davebuchhofer

    Joined:
    Nov 9, 2007
    Posts:
    126
    Dont have much time to debug yours quite yet, but i had updated my version for a similar effect a while back and maybe it could help you. On second read, no.. it wont actually for you, but i like where you are going!

    Primary differences from previous posted version are: moved all the initializing of the variables to an "Init" function that is called anytime the script is enabled

    this gets rid of the jump when switching between orbit and another script..

    also added an option to automatically create the target if there isn't one supplied in the unity interface

    (Ex: Change views could be something like, disable maxcamera, delete temporary target (Maybe this should be in an OnDisable()), translate your camera, enable maxcamera)

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5.  
    6. [AddComponentMenu("Camera-Control/3dsMax Camera Style")]
    7. public class maxCamera : MonoBehaviour
    8. {
    9.     public Transform target;
    10.  
    11.     public Vector3 targetOffset;
    12.     public float distance = 5.0f;
    13.  
    14.     public float maxDistance = 20;
    15.     public float minDistance = .6f;
    16.  
    17.     public float xSpeed = 200.0f;
    18.     public float ySpeed = 200.0f;
    19.  
    20.     public int yMinLimit = -80;
    21.     public int yMaxLimit = 80;
    22.  
    23.     public int zoomRate = 40;
    24.  
    25.     public float panSpeed = 0.3f;
    26.  
    27.     public float zoomDampening = 5.0f;
    28.  
    29.     private float xDeg = 0.0f;
    30.     private float yDeg = 0.0f;
    31.     private float currentDistance;
    32.     private float desiredDistance;
    33.     private Quaternion currentRotation;
    34.     private Quaternion desiredRotation;
    35.     private Quaternion rotation;
    36.     private Vector3 position;
    37.  
    38.  
    39.     void Start() { Init(); }
    40.     void OnEnable() { Init(); }
    41.  
    42.     public void Init()
    43.     {
    44.         //If there is no target, create a temporary target at 'distance' from the cameras current viewpoint
    45.         if (!target)
    46.         {
    47.             GameObject go = new GameObject("Cam Target");
    48.             go.transform.position = transform.position + (transform.forward * distance);
    49.             target = go.transform;
    50.         }
    51.  
    52.         distance = Vector3.Distance(transform.position, target.position);
    53.         currentDistance = distance;
    54.         desiredDistance = distance;
    55.          
    56.          
    57.         //be sure to grab the current rotations as starting points.
    58.         position = transform.position;
    59.         rotation = transform.rotation;
    60.         currentRotation = transform.rotation;
    61.         desiredRotation = transform.rotation;
    62.        
    63.         xDeg = Vector3.Angle(Vector3.right, transform.right );
    64.         yDeg = Vector3.Angle(Vector3.up, transform.up );
    65.     }
    66.  
    67.     /*
    68.      * Camera logic on LateUpdate to only update after all character movement logic has been handled.
    69.      */
    70.     void LateUpdate()
    71.     {
    72.         // If Control and Alt and Middle button? ZOOM!
    73.         if (Input.GetMouseButton(2)  Input.GetKey(KeyCode.LeftAlt)  Input.GetKey(KeyCode.LeftControl))
    74.         {
    75.             desiredDistance -= Input.GetAxis("Mouse Y") * Time.deltaTime * zoomRate*0.125f * Mathf.Abs(desiredDistance);
    76.         }
    77.         // If middle mouse and left alt are selected? ORBIT
    78.         else if (Input.GetMouseButton(2)  Input.GetKey(KeyCode.LeftAlt))
    79.         {
    80.             xDeg += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
    81.             yDeg -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
    82.  
    83.             ////////OrbitAngle
    84.  
    85.             //Clamp the vertical axis for the orbit
    86.             yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
    87.             // set camera rotation
    88.             desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);
    89.             currentRotation = transform.rotation;
    90.            
    91.             rotation = Quaternion.Lerp(currentRotation, desiredRotation, Time.deltaTime * zoomDampening);
    92.             transform.rotation = rotation;
    93.         }
    94.         // otherwise if middle mouse is selected, we pan by way of transforming the target in screenspace
    95.         else if (Input.GetMouseButton(2))
    96.         {
    97.             //grab the rotation of the camera so we can move in a psuedo local XY space
    98.             target.rotation = transform.rotation;
    99.             target.Translate(Vector3.right * -Input.GetAxis("Mouse X") * panSpeed);
    100.             target.Translate(transform.up * -Input.GetAxis("Mouse Y") * panSpeed, Space.World);
    101.         }
    102.  
    103.  
    104.         ////////Orbit Position
    105.  
    106.         // affect the desired Zoom distance if we roll the scrollwheel
    107.         desiredDistance -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs(desiredDistance);
    108.         //clamp the zoom min/max
    109.         desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
    110.         // For smoothing of the zoom, lerp distance
    111.         currentDistance = Mathf.Lerp(currentDistance, desiredDistance, Time.deltaTime * zoomDampening);
    112.  
    113.         // calculate position based on the new currentDistance
    114.         position = target.position - (rotation * Vector3.forward * currentDistance + targetOffset);
    115.         transform.position = position;
    116.     }
    117.  
    118.     private static float ClampAngle(float angle, float min, float max)
    119.     {
    120.         if (angle < -360)
    121.             angle += 360;
    122.         if (angle > 360)
    123.             angle -= 360;
    124.         return Mathf.Clamp(angle, min, max);
    125.     }
    126. }
    127.  
    It doesn't feel quite perfect yet, i think i may adjust the mouse wheel zoom to move/dolly the target object when the desired distance gets near the minimum.. instead of shrinking the desired distance you end up with a finite ability to zoom in.

    Another thought or potential upgrade might be to build the initial orbit target by raycasting into the scene, and if there is a hit, use that depth to place the auto generated target

    that said, so far i like it better than any other publicly available one ;) please, lets tweak it up some more!
     
    gwan likes this.
  18. pipauwel

    pipauwel

    Joined:
    Feb 17, 2010
    Posts:
    1
    Hi,
    Panning functionality in this script does not work when i try it. I attached the script at http://www.unifycommunity.com/wiki/index.php?title=MouseOrbitZoom, which is the same as the one above, to my MainCamera and set the target to a simple Cube object. When trying to pan, the cube object is rotated once to match the rotation of the camera, but there is no visual padding. I changed the padding speed, but no noticeable effect...
    Any ideas about what i am doing wrong? Any help?

    Thank you in advance!
     
  19. Infinitewave

    Infinitewave

    Joined:
    Mar 22, 2010
    Posts:
    9
    Thanks for posting your original script aswinindra, and for your contribution to it Eric5h5. I'm really just a beginner with coding and just figured out how to do something on my own (that worked, haha) for the first time...and just had to share it!

    I wanted to be able to limit the amount the player could zoom out. I had a theory the following addition might do it:

    if(distance > 5)
    distance = 5;

    After first inserting it where I thought seemed a reasonable place I got an error. It seemed logical to me however, and I decided to at least try changing its location in the script. The following was the third spot I tried (and it worked!!!). It's really a great feeling to have one's thinking one is beginning to understand confirmed :~).

    var target : Transform;
    var distance = 5.0;
    var xSpeed = 250.0;
    var ySpeed = 120.0;
    var yMinLimit = -20;
    var yMaxLimit = 80;
    var zoomRate = 2;
    var moveSpeed : float = 1;

    private var x = 0.0;
    private var y = 0.0;

    @script AddComponentMenu("Camera-Control/Mouse Orbit")

    function Start () {
    var angles = transform.eulerAngles;
    x = angles.y;
    y = angles.x;
    }

    function LateUpdate () {
    if (!Input.GetMouseButton(0)){


    if (target) {
    x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
    y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;

    distance += -(Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime) * zoomRate * Mathf.Abs(distance);


    y = ClampAngle(y, yMinLimit, yMaxLimit);

    var rotation = Quaternion.Euler(y, x, 0);
    var position = rotation * Vector3(0.0, 0.0, -distance) + target.position;

    transform.rotation = rotation;
    transform.position = position;
    if(distance > 5)
    distance = 5;

    }

    }
    }

    function Update () {
    if (Input.GetMouseButton(0)) {
    transform.Translate(Vector3.right * -Input.GetAxis("Mouse X") * moveSpeed);
    transform.Translate(transform.up * -Input.GetAxis("Mouse Y") * moveSpeed, Space.World);





    }
    }

    static function ClampAngle (angle : float, min : float, max : float) {
    if (angle < -360)
    angle += 360;
    if (angle > 360)
    angle -= 360;
    return Mathf.Clamp (angle, min, max);

    }
     
  20. w1nterl0ng

    w1nterl0ng

    Joined:
    Jan 19, 2010
    Posts:
    32
    Hi, I am trying to modify this Camera to allow for "roll" on the Z Axis. I have tried a few things and they are not working. Does anyone have a suggestion?

    Thanks, Fred
     
  21. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    An easy way to isolate one axis in a camera script is to put the camera inside an empty parent object. In your case, you could use the parent for the main rotation, but then use the camera's local rotation inside the empty object to isolate the Z axis.
     
  22. w1nterl0ng

    w1nterl0ng

    Joined:
    Jan 19, 2010
    Posts:
    32
    @Andeeee Thanks for the reply and idea. I was heading down a different path and ran into an odd issue. The "Roll" portion of my script, CenterMouse + Left Control, is not Working when I Build+Run the app. It works in the editor when I preview the app.

    Here is my modified version.
    Thanks, Fred
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5.  
    6. [AddComponentMenu("Camera-Control/3dsMax Camera Style")]
    7. public class maxCamera : MonoBehaviour
    8. {
    9.     public Transform target;
    10.     public Vector3 targetOffset;
    11.     public float distance = 5.0f;
    12.     public float maxDistance = 40;
    13.     public float minDistance = 1.0f;
    14.     public float xSpeed = 200.0f;
    15.     public float ySpeed = 200.0f;
    16.     public float zSpeed = 200.0f;
    17.     public int yMinLimit = -90;
    18.     public int yMaxLimit = 90;
    19.     public int zoomRate = 40;
    20.     public float panSpeed = 0.3f;
    21.     public float zoomDampening = 5.0f;
    22.  
    23.     private float xDeg = 0.0f;
    24.     private float yDeg = 0.0f;
    25.     private float zDeg = 0.0f;
    26.     private float currentDistance;
    27.     private float desiredDistance;
    28.     private Quaternion currentRotation;
    29.     private Quaternion desiredRotation;
    30.     private Quaternion rotation;
    31.     private Vector3 position;
    32.  
    33.     void Start() { Init(); }
    34.     void OnEnable() { Init(); }
    35.  
    36.     public void Init()
    37.     {
    38.         //If there is no target, create a temporary target at 'distance' from the cameras current viewpoint
    39.         if (!target)
    40.         {
    41.             GameObject go = new GameObject("Cam Target");
    42.             go.transform.position = transform.position + (transform.forward * distance);
    43.             target = go.transform;
    44.         }
    45.  
    46.         distance = Vector3.Distance(transform.position, target.position);
    47.         currentDistance = distance;
    48.         desiredDistance = distance;
    49.                
    50.         //be sure to grab the current rotations as starting points.
    51.         position = transform.position;
    52.         rotation = transform.rotation;
    53.         currentRotation = transform.rotation;
    54.         desiredRotation = transform.rotation;
    55.        
    56.         xDeg = Vector3.Angle(Vector3.right, transform.right );
    57.         yDeg = Vector3.Angle(Vector3.up, transform.up );
    58.         //zDeg = Vector3.Angle(Vector3.forward, transform.forward );
    59.     }
    60.  
    61.     /*
    62.      * Camera logic on LateUpdate to only update after all character movement logic has been handled.
    63.      */
    64.     void LateUpdate()
    65.     {
    66.         // If Control and Alt and Middle button? ZOOM!
    67.         if (Input.GetMouseButton(2)  Input.GetKey(KeyCode.LeftAlt)  Input.GetKey(KeyCode.LeftControl))
    68.         {
    69.             desiredDistance -= Input.GetAxis("Mouse Y") * Time.deltaTime * zoomRate*0.125f * Mathf.Abs(desiredDistance);
    70.         }
    71.         // If middle mouse and left alt are selected? ORBIT
    72.         else if (Input.GetMouseButton(2)  Input.GetKey(KeyCode.LeftAlt))
    73.         {
    74.             xDeg += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
    75.             yDeg -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
    76.             ////////OrbitAngle
    77.  
    78.             //Clamp the vertical axis for the orbit
    79.             yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
    80.             // set camera rotation
    81.             desiredRotation = Quaternion.Euler(yDeg, xDeg, zDeg);
    82.             currentRotation = transform.rotation;
    83.            
    84.             rotation = Quaternion.Lerp(currentRotation, desiredRotation, Time.deltaTime * zoomDampening);
    85.             transform.rotation = rotation;
    86.         }
    87.         else if (Input.GetMouseButton(2)  Input.GetKey(KeyCode.LeftControl))
    88.         {
    89.             // this is where the roll will go.
    90.             zDeg += Input.GetAxis("Mouse X") * zSpeed * 0.02f;
    91.             desiredRotation = Quaternion.Euler(yDeg, xDeg, zDeg);
    92.             currentRotation = transform.rotation;
    93.            
    94.             rotation = Quaternion.Lerp(currentRotation, desiredRotation, Time.deltaTime * zoomDampening);
    95.             transform.rotation = rotation;
    96.         }
    97.         // otherwise if middle mouse is selected, we pan by way of transforming the target in screenspace
    98.         else if (Input.GetMouseButton(2))
    99.         {
    100.             //grab the rotation of the camera so we can move in a psuedo local XY space
    101.             target.rotation = transform.rotation;
    102.             target.Translate(Vector3.right * -Input.GetAxis("Mouse X") * panSpeed);
    103.             target.Translate(transform.up * -Input.GetAxis("Mouse Y") * panSpeed, Space.World);
    104.         }
    105.  
    106.         ////////Orbit Position
    107.  
    108.         // affect the desired Zoom distance if we roll the scrollwheel
    109.         desiredDistance -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs(desiredDistance);
    110.         //clamp the zoom min/max
    111.         desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
    112.         // For smoothing of the zoom, lerp distance
    113.         currentDistance = Mathf.Lerp(currentDistance, desiredDistance, Time.deltaTime * zoomDampening);
    114.  
    115.         // calculate position based on the new currentDistance
    116.         position = target.position - (rotation * Vector3.forward * currentDistance + targetOffset);
    117.         transform.position = position;
    118.  
    119.    
    120.         }
    121.  
    122.     private static float ClampAngle(float angle, float min, float max)
    123.     {
    124.         if (angle < -360)
    125.             angle += 360;
    126.         if (angle > 360)
    127.             angle -= 360;
    128.         return Mathf.Clamp(angle, min, max);
    129.     }
    130. }
    131.  
     
  23. MarkPixel

    MarkPixel

    Joined:
    Apr 15, 2010
    Posts:
    39
    this is my code so far:

    Code (csharp):
    1.  
    2. //
    3. //Filename: maxCamera.cs
    4. //
    5. // original: [url]http://www.unifycommunity.com/wiki/index.php?title=MouseOrbitZoom[/url]
    6. //
    7. // --01-18-2010 - create temporary temp, if none supplied at start
    8.  
    9. using UnityEngine;
    10. using System.Collections;
    11.  
    12.  
    13. [AddComponentMenu("Camera-Control/3dsMax Camera Style")]
    14. public class maxCamera_combined : MonoBehaviour
    15. {
    16.     //Meine
    17.     private bool tswitch = true;
    18.    
    19.     // Orbit
    20.     public Transform target;
    21.     // maxCamera
    22.     public Transform temp;
    23.     public Vector3 tempOffset;
    24.     public float distance = 5.0f;
    25.     public float maxDistance = 20;
    26.     public float minDistance = .6f;
    27.     public float xSpeed = 200.0f;
    28.     public float ySpeed = 200.0f;
    29.     public int yMinLimit = -80;
    30.     public int yMaxLimit = 80;
    31.     public int zoomRate = 40;
    32.     public float panSpeed = 0.3f;
    33.     public float zoomDampening = 5.0f;
    34.  
    35.     public float xDeg = 0.0f;
    36.     public float yDeg = 0.0f;
    37.     public float currentDistance;
    38.     public float desiredDistance;
    39.     private Quaternion currentRotation;
    40.     private Quaternion desiredRotation;
    41.     private Quaternion rotation;
    42.     private Vector3 position;
    43.  
    44.     void Start() { Init(); }
    45.     void OnEnable() { Init(); }
    46.  
    47.     public void Init()
    48.     {
    49.         //If there is no temp, create a temporary temp at 'distance' from the cameras current viewpoint
    50.         if (!temp)
    51.         {
    52.             GameObject go = new GameObject("Cam temp");
    53.             go.transform.position = transform.position + (transform.forward * distance);
    54.             temp = go.transform;
    55.         }
    56.  
    57.         distance = Vector3.Distance(transform.position, temp.position);
    58.         currentDistance = distance;
    59.         desiredDistance = distance;
    60.                
    61.         //be sure to grab the current rotations as starting points.
    62.         position = transform.position;
    63.         rotation = transform.rotation;
    64.         currentRotation = transform.rotation;
    65.         desiredRotation = transform.rotation;
    66.        
    67.         xDeg = Vector3.Angle(Vector3.right, transform.right );
    68.         yDeg = Vector3.Angle(Vector3.up, transform.up );
    69.     }
    70.  
    71.     /*
    72.      * Camera logic on LateUpdate to only update after all character movement logic has been handled.
    73.      */
    74.     void LateUpdate()
    75.     {
    76.         if (Input.GetKeyDown("b")) { //LOCAL OFF
    77.             tswitch = false;
    78.        
    79.            
    80.             //Change camera position to target, BUT HOW????
    81.  
    82.  
    83.            
    84.  
    85.            
    86.            
    87.             }
    88.         if (Input.GetKeyDown("v")) {
    89.             tswitch = true;
    90.            
    91.             // Sets temp-position in front of cam
    92.             temp.transform.position = transform.position + (transform.forward * desiredDistance);  
    93.         }
    94.        
    95.         if (tswitch) {
    96.        
    97.         // If Control and Alt and Middle button? ZOOM!
    98.         if (Input.GetMouseButton(2)  Input.GetKey(KeyCode.LeftAlt)  Input.GetKey(KeyCode.LeftControl))
    99.         {
    100.             desiredDistance -= Input.GetAxis("Mouse Y") * Time.deltaTime * zoomRate*0.125f * Mathf.Abs(desiredDistance);
    101.         }
    102.         // If middle mouse and left alt are selected? ORBIT
    103.         else if (Input.GetMouseButton(2)  Input.GetKey(KeyCode.LeftAlt))
    104.         {
    105.             xDeg += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
    106.             yDeg -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
    107.  
    108.             ////////OrbitAngle
    109.  
    110.             //Clamp the vertical axis for the orbit
    111.             yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
    112.             // set camera rotation
    113.             desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);
    114.             currentRotation = transform.rotation;
    115.            
    116.             rotation = Quaternion.Lerp(currentRotation, desiredRotation, Time.deltaTime * zoomDampening);
    117.             transform.rotation = rotation;
    118.         }
    119.         // otherwise if middle mouse is selected, we pan by way of transforming the temp in screenspace
    120.         else if (Input.GetMouseButton(2))
    121.         {
    122.             //grab the rotation of the camera so we can move in a psuedo local XY space
    123.             temp.rotation = transform.rotation;
    124.             temp.Translate(Vector3.right * -Input.GetAxis("Mouse X") * panSpeed); // these move temp
    125.             temp.Translate(transform.up * -Input.GetAxis("Mouse Y") * panSpeed, Space.World);
    126.         }
    127.  
    128.         ////////Orbit Position
    129.  
    130.         // affect the desired Zoom distance if we roll the scrollwheel
    131.         desiredDistance -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs(desiredDistance);
    132.         //clamp the zoom min/max
    133.         desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
    134.         // For smoothing of the zoom, lerp distance
    135.         currentDistance = Mathf.Lerp(currentDistance, desiredDistance, Time.deltaTime * zoomDampening);
    136.  
    137.         // calculate position based on the new currentDistance
    138.         position = temp.position - (rotation * Vector3.forward * currentDistance + tempOffset);
    139.         transform.position = position;
    140.     }
    141.  
    142.     if (!tswitch) {
    143.  
    144.  
    145.         xDeg += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
    146.         yDeg -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
    147.         yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
    148.                
    149.  
    150.        desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);
    151.        
    152.          
    153.         //position = rotation * Vector3(0.0f, 0.0f, -distance) + target.position;  
    154.         currentRotation = transform.rotation; // if this is off, cam wiggles
    155.         rotation = Quaternion.Lerp(currentRotation, desiredRotation, Time.deltaTime * zoomDampening);
    156.  
    157.         // affect the desired Zoom distance if we roll the scrollwheel
    158.         desiredDistance -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs(desiredDistance);
    159.         //clamp the zoom min/max
    160.         desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
    161.         // For smoothing of the zoom, lerp distance
    162.         currentDistance = Mathf.Lerp(currentDistance, desiredDistance, Time.deltaTime * zoomDampening);
    163.        
    164.         //Important for Zoom!!!
    165.         position = target.position - (rotation * Vector3.forward * currentDistance);
    166.         //PROBLEM at switch from V to B
    167.  
    168.        
    169.         transform.rotation = rotation;
    170.         transform.position = position;
    171.        
    172.        
    173.  
    174.     }  
    175.    
    176.  
    177. }
    178.  
    179.     private static float ClampAngle(float angle, float min, float max)
    180.     {
    181.         if (angle < -360)
    182.             angle += 360;
    183.         if (angle > 360)
    184.             angle -= 360;
    185.         return Mathf.Clamp(angle, min, max);
    186.     }
    187. }
    188.  
    you have to switch between local-and global-mode via V and B.

    there are still two issues (or one??) left:
    1. the cam changes its position
    2. it doesnot stay at its position and changes its view (rotation) from 'temp' to 'target'



    maybe anyone can help?
     
  24. Zante

    Zante

    Joined:
    Mar 29, 2008
    Posts:
    429
    How do you rotate around the target with these scripts.
     
  25. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
  26. webco

    webco

    Joined:
    Sep 2, 2010
    Posts:
    85
    Hello, I use the same script (found here), but the pan doesn't work. Something is wrong, but I don't know what. Can you help me please ?
     
  27. jzq740176597

    jzq740176597

    Joined:
    Jul 31, 2015
    Posts:
    17
    @MarkPixel
    You Code is worked! test in unity 5.2.2f1.thanks!
     
  28. Stromerz

    Stromerz

    Joined:
    Jan 25, 2018
    Posts:
    13
    Hello, guys, I was trying to make this code work with touch but can't figure out yet, can you guys help me, Thanks in advance
     
  29. deaa86_arch

    deaa86_arch

    Joined:
    Mar 1, 2022
    Posts:
    5
    I have created a video that shows how to use Unity script to orbit, pan and zoom the camera to the mouse position.
     
  30. bouaraourkhaled

    bouaraourkhaled

    Joined:
    Aug 15, 2022
    Posts:
    1
    can you give us the script please