I have a fairly simple function that moves a camera to a destination:
void MoveToward(Vector3 destination, float speed)
{
// so we only want the movement to start when we decide
if (!started)
return;
Debug.Log("Moving to :" destination);
Debug.Log("Currently at: " transform.position);
// Move the camera into position
transform.position = Vector3.Lerp(transform.position, destination, speed);
if (transform.position.Equals(destination))
{
started = false;
Debug.Log("Arrived!");
}
}
The movement works great. However, the if statement at the end never evaluates to true. I also tried to do:
if (transform.position == destination)
{
started = false;
Debug.Log("Arrived!");
}
That also never works, even though the '==' operator is supposed to evaluated 'approximate' equality.
The Debug log earlier in the function seems to show matching values (screenshot attached).
Any guidance is appreciated!
Like I mentioned, checking the values in the debug log, tried using the equality operator, as well as the Vector3.Equals function. None of which seem to ever evaluate to true.
CodePudding user response:
While experimenting, I found that I can change the 'speed' value, and it will cause the equality to evaluate as true. At first, I was using .03f as the speed. Changing it to .1f causes it to eval to true. The bigger the number, the faster it gets there, but .03 never seems to get there.
Also, weirdly, changing the order of the Lerp and the Debug.Log statements seems to cause the movement to change speed, even when the speed value remains the same.
CodePudding user response:
Oh, no, not another misuse of the Lerp function! Lerp moves from value A to value B by a given number, so if I put one and three in, with a value of 0.3, it would move 30% of the way to B giving me 1.6. The issue is when you update A. If you now set A to 1.6 and ran it again, it would move 30% again from the new value, giving 2.02! Each time it will move a smaller and smaller amount, theoretically never reaching it, although floating point numbers can be weird.
Solution 1: Don't change A or B, but increase the lerp amount. With the same example as before, lerping from 1 to 3, it would start the same with a lerp of 0.3 going to 1.6. Next, instead of changing A, change the lerp amount to 0.6. Now lerping from 1 to 3 with 0.6 will give 2.2, the expected amount.
Solution 2: Use MoveTowards. This one literally moves towards the value by the amount specified in the third parameter. If I give it 0.3 it will give 1.3. Next, it would again move by exactly 0.3 to 1.6. This will repeat, 1.9, 2.2, 2.5, 2.8, until it reaches the destination 3.
I would suggest solution two when possible, as you can move the end goal in real time and it will keep running smoothly, and it is easier to give it an exact speed, although if you want it to take an exact amount of time, and the target isn't changing, Lerp is better.
Also, make sure you multiply your speed with the timestep. If this is in Update(), that would be Time.deltaTime, and if it is in FixedUpdate(), that would be Time.fixedDeltaTime.
TLDR: Use .MoveTowards() instead for the easy fix, which takes in an amount and moves by that. Multiply speeds by the timestep for consistent movement. Lerp isn't meant to be used that way, read docs for additional info.
Mathf.Lerp Vector3.Lerp Mathf.MoveTowards Vector3.MoveTowards
Edit: You can also google SmoothDamp if you want a smooth motion, or you can fix how you use Lerp and raise it to some power to get a fade in or out.