Search Unity

  1. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Let us know a bit about your interests, and if you'd like to become more directly involved. Take our survey!
    Dismiss Notice
  4. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  5. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

C# How to use Time.deltatime to move object smoothly

Discussion in 'Scripting' started by Shippety, Mar 5, 2015.

  1. Shippety

    Shippety

    Joined:
    May 9, 2014
    Posts:
    24
    In my script, I want a cube to move from one place to another whenever the player right clicks with his/her mouse. But with my current script, the object moves from one place to the next immediately, as if teleporting. How do I make it so it moves visibly, and smoothly, using Time.deltaTime whenever the player clicks something?

    Heres the current script:


    Code (CSharp):
    1.   public GameObject flashlightGameObject;
    2.  
    3.     // Use this for initialization
    4.     void Start () {
    5.  
    6.     }
    7.  
    8.     // Update is called once per frame
    9.     void Update () {
    10.     if (Input.GetKey (KeyCode.Mouse1))
    11.         {
    12.             flashlightGameObject.transform.localPosition = new Vector3 (0.26F, 0.35F, 0); //
    13.         }
    14.     else
    15.         {
    16.             flashlightGameObject.transform.localPosition = new Vector3 (0, 0, 0); //
    17.         }
    18.      }
    19.  
    20. }
     
  2. lineupthesky

    lineupthesky

    Joined:
    Jan 31, 2015
    Posts:
    92
    There are a lot of ways, but these two outrun the others in this kind of a case :

    • - Affecting Transform's Position
    • - Using Lerp, stands for linear interpolation.

    In your script, it immediately moves the objects because you "SET" their localPositions to some other values. Careful about that, you are not moving them or changing them, you are directly setting localPositions which causes them to move over only one frame, which is immediately for human eye.

    To achieve smooth transition, you should modify values over time, over frames.

    Code (CSharp):
    1. public Vector3 increaseValues = new Vector3(0.1f, 0.1f,0);
    2. public Vector3 targetPosition = new Vector3(0.26f, 0.35f,0);
    3.  
    4. void Update()
    5. {
    6.  
    7. if(Input.GetKey(KeyCode.Mouse1))
    8. {
    9. if(Vector3.Distance(targetPosition, transform.position) > 0.2f)
    10. transform.localPosition += increaseValues * Time.deltaTime;
    11. }
    12. else
    13. {
    14. if(Vector3.Distance(new Vector3(0,0,0), transform.position > 0.1f)
    15. transform.localPosition -= increaseValues * Time.deltaTime;
    16. }
    17.  
    18. }
    as you can see, I used Vector3.Distance as a condition. If I am pressing the button, if there is still distance more than 0.2 units between transform and the targetPosition, then move the transform until that distance. Move by the increaseValues, so each frame it will add 0.1 in x, 0.1 in y, to your position. Smoothed the movement and made it frame-independant by using Time.deltaTime

    But the code I've wrote above, is not that accurate. Since it is using Vector3.Distance, and directly affecting the transform values, there may be complications on higher speeds. The best way, which is also the most secure one, is using Lerp. Lerp stands for Linear Interpolation, and in Unity it can be found under the classes of Vector3 ( To affect Vector3 variables obviously), Quaternion, Mathf ( To affect float, int variables, maybe more. ), Color ( To affect color variables ) and more. It interpolates the value to the targeted value over time. So in your case, simple and not even optimized code would be :

    Code (CSharp):
    1. public Vector3 targetPosition = new Vector3(0.26f, 0.35f,0);
    2. public float speed;
    3.  
    4. void Update()
    5. {
    6. if(Input.GetKey(KeyCode.Mouse1))
    7. {
    8. transform.localPosition = Vector3.Lerp(transform.localPosition, targetPosition, Time.deltaTime * speed);
    9. }
    10. else{
    11. transform.localPosition = Vector3.Lerp(transform.localPosition, new Vector3(0,0,0), Time.deltaTime * speed);
    12. }
    13.  
    14. }
    Worst thing about this code, it is not optimized. Because it will always try to reach targetPosition no matter it has reached or not when holding the key, and it will try to reach to 0,0,0 position no matter it has reached or not when not holding the key. Eventhough you can put conditions to enable disable the lerp, like checking for distance again, the system will still be processing values because then it will be checking the "condition" you've created every frame. But of course, in your situation, it won't even cause a FPS drop, one single lerp is nothing. But keep in mind that, if you are going to build a complicated system over lerps, do not use them in Update, try Coroutines instead. Have a nice day :) !

    Cheers,
    Inan
     
    Last edited: Mar 5, 2015
    Thorlar and namlunoy like this.
  3. Shippety

    Shippety

    Joined:
    May 9, 2014
    Posts:
    24
    Thanks for the help Inan! I think your code should work, but when I use it the object in question spins around the player once I move the mouse. I have to questions that I think could fix this:
    1. Which mouse numbers correspond to the buttons? I meant for mouse2 to be the right click, but I may be wrong.
    2. I think the main problem is that the target position should be a local position. Is there a way to redeclare the variable so that it's refering to localspace?
     
  4. lineupthesky

    lineupthesky

    Joined:
    Jan 31, 2015
    Posts:
    92
    Mouse 2 is third button, Mouse 1 is the right click. Check over here.
    When you declera a variable, and use it to set the local place itself, it will be set in local place. That reference you are talking about, is done by writing "transform.localPosition" already. But seems like I missed a spot, I edited and fixed the code, it is supposed to be :

    Code (CSharp):
    1. transform.localPosition = Vector3.Lerp(transform.localPosition, targetPosition, Time.deltaTime * speed);
    Not this :

    Code (CSharp):
    1. transform.position = Vector3.Lerp(transform.localPosition, targetPosition, Time.deltaTime * speed);
    ( Also must be applied to the second line of lerp. )
     
  5. Shippety

    Shippety

    Joined:
    May 9, 2014
    Posts:
    24
    That did the trick perfectly! Thanks for the help!
     
  6. lineupthesky

    lineupthesky

    Joined:
    Jan 31, 2015
    Posts:
    92
    Always, remember to switch to Coroutines if you get deep into these things. Not necessary for now, but it won't hurt learning a few more tricks, try not to keep your Update function with too many workloads :). Have a nice day !
     
    Thorlar likes this.
  7. hradeli

    hradeli

    Joined:
    Apr 9, 2018
    Posts:
    1
    See this Video: ;)