NoviKorisnikk
NoviKorisnikk

Reputation: 313

How to implement lerp for smooth movement

I want achieve moving object on x axis only with lerp to get smoothly movement.

this is picture what i need

enter image description here

I don't know how i can implement lerp to this code to get smooth movement between these values, it now works but it teleport the player and that is not smooth movement what i want to achieve

This is my working code that teleports player:

void Start()
{

}


void Update()
{
    if (Input.GetMouseButtonDown(0))
    {
        Vector3 desiredPos = new Vector3(transform.position.x + 1.5f, transform.position.y, transform.position.z);
        transform.position = desiredPos;
    }

    if (Input.GetMouseButtonDown(1))
    {
        Vector3 desiredPos = new Vector3(transform.position.x -1.5f, transform.position.y, transform.position.z);
        transform.position = desiredPos;
    }
}

I want to implement this but i don't understand how to do it .. When i put all code into update the player don't even move.. It only works for me when i copy paste all the code from docs, but how i can move the time from start method to update and always do the same to achieve to get smooth movement for player when going left and right i don't know really please help me guys..

This is the code that works but i don't know how to change it for my example..

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

Upvotes: 1

Views: 6001

Answers (2)

derHugo
derHugo

Reputation: 90639

There are multiple ways. I would not use Translate as this gives you little control here but rather e.g. MoveTowards which makes sure you have no over shooting at the end. Use this for a linear movement with a given moveSpeed:

// set move speed in Units/seconds in the Inspector
public float moveSpeed = 1f;

private Vector3 desiredPos;
private bool isMoving;

private void Update()
{
    if (!isMoving && Input.GetMouseButtonDown(0))
    {
        desiredPos = transform.position + Vector3.right * 1.5f;
        isMoving = true;
    }

    if (!isMoving && Input.GetMouseButtonDown(1))
    {
        desiredPos = transform.position - Vector3.right * 1.5f;
        isMoving = true;
    }

    if(isMoving)
    {
        transform.position = Vector3.MoveTowards(transform.position, desiredPos, moveSpeed * Time.deltaTime);

        // this == is true if the difference between both
        // vectors is smaller than 0.00001
        if(transform.position == desiredPos)
        {
            isMoving = false;

            // So in order to eliminate any remaining difference
            // make sure to set it to the correct target position
            transform.position = desiredPos;
        }
    }
}

Or as you asked use Vector3.Lerp like e.g.

// a factor between 0 and 1
[Range(0, 1)] public float lerpFactor;

...

transform.position = Vector3.Lerp(transform.position, desiredPos, lerpFactor);

lerpFactor has to be a value between 0 and 1 where in our case 0 would meen the object never moves and 1 it directly jumps to the target position. In other words the closer you set it to 0 the slower it will reach the target, the closer you set it to 1 the faster it will reach the target.

a lot of people do this to get "smooth" movements but what actually happens is e.g. if you set 0.5 for lerpFactor then every frame the object is placed in the middle between current position and target position.

That looks somehow smooth, moves very fast at the beginning and very very slow at the end ... but: It actually never really reaches the target position but just gets very slow.

For your case that is fine since anyway we compare the current and target position using == with a precision of 0.00001. One just has to have in mind how Lerp works.

But with this you won't have any control neither over the move speed nor the duration.


If you want overall more controll (as I do) I would recommend to use a Coroutine (it is not absolutely neccessary and you could do the same in Update as well but in my eyes Coroutines are better to maintain and keep track of).

Than you could also make a smooth eased-in and eased-out movement with an always fixed duration regardless how far the distance is

// set desired move duration in seconds
public float moveDuration = 1;

private bool isMoving;

privtae void Update()
{
    if (!isMoving && Input.GetMouseButtonDown(0))
    {
        StartCoroutine(transform.position + Vector3.right * 1.5f, moveDuration);
    }

    if (!isMoving && Input.GetMouseButtonDown(1))
    {
        StartCoroutine(transform.position - Vector3.right * 1.5f, moveDuration);
    }
}

private IEnumerator Move(Vector3 targetPosition, float duration)
{
    if(isMoving) yield break;

    isMoving = true;

    var startPosition = transform.position;
    var passedTime = 0f;

    do
    {
        // This would move the object with a linear speed
        var lerpfactor = passedTime / duration;

        // This is a cool trick to simply ease-in and ease-out
        // the move speed 
        var smoothLerpfactor = Mathf.SmoothStep(0, 1, lerpfactor);

        transform.position = Vector3.Lerp(startPosition, targetPosition, smoothLerpfactor);

        // increase the passedTime by the time 
        // that passed since the last frame
        passedTime += Time.deltaTime;

        // Return to the main thread, render this frame and go on
        // from here in the next frame
        yield return null;

    } while (passedTime < duration);

    // just like before set the target position just to avoid any
    // under shooting
    transform.position = targetPosition;

    isMoving = false;
}

and you could still extend this example to also take the dtsnace to move into account like e.g.

var actualDuration = duration * Vector3.Distance(startPosition, targetPosition);

and then later everywhere use actualDuration.

Upvotes: 2

Gray_Rhino
Gray_Rhino

Reputation: 1283

Use transform.Translate instead:

public float moveSpeed = 3f;

void Update ()
{

//Moves Left and right along x Axis              
transform.Translate(Vector3.right * Time.deltaTime * Input.GetAxis("Horizontal")* moveSpeed);      
}

Upvotes: 1

Related Questions