- Home /
Make Lerp or other more fluid or continuous
OK, so I am making an algorithm that goes to one point to another point and I am already done but, when the enemy is walking to the final point it moves to slow, it means that as some knows some algorithm use the grid so is separated in squares(or triangles) so this makes that it doesn't goes fluid or continuous. So my question here is: how can I make a movement more fluid or continuous having the same speed. This is part of what I am doing so you can see it how I do it:
enemy.position = Vector3.Lerp(enemy.position,nodes[newdistance],Time.deltaTime * speed);
Hi, Uriel. Can I ask you a question?? I am new in Unity and I guess I'm trying to do something like I did. I post this question now http://answers.unity3d.com/questions/12859/move-an-object-through-a-set-of-positions.html, and I really think it's similar that what you've done. I would like to now if you can help me. Thanks!
Answer by Bunny83 · Apr 08, 2011 at 03:22 AM
Your problem is that everyone is using lerp in that strange way. Lerp is meant to lineary go from start to end, but for that behaviour you need a fix start and end point and the last parameter specify how far the interpolation is at the moment. This parameter t have to be between 0 and 1 (0==start 1==end). Everyone uses as start the sctual position and a more or less constant value for t. If t is 0.1 that means that the calculated position is exact 10% toward the target position from the actual position. When the start position comes closer to the end the distance will get smaller. We move always 10% each frame but 100% is the current distance. So with this method you will never reach the target, you come very close and the speed is almost zero but theoretically you can't reach the end (due to float inaccuracy you may reach it)
In short: what you want is a constant movement, so a distance independent movement speed. Unity have this very nice function called MoveTowards. This function is supposed to take the current position and moves it towards the target position.
enemy.position = Vector3.MoveTowards(enemy.position,nodes[newdistance],Time.deltaTime * speed);
thanks man, useful, fast and easy, just what I was looking for :)
thank you Bunny83, i just got started with unity about a month ago, and this fixed the not so smooth movement of my objects too !
It's really weird that almost everyone who has not read the docs on Lerp has come up with the same wrong idea of what it's for and what arguments to give it.
@$$anonymous$$iloblargh: Well, as far as i remember the docs had for a long time one of the "wrong" or "bad" examples. Actually most examples in the docs are bad.
It's not really wrong. There's no problem using lerp that way, but you should understand what it does. If you do you should be able to figure out what results you would get and if that's really what you want ;)
Answer by Dragonlance · Oct 04, 2012 at 08:14 PM
For a nice Lerp you need something like:
transform.localPosition =
Vector3.Lerp(
startPos,
targetPos,
(Time.time - startTime) / duration);
Do not put in the current position each frame or it will not interpolate linear! Save the start position and calculate with that until the end.
And you will have to cancel the Lerp as soon as ((Time.time - startTime) / duration) is >= 1.0
As Bunny said (Time.deltaTime * speed) is the right thing for MoveTowards not for Lerp.
Thanks, Dragonlance. The duration would be something like this: float duration = Time.time - lerpStartTime; ?? Sorry for the noob question.
Hi Paul,
no it is somethin you define.
Lets say I want to move the object from (1,5,7) to (2,16,20) in 5 seconds, then it would be:
Vector3 startPos = new Vector3(1.0f,5.0f,7.0f); Vector3 targetPos= new Vector3(2.0f,16.0f,20.0f); float duration = 5.0f;
Well you can also calculate the duration from the speed: float speed = 1.8f; float duration = Vector3.distance(startPos, targetPos) / speed;
Of course this has to be packed in context. $$anonymous$$aybe you want to start the animation from the local position and you just know the target position: Vector3 startPos = transform.localPosition; Vector3 targetPos = new Vector3(2.0f,16.0f,20.0f); float duration = Vector3.distance(startPos, targetPos) / speed;
The most simple way to actually use it is something like:
public float speed = 2.0f;
private Vector3 startPos;
private Vector3 targetPos;
private float duration;
bool animationRunning = false;
void Update()
{
if(animationRunning) {
float animationProgress = (Time.time - startTime) / duration;
transform.localPosition =
Vector3.Lerp(
startPos,
targetPos,
animationProgress );
}
if(animationProgress >= 1.0f) {
transform.localPosition = targetPos;
animationRunning = false;
}
}
}
public void StartAnimation(Vector3 target)
{
Vector3 startPos = transform.localPosition;
Vector3 targetPos = target;
float duration = Vector3.distance(startPos, targetPos) / speed;
animationRunning = false
}
Personally I prefer a Coroutine in most cases ins$$anonymous$$d of update.
(This example is c# and has to be in a $$anonymous$$onobehaviour Class, I just hate the code identation here and did not want to format it all sry.)
Good Luck!!
Ohh, I see! I was trying something completely different! Thanks a looooot! Really! :DD