- Home /
Why is Vector3.MoveTowards easing out near its target?
I have changed my Vector3.Lerp to Vector3.MoveTowards because I was getting the undesired easing out tween when my object was getting close to its end destination. It was my understanding that MoveTowards is precisely for moving from A to B at a certain speed. However as mentioned, for some reason it is slowing down when getting close to its B and I am not understanding why. My code is very straight forward:
if (move) {
//Distance from current to end
Vector3 distToEnd = transform.position - end.position;
float distanceToX = Mathf.Abs(distanceTo.x);
float distanceToZ = Mathf.Abs(distanceTo.z);
//Difference in rotation
float rotationToY = Vector3.Angle(end.forward, transform.forward);
//Lerp & Slerp until reached target position and rotation
if (distanceToX >= 0.01 || distanceToZ >= 0.01 || rotationToY >= 0.01) {
transform.position = Vector3.MoveTowards(transform.position, end.position, Time.deltaTime * speed);
transform.rotation = Quaternion.Slerp(transform.rotation, end.rotation, Time.deltaTime * rotSpeed);
transform.rotation = Quaternion.Euler(new Vector3(0f, transform.rotation.eulerAngles.y, 0f));
}
else {
move = false;
}
}
I have a "move" boolean which is set to true when the object needs to move and slerp from its position to its end target. The if statement inside this checks to see when the X and Z axis distance and y axis rotation are within 0.01 of the end position and rotation at which point the "move" bool is turned off and therefore the move a slerp finish.
The desired effect is to move from A to B at a constant speed without any slow down/ easing out. Is MoveTowards the correct way to do this or am I simply not using it the right way?
Answer by Bunny83 · May 16, 2015 at 04:02 PM
MoveTowards is literally implemented like this:
public static Vector3 MoveTowards(Vector3 current, Vector3 target, float maxDistanceDelta)
{
Vector3 a = target - current;
float magnitude = a.magnitude;
if (magnitude <= maxDistanceDelta || magnitude == 0f)
{
return target;
}
return current + a / magnitude * maxDistanceDelta;
}
As you can see there's no easing. It just uses the normalized direction vector between the current position and the target and multiplies it with your max movement delta. So it always moves with the speed you provided. As long as this speed is constant you will have a constant movement.
If your movement isn't constant it's not related to the above mentioned code.
Hmm that's quite strange. I have updated the code in my question to include more detail of the functionality and explained it briefly underneath, I would appreciate your advice. I have tried changing the $$anonymous$$oveTowards to Lerp and back to $$anonymous$$oveTowards several times but the results appear the same; the object starts of moving fast and then slows towards the end. This makes me think that either I am doing something wrong with the code checking for when to stop the $$anonymous$$oveTowards, or the fact that the object is a rigidbody is somehow having an effect on the movement. I have tried changing the object to kinematic and turning of gravity during the $$anonymous$$oveTowards, but this simply makes the object drop through the floor. Not sure what I'm doing wrong.
Edit: Geh! Whoopsie. Yeah, you're right about that. Sorry for the mixup.
No, that's how Lerp works. $$anonymous$$oveTowards uses a distance delta (in units) for the third parameter, not a percentage. The code in the question is using Slerp incorrectly though. (Which is to say, it's using Slerp like $$anonymous$$oveTowards, which causes it to behave differently at different framerates.)
You might want to use Quaternion.RotateTowards as equivalent to Vector3.$$anonymous$$oveTowards. Lerp and Slerp work differently to $$anonymous$$ove / Rotate towards. Lerp and Slerp only provide a linear interpolation between two fix point / rotations. If you pass the current position / rotation as start value to lerp you will see a slowdown when you get closer to the target as Lerp simply moves a percentage of the distance between start and end.
Lerp is ment to be passed constant start and end values and you should increment the t value slowly from 0.0 to 1.0. If you pass 0 for t Lerp simply returns the start value if you pass 1 it returns the end value if you pass anything in between it will be the linear interpolated position between start and end.
You're right, strangely enough it was the slerp that was causing the $$anonymous$$oveTowards to appear delayed. I changed it to RotateTowards and it now works perfectly. Thanks alot :)
Your answer
Follow this Question
Related Questions
Moving 2D sprite along a path 0 Answers
Moving an UI element from point A to point B 1 Answer
Vector3.lerp doesn't work 1 Answer
Lerp a Object along X and Z axis only. 3 Answers