1

I'm trying to smoothly move from my current position to a new position that I've hard coded but even using the Vector3.Lerp and Vector3.MoveTowards it's just moving the player normally without any delay effect.

I have also tried to add Time.deltaTime in the Vector3.Lerp method but it's just moving the player tiny bit. I just want the player to smoothly move towards the set position.

I'm new to Unity and any help would be highly appreciated.

public class PlayerControl : MonoBehaviour {
    //change position
    private float leftX = -1.65f;
    private float leftY = 0.00f;
    private float rightX = -1.00f;
    private float rightY = -1.13f;

    private Vector3 carPosition;
    private float slowTime = 2f;

    void Start () {
        //set the player to its current position
        carPosition = transform.position;
    }

    void Update () {
        //control the player
        if (Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0)) {
            Debug.Log("Pressed!");

            if(transform.position.y <= -0.5) {
                carPosition.x = leftX;
                carPosition.y = leftY;
            }

            if(transform.position.y >= 0) {
                carPosition.x = rightX;
                carPosition.y = rightY;
            }

            //transform.position = carPosition;
            transform.position = Vector3.Lerp(transform.position, carPosition, slowTime);
        }
    }
}
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
pijushmandal
  • 13
  • 1
  • 3

3 Answers3

2

Your mistake is here:

transform.position = Vector3.Lerp(transform.position, carPosition, slowTime);

Dont use transfrom.position as a parameter. Use some startPosition variable as in

transform.position = Vector3.Lerp(startPosition, carPosition, slowTime);

Also slowTime should be a fraction of the distance traveled clamped to [0, 1]. When you put 2f there you are instantly moved to the finish. Put 0.5f there to see what I am talking about.

Please Check: https://docs.unity3d.com/ScriptReference/Vector3.Lerp.html

Łukasz Motyczka
  • 1,169
  • 2
  • 13
  • 35
  • The startPosition is same as transform.position, the game works like this; when I pressed the key it switches to a different position and also interchanges between the two provided position as I press the key again.I also tried slowTime = 0.5f but it just doesn't reach the desired position and if I set the value of slowTime to more than 1f the result is same it's too quick. – pijushmandal Mar 05 '17 at 18:59
  • @Łukasz Motyczka if you use a fixed starting vector inside `Lerp`, then you need to update the step everytime you call it, otherwise the value returned will be always every `Lerp` call. It's in the code in the link you provided. – Galandil Mar 05 '17 at 20:24
1

Edit: re-wrote the answer to better explain how Lerp works.

Lerp works in a very simple way: let's call the parameters V1, V2 and perc - result = Vector3.Lerp(V1, V2, perc).

Let's say that V1 = (0,0,0), V2 = (1,0,0) and perc = 0,2f. With these fixed parameters, you get result = 0.2f or, in other words, you get a Vector3 nearer to V2, starting from V1, by the percentage perc.

Now, if you want to move an object from V1 to V2 with a fixed step, you need, every Update() call, to modify the parameter perc. For example, if you want to reach the destination in exactly 5 single steps, then you'll need to call Lerp 5 times using this sequence of perc: 0.2 - 0.4 - 0.6 - 0.8 - 1. You want to move the object using 10 steps? Then you use the sequence 0.1 - 0.2 - 0.3 etc, you get the idea.

But this way of doing things gives you a choppy animation, so you want to use the time passed to calculate how much is the perc parameter every Update (the example code is in the link provided by Lukasz) to get a smooth and linear movement from start to end.

So your class should look like this:

using UnityEngine;

public class PlayerControl : MonoBehaviour {    

    private float leftX = -1.65f;
    private float leftY = 0.00f;
    private float rightX = -1.00f;
    private float rightY = -1.13f;
    private float speed = 2f, startTime, totalDistance = 0f;
    private Vector3 carPosition, startPos;

    void Start () {
        carPosition = transform.position;
        startPos = carPosition;
    }

    void Update () {
        if (Input.GetKeyDown (KeyCode.Space) || Input.GetMouseButtonDown (0)) {
            Debug.Log ("Pressed!");
            startTime = Time.time;
            if (transform.position.y <= -0.5) {
                startPos = transform.position;
                carPosition.x = leftX;
                carPosition.y = leftY;
            }
            if (transform.position.y >= 0) {
                startPos = transform.position;
                carPosition.x = rightX;
                carPosition.y = rightY;
            }
            totalDistance = Vector3.Distance(startPos, carPosition);
        }
        if (startPos != carPosition) {
            float newPercentageBetweenVectors = (Time.time - startTime) * speed / totalDistance;
            transform.position = Vector3.Lerp (startPos, carPosition, newPercentageBetweenVectors);
        }
    }
}

The other way to use Lerp to move an object is to keep a fixed perc and use the position of the object as the first parameter. This will give you a logarithmic kind of movement, faster at start and slower the more you're near the destination, but be aware that you'll never reach it since it's an asymptote - this means that you'll need to check by yourself if the current position is near enough the final position by a specific distance, for example 10^-2, with code like this:

using UnityEngine;

public class PlayerControl : MonoBehaviour {

    private float leftX = -1.65f;
    private float leftY = 0.00f;
    private float rightX = -1.00f;
    private float rightY = -1.13f;
    private float speed = 2f, totalDistance;
    private Vector3 carPosition;

    void Start () {
        carPosition = transform.position;
    }

    void Update () {
        if (Input.GetKeyDown (KeyCode.Space) || Input.GetMouseButtonDown (0)) {
            Debug.Log ("Pressed!");
            if (transform.position.y <= -0.5) {
                carPosition.x = leftX;
                carPosition.y = leftY;
            }
            if (transform.position.y >= 0) {
                carPosition.x = rightX;
                carPosition.y = rightY;
            }
        }
        if (transform.position != carPosition) {
            transform.position = Vector3.Lerp (transform.position, carPosition, speed * Time.deltaTime);
            totalDistance = Vector3.Distance(transform.position, carPosition);
            if (totalDistance < Mathf.Pow(10,-2)) transform.position = carPosition;
        }
    }
}

The use of Time.deltaTime in this case isn't necessary, if you provide a low enough speed. This second use of Lerp is particularly indicated (and indeed widely used) for moving cameras towards a game object.

Galandil
  • 4,169
  • 1
  • 13
  • 24
  • Lerp isn't a single step towards towards a final position, if you want that behaviour use MoveTowards. – CaTs Mar 06 '17 at 00:24
  • True, I used the term step in an unappropriate way. I'll edit my answer to explain better how Lerp works. – Galandil Mar 06 '17 at 00:44
  • 1
    Thank you so much it works. As I'm new to Unity the Lerp concept was difficult to understand for my project and the answer you provided is up to the point but little advance for me but I understood the logic behind it. guess I need to learn a lot. your answer is really appreciated. – pijushmandal Mar 06 '17 at 05:39
0

This is the way I learned to do it:

Make a new Coroutine (IEnumerator Title){}.

Make a float called t. Assign its value to 0.

Make a while loop:

while(t < 1){

}

Type in "t += Time.deltaTime / speed

Do transform.position = Vector3.Lerp(transform.position, carPosition, t);

Do yield return null.

That's the way I learned it. Your finished code should be this:

IEnumerator Drive(){  
    float t = 0;  
    while(t < 1){    
         t += Time.deltaTime / speed;    
         transform.position = Vector3.Lerp(transform.position, carPosition, t);  
         yield return null;     
    }  
}

And remember to start the Coroutine, too. (StartCoroutine(Drive());

hardkoded
  • 18,915
  • 3
  • 52
  • 64