- Home /
Mathf.Lerp working in one direction but not the other
Hi folks, I'm making a flying game with airplanes and am looking to create a visual effect when the player is flying upwards or downwards (vertical axis). Simply, I'm currently trying to rotate the plane body about 30 degrees off the start rotation around the x axis. The player body is a child of an empty game object.
I'm using Lerp to accomplish this, but it doesn't seem to be working as expected. It works perfectly well when flying upwards but not the case when flying downwards. Here is my code:
void RotateBody()
{
float currentRotation = playerBody.localRotation.eulerAngles.x;
float targetRotation = bodyTurnRotation * verticalMovement + startRotation;
float lerpedValue = Mathf.Lerp(currentRotation, targetRotation, bodyTurnRotationSpeed * Time.deltaTime);
playerBody.localRotation = Quaternion.Euler(new Vector3(lerpedValue, 0, 0));
}
I log out all the values to the console and the Lerp value is correctly changing but the localRotation doesn't actually change! This only happens when flying downwards, it works as expected when flying upwards. Any help would be greatly appreciated!
Does bodyTurnRotationSpeed ever change? If not I'm surprised that this works moving upwards! If it does change then could you give more information about where that's set.
Aside from this issue, it's not great practice to move between rotations using Mathf.Lerp: say you wanted to lerp between 5 degrees and 355 degrees, since Mathf.Lerp doesn't care about degrees it would take the long route and hit 180 degrees at half way instead of 0. It's possible that this could be at play here. It's preferable to use Quaternion.Lerp for lerping between rotations.
bodyTurnRotationSpeed does not change. That's a good point about the degrees, as it so happens the degrees for the body turn stay clamped to between 60 and 120 degrees (90 is the default position).
I can and definitely will use Quaternion, but I guess I wanted to confirm my understanding of Lerp, since you mentioned that you're surprised it worked at all if bodyTurnRotationSpeed doesn't change. Lerp(a, b, t)
will produce the next value from a
to b
with step t
. So t
(whch is determined by bodyTurnRotationSpeed
) is just a step value, right? Why should this need to change? The only one that should change (per my understanding) is a
(currentRotation in this case)?
Answer by highpockets · Mar 04 at 11:22 PM
Your understanding is wrong about Lerp. The timescale value (3rd parameter) is the distance between the 2 values and it is the only value that should change if you want to do a pure linear interpolation. Well you could calculate it without Lerp, but that’s irrelevant here.
—————-
If you want to go from 10 - 50. Inside the Lerp function, 10 will be a time scale value of 0 and 50 will be a time scale value of 1. So, with the code you are using above, you are not actually doing a linear interpolation at all. A linear interpolation would keep the same start and end positions throughout the duration of the Lerp and just change the timescale evenly on every update. Instead you are getting more of a dampened change from A to B, because you keep moving “A” closer to “B” and so the distance is shorter, but your time scale is more or less the same for every update.
——————
So, let’s say the initial distance is 40 with A at 10 and B at 50. If your timescale is 0.5, it will return 30. So now 30-50 and say your timescale is again 0.5. It will return 40. So as you see, the closer you get, the more you slow down and you may never actually reach the destination because even when you get to a point where A is at 49.9999 and B at 50, 0.5 is still halfway between the 2 values.
——————
So now to go in the opposite direction, it is the exact same, but A is now 50 and B is now 10 and a timescale of 0 is 50 and a timescale of 1 is 10.