how to make character move smoothly is endless runner game

I am working on an endless runner game, the problem is when I move my character left or right, it teleports to the left or right see:

if (Input.GetKeyDown(KeyCode.RightArrow))
{
controller.Move(Vector3.right * 200 * Time.deltaTime);

    }

    if (Input.GetKeyDown(KeyCode.LeftArrow))
    {
        controller.Move(Vector3.left * 200 * Time.deltaTime);

    }

My problem is that the character is teleporting, How do you make the character smoothly move the a designated location the left or right, Please note that I am not want the character to have free rain over there exact position, I want it to have three positions you can be in like normal endless runners.

Hello, sorry for a bit late response, but it’s now that I’m working on a endless runner game for a school project. This could be a bit different approach what you had in mind, but still maybe it will help you.

I’m also posting this for anyone else who is checking the forums that might be having issues with this case and could benefit from my input, since I’ve looked and found an answer to my problems countless times and I just want to return to community.

I’ve written this code for moving a character quite smoothish(probably could be even smoother) from point A to B and B to C and vice versa . This code also responds if a player wants to change direction of character when its already moving towards a certain lane. For example he wants to go from lane A to B but while character is moving to B he wants to go back to A. I hope this will help u in any way.

//This is all in Update Function
// I have a 3 lane runner { -1, 0, 1 }, checking so it doesn't gets over that
    if (Input.GetKeyDown(moveL)  && wantedRow > -1)
            {
                centeringZero = false;
                wantedRow--;
            }
            if (Input.GetKeyDown(moveR)  && wantedRow < 1)
            {
                centeringZero = false;
                wantedRow++;
            }
            if (wantedRow == -1)
                wantedX = -horiDiff;
            else if (wantedRow == 0)
                wantedX = 0;
            else if (wantedRow == 1)
                wantedX = horiDiff;
    //bool centeringZero is necessary to prevent update of doing a multiple movement changes at once, since update is a bit unpredictable and same thing can be set multiple times. So I find bools quite useful in Update functions.
            if (centeringZero)
            {
                transform.Translate(new Vector3(0, 0, moveSpeed) * Time.deltaTime);
                Debug.Log("0, 0, moveSpeed");
            }
            else if (transform.localPosition.x < wantedX && !centeringZero)
            {
                transform.Translate(new Vector3(3, 0, moveSpeed) * Time.deltaTime);
                Debug.Log("translate 3,0,movespeed");
                if (wantedRow == 0)
                {
    //if statement to check if its close to zero if it is its sets it to zero.
                    if (transform.localPosition.x >= -0.1f && transform.localPosition.x <= 0.1f && !centeringZero)
                    {
                        Vector3 fixX = transform.localPosition;
                        fixX.x = 0;
                        transform.localPosition = fixX;
                        currRow = 0;
                        centeringZero = true;
                        Debug.Log("centering 0");
                    }
                }
                if(wantedRow == 1)
                {
    //if statement to check if its close to horiDiff in my case its set to 1.25f and set it to 1.25f
                    if (transform.localPosition.x < horiDiff && transform.localPosition.x > horiDiff - 0.1f && !centeringZero)
                    {
                        Vector3 fixX = transform.localPosition;
                        fixX.x = horiDiff;
                        transform.localPosition = fixX;
                        currRow = 1;
                        centeringZero = true;
                        Debug.Log("centering " + horiDiff);
                    }
                }
                
            }
            else if(transform.localPosition.x > wantedX && !centeringZero)
            {
                transform.Translate(new Vector3(-3, 0, moveSpeed) * Time.deltaTime);
                Debug.Log("translate -3,0,movespeed");
                if (wantedRow == 0)
                {
    //if statement to check if its close to 0 and sets it to 0
                    if (transform.localPosition.x >= -0.1f && transform.localPosition.x <= 0.1f && !centeringZero)
                    {
                        Vector3 fixX = transform.localPosition;
                        fixX.x = 0;
                        transform.localPosition = fixX;
                        currRow = 0;
                        centeringZero = true;
                        Debug.Log("centering " + 0);
                    }
                }
                if (wantedRow == -1)
                {
    //if statement to check if its close to horiDiff in my case its set to 1.25f and set it to 1.25f
                    if (transform.localPosition.x > -horiDiff && transform.localPosition.x < -horiDiff + 0.1f && !centeringZero)
                    {
                        Vector3 fixX = transform.localPosition;
                        fixX.x = -horiDiff;
                        transform.localPosition = fixX;
                        currRow = -1;
                        centeringZero = true;
                        Debug.Log("centering " + -horiDiff);
                    }
                }
            }

If you want smoother transitions from one lane to another, only thing that could be causing uneven transition is when function fixes character position to its lane. You can play around with if statements where it checks if its close to desired character X position and then set its position.

//try changing this to even closer to horiDiff, perhaps 0.01f - could be better but not sure
if (transform.localPosition.x < horiDiff && transform.localPosition.x > horiDiff - 0.1f && !centeringZero)
                     {
                         Vector3 fixX = transform.localPosition;
                         fixX.x = horiDiff;
                         transform.localPosition = fixX;
                         currRow = 1;
                         centeringZero = true;
                         Debug.Log("centering " + horiDiff);
                     }

I’ve tried to explain the code and logic best as I can, but if there is still anything unclear, please tell me where and I’ll try to explain it as best as I can.
Again this could be probably done smoother/better and definitely cleaner, but I’m kinda rushing to finish it as fast as I can, since project due is closing in fast, so this will work for me.

I don’t know if smooth movement is possible with controller.Move. I would use a coroutine:

bool isMovinLeft = false;

void Update ()
{
        if (Input.GetKeyDown(KeyCode.LeftArrow) && !isMovinLeft)
        {
            StartCoroutine(LeftMove());
        }
}

IEnumerator LeftMove()
{
        for (float f = 0; f < 10; f += 0.1f)
        {
            GetComponent<CharacterController>().Move(Vector3.left * Time.deltaTime);
            yield return null;
        }
        isMovinLeft = false;
}

The character is teleporting because you’re multiplying by 200. And using a coroutine just seems like a bad idea.
Instead of using keys to move the character, use them to change the the target row and make character move to it.

Try this:

using UnityEngine;

public class Derp : MonoBehaviour {

    public int[] rows = new int[] { -1, 0, 1 };     // x position of each row
    private int targetRow = 0;
    private CharacterController charController;


    private void Awake () {
        charController = GetComponent<CharacterController>();
        transform.position = new Vector3(rows[targetRow], 0, 0);
    }


    void Update () {

        if (Input.GetKeyDown(KeyCode.LeftArrow) && targetRow > 0) {
            targetRow--;
        }

        if (Input.GetKeyDown(KeyCode.RightArrow) && targetRow < rows.Length - 1) {
            targetRow++;
        }


        //Move Character Controller towards target row when distance is greater than 0.05
        if (Mathf.Abs(transform.position.x - rows[targetRow]) > 0.05f) {

            if (transform.position.x < rows[targetRow]) {
                charController.Move(Vector3.right * Time.deltaTime);
            }
            else if (transform.position.x > rows[targetRow]) {
                charController.Move(Vector3.left * Time.deltaTime);
            }
        }
        //Lerp transform to position when character controller is close enough
        else {
            transform.position = Vector3.Lerp(transform.position, new Vector3(rows[targetRow], 0, 0), Time.deltaTime);
        }    
    }

}