Vector3.Lerp is not working

2019-09-15 07:16发布

问题:

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);
        }
    }
}

回答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.



回答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



回答3:

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());



标签: c# unity3d lerp