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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Moving the camera smoothly

Discussion in 'Scripting' started by ericspataru, Apr 4, 2017.

  1. ericspataru

    ericspataru

    Joined:
    Jan 31, 2017
    Posts:
    54
    First and foremost, I know that this question seems to have been asked previously, but it hasn't been answered. At least, not in the manner I wanted it to be..

    I have a camera high up in the sky at the beginning of the game. After pressing the End Turn Button, I want to rotate its X axis with 15 degrees (down) and then modify its Y transform position from 12 to 3. But I want all these to be smooth. I know that what I want is somehow related to Time.deltaTime or the so-called Lerp function, but I couldn't understand anything from the previous answers. Can someone explain all these for dummies? To make it more simple, I already know the moment the player presses the End Turn Button.

    Code (CSharp):
    1.  public void applyClick()
    2.     {
    3.         Click = true;
    4.     }
    5.  
    6.     void Update () {
    7.      
    8.         if (Click == true && playerTurn == 0) {
    9.             playerTurn = 1;
    10.             Click = false;
    11.  
    12.             //mainCam.transform.Rotate (new Vector3 (15f, 0f, 0f) * Time.deltaTime); }
    13.  
    14.  
    The function applyClick is called at On Click property of the inspector, so the EndTurn Button clicking is not the problem. The problem is how do I make the camera do this (15 degrees rotating over its x axis and then going downwards with 10 units) in like 3 or 4 seconds. Please, have mercy and explain it as if I were the biggest dummy you've ever seen. Thanks a lot for your time!
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,748
    I'll give you a handy snippet that I think you'll find useful:
    Code (csharp):
    1.  
    2.   void Update () {
    3.    
    4. if (Click == true && playerTurn == 0) {
    5. playerTurn = 1;
    6. Click = false;
    7. StartCoroutine(LerpFromTo(transform.position, newDesiredPosition, 1f) );
    8. }
    9. }
    10.  
    11. IEnumerator LerpFromTo(Vector3 pos1, Vector3 pos2, float duration) {
    12. for (float t=0f; t<duration; t += Time.deltaTime) {
    13. transform.position = Vector3.Lerp(pos1, pos2, t / duration);
    14. yield return 0;
    15. }
    16. transform.position = pos2;
    17. }
    The for loop at the end there is extremely handy in many, many situations like this. You can use any Lerp function (or in the case of rotations, Slerp) there in exactly the same way, and smoothly transition from one value to the other value over a given duration.

    Adding in the rotation to that function is left as an exercise for the reader. Let me know if you need more help :)
     
  3. ericspataru

    ericspataru

    Joined:
    Jan 31, 2017
    Posts:
    54
    Thanks for your answer, I will try it as soon as I get home.
    but one question: what can I change from the code?

    the variables from coroutine and the duration? if so, for duration do i use 3 for 3 seconds or 3 for 3 minutes?
     
  4. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,748
    I mean, change whatever you want to change ;) But most likely, you'll want to leave the for statement line intact at least.

    duration is measured in seconds.
     
    ericspataru likes this.
  5. ericspataru

    ericspataru

    Joined:
    Jan 31, 2017
    Posts:
    54
    I'm impressed! It worked! The only thing I added is that this script was not attached to the camera and I declared it as a game object and then used it as mainCam.transform.position..

    I have one more question, what can I do if I also want to rotate it? (also smoothly)
     
  6. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,748
    You'll need to add "from" and "to" Quaternion parameters to that function, and set the rotation alongside the setting of transform.position.
     
    ericspataru likes this.
  7. joshmond

    joshmond

    Joined:
    May 28, 2012
    Posts:
    34
    Rather than using Lerp you could also try using MoveTowards() or SmoothDamp() for the movement. The advantage to using either of those over Lerp is they don't slow down as the camera approaches the end target position. You could try putting your logic in LateUpdate as well which is recommended for camera movement.

    Hope that helps

    -Joshmond
     
    ericspataru likes this.
  8. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,748
    Incorrect. What you're saying would apply if Lerp was being used with a constant as the third parameter with a first parameter that moves, such as:
    Code (csharp):
    1. transform.position = Vector3.Lerp(transform.position, targetPosition, 0.1f);
    But in the code example provided, the third parameter changes, while the first parameter is set at the start and remains constant until the end. This code will make it move linearly.
     
    ericspataru likes this.
  9. ericspataru

    ericspataru

    Joined:
    Jan 31, 2017
    Posts:
    54
    I tried this but I do not fully understand what you're saying due to the fact that I don't even know what Quaternion is. I just use it when spawning an object

    Code (CSharp):
    1. mainCam.transform.rotation = Quaternion.Slerp(from.rotation, to.rotation, Time.deltaTime * speed);
    EDIT: I also put from empty game object in the scene and set its rotation X at -15 and put to game object in the scene and set its rotation X at 15. I dragged and dropped them onto the script, but now if I run, after clicking the button, it only rotates it 0,0121 deegres, or one random value between 0,0001 and 0,01..

    EDIT2: I looked up for Quaternion in the documentation and it seems to tell me the rotation of an gameobject using the Quaternion.identity (it's read-only). So if I go ahead and set Quaternion.identity as a new parameter and then write a transform.Rotate = something, will it work?
     
    Last edited: Apr 5, 2017
  10. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,748
    A Quaternion is just like a Vector3, but for rotations instead of positions. Quaternion.identity is one (neutral/non-rotated) value of that type, just like Vector3.zero is (0, 0, 0).

    The function with rotations added to it might look like:
    Code (csharp):
    1.  
    2. IEnumerator LerpFromTo(Vector3 pos1, Vector3 pos2, Quaternion rot1, Quaternion rot2, float duration) {
    3. for (float t=0f; t<duration; t += Time.deltaTime) {
    4. transform.position = Vector3.Lerp(pos1, pos2, t / duration);
    5. transform.rotation = Quaternion.Slerp(rot1, rot2, t / duration);
    6. yield return 0;
    7. }
    8. transform.position = pos2;
    9. transform.rotation = rot2;
    10. }
     
    ericspataru likes this.
  11. ericspataru

    ericspataru

    Joined:
    Jan 31, 2017
    Posts:
    54
    It worked perfectly. I have some other couple of bugs, but I think that I can solve the rest alone. Thanks a lot again, @StarManta
     
  12. LeGingerGamer

    LeGingerGamer

    Joined:
    Jan 13, 2017
    Posts:
    4
    In case anyone comes on here and wants a nice clean answer.
    Put this block of code into your script if you want to lerp one object to another location over a given amount of time. It's just a nice handy function that I've reused for years.
    Code (CSharp):
    1.  public IEnumerator MoveCameraToPosition(Transform _cameraToMove, Transform _locationToMoveTo, float _timeToMove)
    2.     {
    3.         Vector3 currentPos = _cameraToMove.transform.position;
    4.         float t = 0f;
    5.  
    6.         while (t < 1)
    7.         {
    8.             t += Time.deltaTime / _timeToMove;
    9.             _cameraToMove.transform.position = Vector3.Lerp(currentPos, _locationToMoveTo.position, t);
    10.             if (t > 0.8f)
    11.                 currentlyFollowing = _locationToMoveTo;
    12.             yield return null;
    13.          
    14.  
    15.         }
    16.     }
    This way you can reuse it for literally any object :)
    Rotation works just the same, add a line referencing the current Rotation in a vector 3, then get the rotation of the location you're going to, then lerp in the same manner :)
     
  13. gymfrecklelaundry

    gymfrecklelaundry

    Joined:
    Aug 20, 2020
    Posts:
    3
    currentlyFollowing is undefined
     
  14. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Then define it. It is of type Transform, and from the name it obviously needs to be set to the Transform you want the camera to follow.
     
  15. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    You helped me thanks.However i have problem with my ui and cant find why do you guys have some ideas?
    https://gifyu.com/image/5Q98

    fyi my UI is not child of map camera so i think is shouldt move
     
    Last edited: May 6, 2021