Search Unity

Camera won't move after zoom

Discussion in 'Scripting' started by asdx, Jun 30, 2013.

  1. asdx

    asdx

    Joined:
    Jun 3, 2013
    Posts:
    18
    My head is already ready to burst so please help. I made my camera move with W, S, A and D keys for up, down, left and right and also zoom with the mouse wheel. Everything works except for one bug: I cannot move the camera immediately after zooming, it just moves a little and drags the camera back. It only allows me to move the camera after waiting about one second or so.. wtf:mad: processing speed or what?
    This is the code I used:
    Code (csharp):
    1.     private void Update ()
    2.     {
    3.        
    4.         ZoomCamera();
    5.         MoveCamera();
    6.        
    7.     }
    8.        private void MoveCamera()
    9.        {
    10.                 float x = Input.GetAxis("Horizontal") * Time.deltaTime * speed;
    11.         float y = Input.GetAxis("Vertical") * Time.deltaTime * speed;
    12.        
    13.         transform.Translate(x, y, 0);
    14.  
    15.         }
    16.    
    17.     private void ZoomCamera()
    18.     {
    19.         float moveY = Input.GetAxis("Mouse ScrollWheel");
    20.        
    21.        
    22.         if (moveY != 0)
    23.             zoomDestination = transform.position + (transform.forward * moveY) * zoomSpeed;
    24.        
    25.         if(zoomDestination != Vector3.zero  zoomDestination.y < zoomMaxY  zoomDestination.y > zoomMinY)
    26.         {
    27.             transform.position = Vector3.Lerp(transform.position, zoomDestination, zoomTime);
    28.            
    29.             if (transform.position == zoomDestination)
    30.                 zoomDestination = Vector3.zero;
    31.         }
    32.            
    33.        
    34.         if (transform.position.y > zoomMaxY)
    35.             transform.position = new Vector3(transform.position.x, zoomMaxY, transform.position.z);
    36.         if (transform.position.y < zoomMinY)
    37.             transform.position = new Vector3(transform.position.x, zoomMinY, transform.position.z);
    38.     }

    Please, please help

    EDIT: Sorry, here are the variables:

    Code (csharp):
    1.     public float zoomMaxY = 1;
    2.     public float zoomMinY = 1;
    3.     public float zoomSpeed = 0.05f;
    4.     public float zoomTime = 0.25f;
    5.     public Vector3 zoomDestination = Vector3.zero;
     
    Last edited: Jul 1, 2013
  2. gilley033

    gilley033

    Joined:
    Jul 10, 2012
    Posts:
    1,191
    Just a guess, but the problem might have to do with the Vector3.Lerp method call on line 27. More specifically, I'm thinking it has something to do with the zoomTime variable; what is this variable and how is it calculated? Actually, now that I am looking at your code again, I'm pretty sure you also don't want to use transform.position as the first variable in the Lerp method call. The lerp should have a fixed start and end for it's cycle. You have the end part fixed, but the start is constantly changing since you're reassigning transform.position each time.

    Those are just some ideas, not sure if they will help you. If you don't get it figured out by tomorrow I'll try running the code myself and see if I can't figure out what's going on for sure. In the mean time, take a look at the Vector3.Lerp method in the unity docs if you haven't already! There's an example on that page that uses distance rather than time as the third variable; maybe you could do the same.
     
  3. asdx

    asdx

    Joined:
    Jun 3, 2013
    Posts:
    18
    After looking at your suggestion I see that changing zoomTime to 1 the problem disappears. I only need to set my zoomSpeed so it won't go too fast/slow when zooming. The only thing I don't know is if it will zoom smoothly, but that will be a minor loss if it makes the main problem go away.
    So a big THANKS to you gilley033 for helping me out!
     
  4. gilley033

    gilley033

    Joined:
    Jul 10, 2012
    Posts:
    1,191
    I'm glad that helped, but I'm still not completely sure what you're wanting to do.

    The lerp function returns a position between two points, based on a start value, an end value, and an input value between 0 and 1. If the input value is 0, the start value (in this case transform.position) is returned, and if the input value is 1, the end value (in this case zoomDestination) is returned. A value between 0 or 1 returns a position between the start and end.

    So when you just set zoomTime to 1, you're telling the lerp to return zoomDestination. If that's all you want, then you can replace the lerp with this instead:
    Code (csharp):
    1. transform.position = zoomDestination;
    However, I am guessing you want to smoothly zoom the camera over a short amount of time, rather than instantaneously. With that in mind, I rewrote your script. I have tested this and it should work, however I am not positive if it will produce the result you're looking for. It basically just moves the camera forward or backward via the scroll wheel.

    Code (csharp):
    1. public float zoomAmount = 0.05f;
    2.     public float zoomSpeed = 10;
    3.     public float movementSpeed = 10f;
    4.    
    5.     private bool zoomInProcess = false;
    6.     private Vector3 zoomDestination = Vector3.zero;
    7.     private Vector3 zoomStart = Vector3.zero;
    8.     private float t;
    9.     private float lerpStepSize;
    10.     // Use this for initialization
    11.    
    12.     private void Start()
    13.     {
    14.         //The larger the zoomSpeed, the bigger the lerpStepSize, and thus the quicker the lerp
    15.         lerpStepSize = 1f - 1f/zoomSpeed;  
    16.        
    17.         if(lerpStepSize < 0f || Mathf.Approximately(0f, lerpStepSize))
    18.             lerpStepSize = .1f;
    19.         else if(lerpStepSize > 1f || Mathf.Approximately(1f, lerpStepSize))
    20.             lerpStepSize = 1f;
    21.     }
    22.    
    23.     private void Update ()
    24.     {
    25.         ZoomCamera();
    26.         MoveCamera();
    27.     }
    28.  
    29.     private void MoveCamera()
    30.     {
    31.         float x = Input.GetAxis("Horizontal") * Time.deltaTime * movementSpeed;
    32.         float y = Input.GetAxis("Vertical") * Time.deltaTime * movementSpeed;
    33.         transform.Translate(x, y, 0);
    34.     }
    35.  
    36.     private void ZoomCamera()
    37.     {
    38.         if(!zoomInProcess)
    39.         {
    40.             float moveY = Input.GetAxis("Mouse ScrollWheel");
    41.            
    42.             if(moveY != 0)
    43.             {
    44.                 zoomStart = transform.position;
    45.                 zoomDestination = transform.position + new Vector3(0f, 0f, moveY) * zoomAmount;
    46.                 zoomInProcess = true;
    47.                 t = 0f; //Reset lerpInterpolater back to 0
    48.                 Zoom(); //Start zooming immediately
    49.             }
    50.         }
    51.         else //Zoom in process so zoom!
    52.             Zoom();      
    53.     }
    54.    
    55.     private void Zoom()
    56.     {
    57.         t += lerpStepSize;
    58.        
    59.         //Tracks whether we should end the zooming after this method returns
    60.         bool timeToEndZoom = false;
    61.        
    62.         //Make sure t is not greater than 1, if it is, set it to 1 and set
    63.         //timeToEndZoom to true
    64.         if(t > 1f)
    65.         {
    66.             t = 1f;
    67.             timeToEndZoom = true;
    68.         }
    69.        
    70.         //Use lerp to alter the position of the camera
    71.         transform.position = Vector3.Lerp(zoomStart, zoomDestination, t);
    72.        
    73.         //If timeToEndZoom isn't already true, check if t == 1f.
    74.         //If it is, it's time to end the zoom
    75.         if(!timeToEndZoom  Mathf.Approximately(1f, t))
    76.             timeToEndZoom = false;
    77.        
    78.         //If it's time to end the zoom, set zoomInProcess to false
    79.         if(timeToEndZoom)
    80.             zoomInProcess = false;
    81.     }
    The code relating to minZoom and maxZoom was removed because I didn't know what it was being used for, but you can certainly add it back in if you want to. I used values of 100 for zoomAmount and zoomSpeed and that seemed to work well.

    Like I said, this will just move the camera forward and backward. If you're trying to zoom the camera without physically moving it, you may be interested in this page: http://answers.unity3d.com/questions/20693/camera-zoom-in-script.html

    Good luck!
     
  5. asdx

    asdx

    Joined:
    Jun 3, 2013
    Posts:
    18
    Thanks. Have been on a small vacation. Will try the code :)
     
  6. FredericRP

    FredericRP

    Joined:
    Jan 11, 2010
    Posts:
    79
    I think another problem you could have is that while the Zoom is in progress, the camera position is always reassigned by the zoom function. The code posted by gilley003 ends the zoom nicely so you will be able to move your camera after the zoom is done, but won't be able to move while it's in progress.
    I don't have the perfect solution but if you want to move and zoom at the same time, you could store the offset from the Input.GetAxis while zooming and use it in the Lerp function. When it's done, reset the offset.

    Code (csharp):
    1. public float zoomAmount = 0.05f;
    2.     public float zoomSpeed = 10;
    3.     public float movementSpeed = 10f;
    4.  
    5.     private bool zoomInProcess = false;
    6.     private Vector3 zoomDestination = Vector3.zero;
    7.     private Vector3 zoomStart = Vector3.zero;
    8.     private Vector3 zoomOffset = Vector3.zero;
    9.     private float t;
    10.     private float lerpStepSize;
    11.  
    12.     // Use this for initialization
    13.     private void Start()
    14.     {
    15.         //The larger the zoomSpeed, the bigger the lerpStepSize, and thus the quicker the lerp
    16.         lerpStepSize = 1f - 1f/zoomSpeed;  
    17.        
    18.         if(lerpStepSize < 0f || Mathf.Approximately(0f, lerpStepSize))
    19.             lerpStepSize = .1f;
    20.         else if(lerpStepSize > 1f || Mathf.Approximately(1f, lerpStepSize))
    21.             lerpStepSize = 1f;
    22.     }
    23.  
    24.     private void Update ()
    25.     {
    26.         ZoomCamera();
    27.         MoveCamera();
    28.     }
    29.  
    30.     private void MoveCamera()
    31.     {
    32.         float x = Input.GetAxis("Horizontal") * Time.deltaTime * movementSpeed;
    33.         float y = Input.GetAxis("Vertical") * Time.deltaTime * movementSpeed;
    34.         // Move immediately or store the offset to use with zoomDestination
    35.         if (!zoomInProcess)
    36.             transform.Translate(x, y, 0);
    37.         else
    38.              zoomOffset += new Vector3(x, y, 0);
    39.     }
    40.  
    41.     private void ZoomCamera()
    42.     {
    43.         if(!zoomInProcess)
    44.         {
    45.             float moveY = Input.GetAxis("Mouse ScrollWheel");
    46.  
    47.             if(moveY != 0)
    48.             {
    49.                 zoomStart = transform.position;
    50.                 zoomDestination = transform.position + new Vector3(0f, 0f, moveY) * zoomAmount;
    51.                 zoomInProcess = true;
    52.                 t = 0f; //Reset lerpInterpolater back to 0
    53.                 Zoom(); //Start zooming immediately
    54.             }
    55.         }
    56.         else //Zoom in process so zoom!
    57.             Zoom();      
    58.     }
    59.  
    60.     private void Zoom()
    61.     {
    62.         t += lerpStepSize;
    63.  
    64.         //Tracks whether we should end the zooming after this method returns
    65.         bool timeToEndZoom = false;
    66.  
    67.         //Make sure t is not greater than 1, if it is, set it to 1 and set
    68.         //timeToEndZoom to true
    69.         if(t > 1f)
    70.         {
    71.             t = 1f;
    72.             timeToEndZoom = true;
    73.         }
    74.  
    75.         //Use lerp to alter the position of the camera
    76.         transform.position = Vector3.Lerp(zoomStart, zoomDestination + zoomOffset, t);
    77.  
    78.         //If timeToEndZoom isn't already true, check if t == 1f.
    79.         //If it is, it's time to end the zoom
    80.         if(!timeToEndZoom  Mathf.Approximately(1f, t))
    81.             timeToEndZoom = false;
    82.  
    83.         //If it's time to end the zoom, set zoomInProcess to false, and reset offset
    84.         if(timeToEndZoom) {
    85.             zoomInProcess = false;
    86.             zoomOffset = Vector3.zero;
    87.         }
    88.     }