Smooth movement using transform.Translate

I am making a 2.5d game with three “paths” lined up along the z axis, the player is moving forward along the x axis, i am trying to make it so that when you swipe up on the screen it moves “25.0f” on the z axis and when you swipe down it does the same downwards. This is the code i am using:

	public float moveCar = 25.0f;
	//First establish some variables
	private Vector3 fp; //First finger position
	private Vector3 lp; //Last finger position
	public float dragDistance;  //Distance needed for a swipe to register
	
	// Update is called once per frame
	void Update()
	{
		//Examine the touch inputs
		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)
			{
				//First check if it's actually a drag
				if (Mathf.Abs(lp.x - fp.x) > dragDistance || Mathf.Abs(lp.y - fp.y) > dragDistance)
				{   //It's a drag
					//Now check what direction the drag was
					//First check which axis
					if (Mathf.Abs(lp.x - fp.x) > Mathf.Abs(lp.y - fp.y))
					{   //If the horizontal movement is greater than the vertical movement...
						if (lp.x>fp.x)  //If the movement was to the right
						{   //Right move
							//MOVE RIGHT CODE HERE

						}
						else
						{   //Left move
							//MOVE LEFT CODE HERE
						
						}
					}
					else
					{   //the vertical movement is greater than the horizontal movement
						if (lp.y>fp.y)  //If the movement was up
						{   //Up move
							transform.Translate (Vector3.right * moveCar); 
						}
						else
						{   //Down move
							transform.Translate (Vector3.left * moveCar); 
						}
					}
				}
				else
				{   //It's a tap
					//TAP CODE HERE
					transform.Translate (Vector3.up * 6);

				}

This does what i want, except that the movement isn’t smooth at all, it just kind of teleports to the new location, i was wondering how i could make it move to the new position smoother. I have tried looking into the Vector3.Lerp but didnt really understand how to implement it.
Any tips on how i could achieve the smoother movement effect? :slight_smile:

First, you’ll need to store the destination location to move to over time. This is not something that can be done in a single update call, and you’ll need to store the state between frames. So you can start by putting in something like this.

public Vector3 destination;

Initialize that in Start to your current location, so it doesn’t try to move right away.

void Start() {
  destination = transform.location;
}

And now instead of immediately translating to your destination, in your input detection code all you need to do is something like this.

destination += Vector3.left * moveCar;

You’re all set up to go, now the Vector3.Lerp part. Vector3.Lerp will return a point on a line between two vectors. The “time” parameter you give it is something between 0 and 1, at 0 it’ll return the first vector, at 1 it’ll return the second vector, at 0.5 a point in the middle of the two vectors, etc. But you don’t need to keep track of time. There’s a clever way of doing this.

transform.position = Vector3.Lerp(transform.position, destination, 0.5f * Time.deltaTime);

In this code, instead of keeping track of how far we’ve gone and how long we have to get there, we continually pass 0.5f (multiplied by Time.deltaTime, since we’re doing this every frame), so we’re continually aiming for a point halfway between where the object is this frame, and where we want to go. The first frame you’ll accelerate quickly. As you start to get closer, you’ll continually slow down as the halfway point gets closer and closer to the destination. It’s very simple, and it’s certainly not the best way, but I think you’ll find this script useful.

using UnityEngine;
using System.Collections;

public class SmoothMove : MonoBehaviour {
    public Vector3 destination;
    public float speed = 0.1f;

	void Start () {
        destination = transform.position;
	}
	
	void Update () {
	    transform.position = Vector3.Lerp(transform.position, destination, speed * Time.deltaTime);
	}
}

Simply attach this to an object, set the destination Vector3 and it’ll move there relatively smoothly.

I would suggest using a coroutine instead of changing the transform through Update. Using a coroutine makes the code look nicer and there’s significantly less overhead. (Read more here: Unity Docs)

Here is a generic example that moves an object smoothly in the x direction by 1 unit when someone hits the right arrow key (Attach this to what you want to move.):

using UnityEngine;
using System.Collections;

public class Move_EX : MonoBehaviour {
	Vector3 right = new Vector3 (1f, 0, 0); //Vector in the direction you want to move in.

	void Update () { 
		if (Input.GetKeyDown ("right")) {//Using update to capture the keypress.
			StartCoroutine (smooth_move (right, 1f)); //Calling the coroutine.
		}
	}


	IEnumerator smooth_move(Vector3 direction,float speed){
		float startime = Time.time;
		Vector3 start_pos = transform.position; //Starting position.
		Vector3 end_pos = transform.position + direction; //Ending position.

		while (start_pos != end_pos && ((Time.time - startime)*speed) < 1f) { 
			float move = Mathf.Lerp (0,1, (Time.time - startime)*speed);

			transform.position += direction*move;

			yield return null;
		}
	}
}