Lerp Only Works Incrementally

Hey everyone,
I’m trying to create a infinite runner for mobile and am working on switching lanes. I’ve tried using lerp to achieve this but I keep having to swipe the screen in order to move the character. This looks like to me something to do with the positioning of the lerp. So i tried creating a method called MoveLeft() however it gave me an error saying void is not being used in context. The first code is without the method and the second one is with the methods. I appreciate your help very much.

    void Update ()
    {
        foreach(Touch touch in Input.touches)
        {
            if(touch.phase == TouchPhase.Began)
            {
                fp = touch.position;
                lp = touch.position;
            }

            if(touch.phase == TouchPhase.Moved)
            {
                lp = touch.position;
            }
           
            if(touch.phase == TouchPhase.Ended)
            {
                if((fp.x - lp.x) > 80) //left swipe
                {
                    Debug.Log("Left Swipe");

                   
                 
                }

                currentLerpTime += Time.deltaTime;
                if (currentLerpTime >= lerpTime)
                {
                    currentLerpTime = lerpTime;
                }

                float Perc = currentLerpTime / lerpTime;

                transform.position = Vector3.Lerp(rightPos, leftPos, Perc);

                if ((fp.x-lp.x) < -80) //right swipe
                {
                    Debug.Log("Right Swipe");
                   
                }
            }
        }
    }
}
    void Update ()
    {
        foreach(Touch touch in Input.touches)
        {
            if(touch.phase == TouchPhase.Began)
            {
                fp = touch.position;
                lp = touch.position;
            }

            if(touch.phase == TouchPhase.Moved)
            {
                lp = touch.position;
            }
           
            if(touch.phase == TouchPhase.Ended)
            {
                if((fp.x - lp.x) > 80) //left swipe
                {
                    Debug.Log("Left Swipe");

                    MoveLeft();
                 
                }

                if ((fp.x-lp.x) < -80) //right swipe
                {
                    Debug.Log("Right Swipe");
                   
                }
            }
        }

        void MoveLeft()
        {
            currentLerpTime += Time.deltaTime;
            if (currentLerpTime >= lerpTime)
            {
                currentLerpTime = lerpTime;
            }

            float Perc = currentLerpTime / lerpTime;

            transform.position = Vector3.Lerp(rightPos, leftPos, Perc);
        }
    }

How about this:

void Update ()
{
    foreach(Touch touch in Input.touches)
    {
        if(touch.phase == TouchPhase.Began)
        {
            fp = touch.position;
        }
        else if(touch.phase == TouchPhase.Ended)
        {
            lp = touch.position;
           
            if((fp.x - lp.x) > 80) //left swipe
            {
                Debug.Log("Left Swipe");
                StartCoroutine(MoveLeft());
            }
            else if((fp.x - lp.x) < -80) //right swipe
            {
                Debug.Log("Right Swipe");
            }
        }
    }

    IEnumerator MoveLeft()
    {
        float Perc = 0f;
        float incrementAmount = 1f / lerpTime;
       
        while(Perc < 1f)
        {
            Perc += Time.deltaTime * incrementAmount;
            transform.position = Vector3.Lerp(rightPos, leftPos, Perc);
           
            yield return null; // Wait for one frame (for smooth transition)
        }
       
        transform.position = leftPos;
    }
}

Not sure if it works yet but for some reason there is no red line in visual studio but unity says that The ending } of my entire class is an unexpected symbol and also that the first line of your IEnumerator that you gave me it says it has an unexpected symbol…

IEnumerator MoveLeft()

that line

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    public Transform player;
    private Vector2 fp;
    private Vector2 lp;
    private int speed = 1;
    public Rigidbody rb;

    public Transform right;
    public Transform left;

    private Vector3 rightPos;

    private Vector3 leftPos;

    private float distance = 10f;

    private float lerpTime = 5f;

    private float currentLerpTime = 0;


    // Use this for initialization
    void Start()
    {
        rightPos = right.transform.position;
        leftPos = left.transform.position;
    }

    // Update is called once per frame
    void Update()
    {
        foreach (Touch touch in Input.touches)
        {
            if (touch.phase == TouchPhase.Began)
            {
                fp = touch.position;
                lp = touch.position;
            }

            if (touch.phase == TouchPhase.Moved)
            {
                lp = touch.position;
            }

            if (touch.phase == TouchPhase.Ended)
            {
                if ((fp.x - lp.x) > 80) //left swipe
                {
                    Debug.Log("Left Swipe");

                    StartCoroutine(MoveLeft());

                }

                if ((fp.x - lp.x) < -80) //right swipe
                {
                    Debug.Log("Right Swipe");

                }
            }
        }

        IEnumerator MoveLeft()
        {
            float Perc = 0f;
            float incrementAmount = 1f / lerpTime;

            while (Perc < 1f)
            {
                Perc += Time.deltaTime * incrementAmount;
                transform.position = Vector3.Lerp(rightPos, leftPos, Perc);

                yield return null; // Wait for one frame (for smooth transition)
            }

            transform.position = leftPos;
        }
    }
}

thats the entire code if it helps… thanks for your quick reply btw

Put } at line 67 and remove the } at the end of the script.

It works!!! Thanks a lot. Another quick question: If I wanted to tilt the car (in this case for my runner) would i use an animation or should i physcially change the rotation of the mesh? Also this lerp will work for up and down movement right? Oh and how did this fix the problem? was it because it shouldn’t be inside the update function? Because now the IEnumerator is no longer inside the update function.

Also the movement is slightly jittery is there a way i can make it smoother?

I’d recommend you to use animations for the tilting, it’d be easier. This particular Lerp will lerp the position from rightPos to leftPos. To understand how this code works, you should be familiar with coroutines. Just google “unity coroutine” and you’ll find plenty of beginner-friendly tutorials. Hope that helps.

P.S. To possibly fix the jittery, you can try moving the camera movement code into LateUpdate. If you are not moving the camera via a script, then I’m unsure about the solution to this issue.

Yup I’ve changed the code so it does both directions, I haven’t made the camera operational yet so I think when I do it should be better. Thanks so much for the help.

transform.position = Vector3.Lerp(leftPos, rightPos, Mathf.SmoothStep(0.0f, 1.0f, Perc));

I found this mathf.smoothstep and added it in. Should it make it smoother? I can’t really tell a difference between them so do you know if there is a downside to using this smoothstep?

Ok my final question is how I could make this only lerp the player on the x axis?

SmoothStep may make the movement more smooth, yes; feel free to use it. To restrict the movement to x-axis only:

Vector3 pos = transform.position;
pos.x = Vector3.Lerp(rightPos, leftPos, Perc).x;
transform.position = pos;

This doesn’t really work, I move the player and there is a delay of just under a second and then it jumps to the left side there is no smooth moving. If i try to decrease the increment amount then the lag becomes longer…

It might have something to do with the way the game updates and when the movement happens so here is the code:

 void Start()
    {
        playerPos = transform.position;
        rightPos = right.transform.position;
        leftPos = left.transform.position;
        upL = upLT.transform.position;
        upR = upRT.transform.position;
    }

    // Update is called once per frame
    void Update()
    {
        foreach (Touch touch in Input.touches)
        {
            if (touch.phase == TouchPhase.Began)
            {
                fp = touch.position;
                lp = touch.position;
            }

            if (touch.phase == TouchPhase.Moved)
            {
                lp = touch.position;
            }

            if (touch.phase == TouchPhase.Ended)
            {
                float xDiff = fp.x - lp.x;
                float yDiff = fp.y - lp.y;

                if (yDiff < -50 && InAir == false) //Up swipe
                {
                    if (Mathf.Abs(xDiff) > Mathf.Abs(yDiff))
                    {
                        Debug.Log("Y axis was larger than x axis");
                    }
                 else
                    Debug.Log("Up Swipe");
                    StartCoroutine(MoveUp());
                    SwipeCount = SwipeCount + 1;

                }
               
                if (xDiff > 50) //left swipe
               
                    if (LaneNumber > 0 && InAir == false)
                        {
                            Debug.Log("Left Swipe");
                            StartCoroutine(MoveLeft());
                            LaneNumber = LaneNumber - 1;
                            SwipeNum = -1;
                        }

                if (xDiff < -50) //right swipe
                   
                        if (LaneNumber < 1)
                        {
                            Debug.Log("Right Swipe");
                            StartCoroutine(MoveRight());
                            LaneNumber = LaneNumber + 1;
                            SwipeNum = 1;
                        }
            }
        }
    }
    IEnumerator MoveLeft()
    {
        float Perc = 0f;
        float incrementAmount = 1f / lerpTime;
        while (Perc < 1f)
        {
            Perc += Time.deltaTime * incrementAmount;
            playerPos.x = Vector3.Lerp(rightPos, leftPos, Mathf.SmoothStep(0.0f, 1.0f, Perc)).x;

            yield return null; // Wait for one frame (for smooth transition)
        }

        transform.position = playerPos;
    }

maybe I should use smoothdamp instead of lerp?

This is a video of what i mean.
When i move to the left lane I am using the code that fixes the lerp on the x axis but when I move from left to right I am using the old code that takes the complete vector. Do you see how it lags and practically jumps?

I’ve tried all other methods, smoothDamp, moveTowards and mathf.lerp and they all move the object yet it is always teleporting it so it must be something outside the actual lerp.

You should put transform.position = playerPos; at line 74. Then all these methods will start working.

1 Like

Ok I’m almost there! Now it works fine but when I try to jump up and switch lanes in mid air it locks the start position to that y coordinate and swiping right even on the ground brings you from mid air to the ground.

    IEnumerator MoveUp()
    {
        float Perc = 0f;
        float incrementAmount = 30f / lerpTime;
        while (Perc < 1f)
        {
            Perc += Time.deltaTime * incrementAmount;
            playerPos.y = Vector3.Lerp(transform.position, upPos, Mathf.SmoothStep(0.0f, 1.0f, Perc)).y;
            transform.position = playerPos;
            yield return null; // Wait for one frame (for smooth transition)
        }

    }

thats my code for moving the player up (I use gravity to bring the player down which is why i was expecting it to allow the player to switch x on its way back down)

Hmm, you may have to put playerPos = transform.position; between lines 72 and 73. We can continue this chat in a private conversation, no need to bump this thread any further :slight_smile:

Ok where would we continue it? through email? also lines 72 and 73 in relation to which post? since the latest code i have sent does not go that far.