Vector3.Lerp doesn't work

Hi there!
this is my puzzle game

And this is my script (I cut it short):

var emptySlot: Transform;
var xtemp;
var ytemp;
var Tile1Pos : GameObject;
var Tile2Pos : GameObject;
var Tile3Pos : GameObject;
var speed : float= 0.01f;

function Update()
{
	Tile1Pos= GameObject.Find("Tile_1");
	
	Tile2Pos= GameObject.Find("Tile_2");

	Tile3Pos= GameObject.Find("Tile_3");
}

function OnMouseUp()
{
	
	if (Vector3.Distance(transform.position,emptySlot.position)< 3.2)
	{
		xtemp= transform.position.x;
		ytemp= transform.position.y;
		transform.position.x= emptySlot.position.x;
		transform.position.y= emptySlot.position.y;
		emptySlot.position.x= xtemp;
		emptySlot.position.y= ytemp;
                
            var movement = speed * Time.deltaTime;
		Tile1Pos.transform.position = Vector3.Lerp( Tile1Pos.transform.position, emptySlot.position, movement);

		Tile2Pos.transform.position = Vector3.Lerp( Tile2Pos.transform.position, emptySlot.position, movement);

		Tile3Pos.transform.position = Vector3.Lerp( Tile3Pos.transform.position, emptySlot.position, movement);
     }

If i write like this, i didn’t get any error message but my tile won’t change the position with my empty slot slowly. I don’t know why so i tried like this:

Tile3Pos.transform.position = Vector3.Lerp( transform.position, emptySlot.position, movement);

After i click my tile, all my tile just fly away @@!

If i write my Vector3.Lerp to function Update column, my tile just keep changing their position automatically. Can someone tell me what’s the problem here?

var emptySlot: Transform;
var xtemp;
var ytemp;
var Tile1Pos : GameObject;
var Tile2Pos : GameObject;
var Tile3Pos : GameObject;
private var speed : float= 1f;

function Start() {
	Tile1Pos= GameObject.Find("Tile_1");
	Tile2Pos= GameObject.Find("Tile_2");
	Tile3Pos= GameObject.Find("Tile_3");
}
function OnMouseUp() {
	if (Vector3.Distance(transform.position,emptySlot.position)< 3.2f) {
		Change();
	}
}

function Change() {
	var timer : float = 0f;
	var myPos : Vector3 = transform.position;
	var emptyPos : Vector3 = emptySlot.position;
	while (timer <= 1f) {
		timer += Time.deltaTime * speed;
		transform.position = Vector3.Lerp(transform.position, emptyPos, timer);
		emptySlot.position = Vector3.Lerp(emptySlot.position, myPos, timer);
		yield WaitForEndOfFrame();
	}
	transform.position = emptyPos;
	emptySlot.position = myPos;
	return;
}

Well, the problem here is that you shouldn’t be using just the Time.deltaTime in the lerp.

Because here is how Lerp works:
“Interpolates between a and b by t. t is clamped between 0 and 1.”

So for the lerp to actually “get there” you need to maintain a counter, here is a simple Coroutine:

function lerpBetweenPositions(who : transform, a : Vector3 , b: Vector3, duration : float){
     var counter : float = 0.0f;
     while(counter < 1.0f){
         transform.position = Vector3.Lerp(a, b, counter);

         counter += Time.deltaTime / duration;
         yield;
     }
     transform.position = b; // its important to clamp the lerp to final position
 }

Alternatively using SmoothDamp might be more intuitive for you:

Update:
It’s common mistake to use any of the Unity’s Lerp with a constant or near constant value every frame. If your doing Lerp(a, b, deltaTime * scaler) every frame then the output might be visually similar to what you want to achieve but in fact it’s not. Look at this pseudocode of how lerp works:
Lerp(a,b,t) = (1-t)a + tb

ie.
at t = 0 → Lerp(a,b,0) = a;
at t = 1 → Lerp(a,b,1) = b;

at any point between 0 and 1 it’s simple linear interpolation of the result.

Since Time.deltaTime is very similar every frame, when you use a scaler value (like a constant speed, 0.3f or whatever) a

a = Lerp(a,b, Time.deltaTime * scaler) the animation will never reach b. In fact just don’t get the control over the animation you could achieve using SmoothDampen or whatever.

In my approach in the code above to get smoothing and full control over the animation you can use

function lerpBetweenPositions(who : transform, a : Vector3 , b: Vector3, duration : float){
     var counter : float = 0.0f;
     while(counter < 1.0f){
         transform.position = Vector3.Lerp(a, b, Mathf.SmoothStep(0.0f, 1.0f, counter));

         counter += Time.deltaTime / duration;
         yield;
     }
     transform.position = b; // its important to clamp the lerp to final position
 }

Similar question:

I made a simple example project which can be downloaded here: Dropbox - File Deleted - Simplify your life

Let me explain the workflow:

First, I created a tile map controller which is capable of controlling slots and tiles. The click events are achived by using box colliders marked as “Trigger”.

The tile map controller identifies all attached slots by searching for a component called “SlotController”.
A slot controller can be marked as “Leave Empty on Start” so it will not be filled.

All slots not marked as empty will be filled automatically by instantiating a new tile, defined by a prefab and a component called “TileController” will be added to the instantiated object.

SlotControllers and TileControllers will notify the TileMapController about click events - the tile map controller then decides if a tile can be moved to the clicked position.

While the tile is lerping to the new position it will prevent mouse clicks to prevent movements in “mid air”.

I did not implement drag and drop for the sake of simplicity - just click a tile and an empty slot to start the movement.

If your want to have more slots, simply copy and paste one of the game objects called “Slot”.