- Home /
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?
I was trying to convert my previous answer to a comment but Answers bugged out and it disappeared completely... which is O$$anonymous$$ since it wasn't a good answer anyways =)
Is the mechanic you are looking for perhaps for a game like this ?
EDIT: oh now it's there again...
Your lerp is in On$$anonymous$$ouseUp() so only gets called once per $$anonymous$$ouseUp event. Sure, you wired in a Time.deltaTime piece, but that doesn't really make sense in the context of this function.
To Lerp (linear interpolate) an object moving from 1 location to the next, you need to wire this bit into Update() or start a coroutine that moves the position of your game object.
in this case..can i just apply Time.deltaTime ins$$anonymous$$d of Vector3.Lerp to my tile, give them speed so that they can swap their position smoothly,not just teleport to the position?
if yes, what can i do with my script?
Now that i know what you want to achieve, I'll try to give you an example when i get home in about 7 hours unless someone beats me to it. Hang in there !
Answer by jenci1990 · Dec 04, 2014 at 09:43 AM
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;
}
hi @jenci1990, this code is work but when i click my tile to swap position, all my tile just fly away..
Do tiles contanis this script?? if no attach this scrip to all 3 tiles, but only to tiles!
yes, all my tiles attach with this script(included emptySlot tile), for my emptySlot tile, do i need to attach this script too?
This works for me with my script.
Answer by sed · Dec 04, 2014 at 09:55 AM
Well, the problem here is that you shouldn't be using just the Time.deltaTime in the lerp.
http://docs.unity3d.com/ScriptReference/Vector3.Lerp.html
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: http://docs.unity3d.com/ScriptReference/Vector3.SmoothDamp.html
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 + t*b
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: http://answers.unity3d.com/questions/620401/mathflerp-never-gets-there.html
Please give me some time, i'm trying to figure this out, i just start coding around 2 month, thanks for your suggestion
Hi @sed, i tried like this
function On$$anonymous$$ouseUp()
{
if (Vector3.Distance(transform.position, emptySlot.position )< 3.5f)
{
lerpBetweenPosition();
}
}
function lerpBetweenPosition ()
{
var emptySlot: Transform;
var TilePos: Vector3 = transform.position;
var emptyPos: Vector3 = emptySlot.position;
var duration:float;
var counter : float = 0.0f;
while (counter< 1.0f)
{
transform.position = Vector3.Lerp (TilePos, emptyPos, counter);
counter = Time.deltaTime/duration;
yield;
}
TilePos = transform.position;
transform.position = emptyPos;
}
i got this error message:
NullReferenceException: Object reference not set to an instance of an object
$$anonymous$$ovement_ClickLimit_L1+$lerpBetweenPosition$41+$.$$anonymous$$oveNext () (at Assets/Scripts/Level_Script/$$anonymous$$ovement_ClickLimit_L1.js:72)
UnityEngine.$$anonymous$$onoBehaviour:StartCoroutine_Auto(IEnumerator)
$$anonymous$$ovement_ClickLimit_L1:On$$anonymous$$ouseUp() (at Assets/Scripts/Level_Script/$$anonymous$$ovement_ClickLimit_L1.js:41)
UnityEngine.Send$$anonymous$$ouseEvents:DoSend$$anonymous$$ouseEvents()
This is a bit to complex and not a smart way to solve the problem. The documentation of the Vector3.Lerp method shows a very good way to use the method: http://docs.unity3d.com/ScriptReference/Vector3.Lerp.html
One should pass Time.deltaTime and scale it up or down to increase or decrease speed of the interpolation: transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * lerpScaler);
i tried Vector3.Lerp, but i don't know why after i clicked my tile, they swap but they also fly away from the puzzle box
@Lunatix you might want to read the documentation again. It's very common mistake you've made there. I'll update the answer to make it more clear.
Answer by Lunatix · Dec 04, 2014 at 12:45 PM
I made a simple example project which can be downloaded here: https://www.dropbox.com/s/zt02y7bcg5nae1q/TileMapController.7z?dl=0
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".
hi @Lunatix thanks for your effort, but i can't open the file, because my unity version is 3.5.0 :(
Uhm.. try to update to the latest version, maybe ;)? There will be no disadvantages for you :) But I think you can use the scripts with unity 3.5, too.
yeap, i can open the script with my unity too, but i don't know c#, i will try my best to convert it to javascript :) this script can apply on 3D game object right?
Yes. Do the following:
[GameObject] (Attach Tile$$anonymous$$apController.cs) - [Sprite with BoxCollider] (Attach SlotController.cs) - [Sprite with BoxCollider] (Attach SlotController.cs) - [Sprite with BoxCollider] (Attach SlotController.cs) - [Sprite with BoxCollider] (Attach SlotController.cs, LeaveEmptyAtStartup: false)
And assign a Sprite Prefab to the Tile$$anonymous$$apController.
[1]: https://www.dropbox.com/s/fx1rjdiq23w8wed/editor-3.png?dl=0
Your answer
![](https://koobas.hobune.stream/wayback/20220613173108im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Can someone help me fix my Javascript for Flickering Light? 6 Answers
why one works, the other does not 2 Answers
whats wrong with my save/load script? (transform.position) 1 Answer
How to move a object forward relative to it smoothly without update function? 1 Answer
Swap texture2D on enemy sprite once reached a certain point 1 Answer