Home > Software design >  Why does an object fly down at high speed when using Vector2.Lerp?
Why does an object fly down at high speed when using Vector2.Lerp?

Time:09-28

When I try to use Vector2.Lerp in unity, I run into a problem. The object flies downwards at a very high speed.

I am trying to make a moving platform in a 2D game. It moves from minimum x value to maximum x value. I want to use Vector2.Lerp to make the speed in both directions the same, but when I apply transform.Translate, and pass Vector2.Lerp as argument, the object flies down with very high speed.

That's the problem, because when I pass in Vector 3 with coordinates divided by 100, everything works fine. But different speeds appear in different directions.

The object has a box collider 2D and a script that moves it. It has no rigidbody 2D.

What am I doing wrong?

Here's my function that moves the object in one direction (it's called in FixedUpdate):

Vector2 target = new Vector3(xMin, 0);

Vector2 moving = Vector2.Lerp(transform.position, target, speed * Time.fixedDeltaTime);

transform.Translate(moving);

CodePudding user response:

Lerp(a, b, t) interpolates between a and b.

t must be in the range [0,1], so that Lerp(a, b, 0) = a and Lerp(a, b, 1) = b. Using speed * Time.fixedDeltaTime in the place of t doesn't make sense.

If you want to move your object from a to b with a constant speed of speed (units per second), you can do:

IEnumerator Move(Vector2 a, Vector2 b, float speed){
    float movementDuration = Vector2.Distance(a, b) / speed;
    for(float t = 0; t < 1; t  = Time.deltaTime / movementDuration){
        transform.position = Vector2.Lerp(a, b, t);
        yield return null;
    }
    transform.position = b;
}

And you can call this method using StartCoroutine(Move(a, b, speed));

Be careful not to call this every frame. Call only once and see what happens.

CodePudding user response:

As explained here Lerp interpolates linear from the given start value to he target value using a relative factor from 0 to 1.

You can go with a Coroutine but would need to start it and make sure it is running only once at a time.

Or if you simply want to continuously move towards the target you would want to rather use

private void Update()
{
    transform.position = Vector2.MoveTowards(transform.position, new Vector2(xMin, 0), speed * Time.deltaTime);
}

Another note for your usecase: If you use Rigibody/Rigidbody2D or any other component form the physics engines you do not want to move anything via Transform as this breaks with the physics, usually looks weird and breaks collision detection etc.

You rather want to go though the according component - in your case e.g.

[SerializeField] private Rigidbody2D _rigidbody;

pivate void Awake()
{
    if(!_rigidbody) _rigidbody = GetComponent<Rigidbody2D>();
}

private void FixedUpdate()
{
    var position = Vector2.MoveTowards(_rigidbody.position, new Vector2(xMin, 0), speed * Time.deltaTime);
    _rigidbody.MovePosition(position);
}
  • Related