- Home /
Mathf.Lerp never gets there
Hi,
I want to lerp from 0 to 1 then back from 1 to 0, this is my code -
// Only look at the player if within lookdistance
if(distanceToPlayer < lookdistance){
theLookAtPosition = player.position;
ikLootAt.solver.IKPosition = theLookAtPosition;
lerpWieghtUp();
ikLootAt.solver.IKPositionWeight = lookWeight;
}else if(distanceToPlayer > lookdistance){
lerpWieghtdown();
ikLootAt.solver.IKPositionWeight = lookWeight;
}
}
function lerpWieghtUp(){
while(lookWeight < 1.0f){
lookWeight = Mathf.Lerp(lookWeight,1.0f,Time.deltaTime*lookSmoother);
yield;
}
}
function lerpWieghtdown(){
while(lookWeight > 0.0f){
lookWeight = Mathf.Lerp(lookWeight,0.0f,Time.deltaTime*lookSmoother);
yield;
}
}
But lookWeight never reaches 0 or 1 so the while loop still keep going, how can I hit 0 and 1 with lerp?
Another way I can do this is -
// Only look at the player if within lookdistance
if(distanceToPlayer < lookdistance){
theLookAtPosition = player.position;
ikLootAt.solver.IKPosition = theLookAtPosition;
lerpWieghtUp();
ikLootAt.solver.IKPositionWeight = lookWeight;
}else if(distanceToPlayer > lookdistance){
lerpWieghtdown();
ikLootAt.solver.IKPositionWeight = lookWeight;
}
}
function lerpWieghtUp(){
while( lookWeight < 1.0f ){
lookWeight =+ 0.01f;
yield;
}
}
function lerpWieghtdown(){
while( lookWeight > 0.0f){
lookWeight =- 0.01f;
yield;
}
}
But it looks false because of the sudden stoping at the ends, not gradually like lerp, any help would be appreciated, thanks.
Answer by instruct9r · Jan 19, 2014 at 11:52 AM
What i do, when using Lerp is add one IF statement which finish the Lerp when it gets realy close to it's target, cuz when finishing, the Lerp is slowing down and yes, sometimes it allmost never reach it's target value.
So what you can do is this:
function lerpWieghtUp(){
while(lookWeight < 1.0f){
lookWeight = Mathf.Lerp(lookWeight,1.0f,Time.deltaTime*lookSmoother);
if (lookWeight >= 0.95)
lookWeight = 1;
yield;
}
}
function lerpWieghtdown(){
while(lookWeight > 0.0f){
lookWeight = Mathf.Lerp(lookWeight,0.0f,Time.deltaTime*lookSmoother);
if (lookWeight <= 0.05)
lookWeight = 0;
yield;
}
I am not testing the code in Unity, so i'm not sure if you have to put the If statement before or after the yield... Hope it helps :)
If 0.05 makes your object to snap too noticeable, you can decrease it to 0.025...
instruct9r, thanks for the input, I'll accept your answer as correct because you pointed me in the right diction, thanks, this is what works for me -
function lerpWieghtUp(){
while(lookWeight < 0.99f){
lookWeight = $$anonymous$$athf.Lerp(lookWeight,1.0f,Time.deltaTime*lookSmoother);
yield;
}
lookWeight = 1.0f;
}
function lerpWieghtdown(){
while(lookWeight > 0.02f){
lookWeight = $$anonymous$$athf.Lerp(lookWeight,0.0f,Time.deltaTime*lookSmoother);
yield;
}
lookWeight = 0.0f;
}
What both of you are doing wrong here, is that you do NOT lerp (linear interpolation), but use a bad quadratic interpolation. Look at your code, assu$$anonymous$$g you lerp from A to B, in .5 steps - if should be done in 2 steps, but your version NEVER reaches B. That is, because what you do is: lerp from A to (A + .5* AB) , then from THIS point again: (A + .5 (.5 AB)) and again (A + .5 (.5 (.5* AB))) etc.
If you want to do a real linear interpolation, you have to save your original position, and then do
lookWeight = $$anonymous$$athf.Lerp(lookWeightOld,1.0f,Time.deltaTime*lookSmoother);
Simpler: you want to lerp from 0 to 1, in .5 steps.
You want: 0 .5 1
You actually do: 0 .5 .75 .875 ....
I don't get it. Where do you see (A + 0.5)? you Lerp from A (lookWeight) to 1.0. We never sum A (lookWeight) with 0.5..
Are you trying to say, that while Lerping, the lookWeight, as start point in the Lerp changes as well?
$$anonymous$$eaning when we start Lerping:
lookWeight = $$anonymous$$athf.Lerp(lookWeight, 1.0, Time.deltaTime*lookSmoother);
which can be read in the begining as
lookWeight = $$anonymous$$athf.Lerp(0.0, 1.0, Time.deltaTime*lookSmoother);
and somewhere at the middle of the Lerping the lookWeight in the brackets is also changing? like
lookWeight = $$anonymous$$athf.Lerp(0.5, 1.0, Time.deltaTime*lookSmoother);
And even if this is true, then what does this have to do with the end value of the Lerp, which in this case is 1.0. It never changes...
It is true, and your explanation is correct. But what you miss is, while the end of the lerp is 1.0, your lerp will NEVER reach 1.0 if the parameter is not 1, too. lerp(0.99, 1.0, 0.99) is still not 1.
Answer by sed · Nov 18, 2014 at 04:55 PM
Well, the problem here is that you shouldn't be using just the Time.deltaTime in the lerp.
http://docs.unity3d.com/ScriptReference/Mathf.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
function lerpWieghtUp(duration : float){
var counter : float = 0.0f;
while(counter < 1.0f){
lookWeight = Mathf.Lerp(lookWeight,1.0f, counter);
counter += Time.deltaTime / duration;
yield;
}
lookWeight = 1.0f;
}
and if you want it to look smoother you can use Mathf.SmoothStep
function lerpWieghtUp(duration : float){
var counter : float = 0.0f;
while(counter < 1.0f){
lookWeight = Mathf.Lerp(lookWeight, 1.0f,
Mathf.SmoothStep(0.0f, 1.0f, counter));
counter += Time.deltaTime / duration;
yield;
}
lookWeight = 1.0f;
}
Duration here let's you specify how long should the animation take.
Omg thank you. I know this was 3 years ago but I never knew how to lerp for a specified duration.
Glad it helped. Too bad the accepted answer to this question is actually misleading.
And by the way, you could hit the vote up button next to the answer so I get internet points and eternal glory ;)