- Home /
Vector3.Lerp does not linearly interpolate, any ideas?
I've had this little idea for an FPS game and following the success with the few people that played the last game I finished I decided to go into it with a light heart. However, I've come up against a couple of problems with it; my Vector3.Lerps do not seem to work as intended. I know it is something I've done and it's almost certainly blindingly obvious to anyone else but I can't see what's wrong and so some help would be very much appreciated.
Relevant Code:
public Vector3 editingPosition;
public Vector3 originalPosition;
public Vector3 editingRotation;
public float editingFOV = 30.0f;
public float editingFOVAll = 45.0f;
public float defaultFOV = 60.0f;
public float timeToTake = 0.3f;
if(!isEditing){
transform.localPosition = Vector3.Lerp(originalPosition, editingPosition, 1f * Time.deltaTime * (timeToTake * 10));
transform.localRotation = Quaternion.Slerp(Quaternion.Euler (0,5.8f,0), Quaternion.Euler(editingRotation), 1f * Time.deltaTime * (timeToTake*10));
Camera.main.fieldOfView = Mathf.Lerp (Camera.main.fieldOfView, defaultFOV, 1f * Time.deltaTime * (timeToTake * 10));
weaponCamera.fieldOfView = Mathf.Lerp (weaponCamera.fieldOfView, defaultFOV, 1f * Time.deltaTime * (timeToTake * 10));
}
else{
transform.localPosition = Vector3.Lerp(editingPosition, originalPosition, 1f * Time.deltaTime * (timeToTake * 10));
transform.localRotation = Quaternion.Slerp(Quaternion.Euler(editingRotation), Quaternion.Euler (0,5.8f,0), 1f * Time.deltaTime * (timeToTake*10));
Camera.main.fieldOfView = Mathf.Lerp (Camera.main.fieldOfView, editingFOVAll, 1f * Time.deltaTime * (timeToTake * 10));
weaponCamera.fieldOfView = Mathf.Lerp (weaponCamera.fieldOfView, editingFOV, 1f * Time.deltaTime * (timeToTake * 10));
}
The problems I'm having is that the Vector3.Lerp isn't moving the model at all (All the values are set in the editor to the correct places) and, though I took this from my other script where the Vector3.Lerp worked, however, it does not linearly interpolate but rather jump to the second location.
N.B. The Quaternion.Slerp and the Mathf.Lerp work as intended.
Any help to point out my errors would be very much appreciated.
Thanks.
Answer by robertbu · May 15, 2014 at 08:05 PM
None of your Lerps/Slerps are linear. All are used in a non-traditional fashion. Lerp is intended to be used by passing a value between 0 and 1 as the last parameter. So typically a timer is used and some ever-increasing fraction is used as the last parameter. But code like your is the predominant way that Lerp/Slerp is used in questions and answers on UA. Instaed of a linear movement, it produces a eased movement towards the goal. It works by passing the same fraction as the last parameter, but it updates the first parameter to be the current position/setting. The result is that at each call it moves the same fraction towards the goal, but since the distance is shrinking the same fraction is an ever decreasing distance. The result is an eased movement towards the goal. And while it gets close to the goal quickly, it runs for a long time before reaching the goal.
Taking a look at line 10 you have:
transform.localPosition = Vector3.Lerp(originalPosition, editingPosition, 1f * Time.deltaTime * (timeToTake * 10));
If you look at your first parameter, you are using 'originalPositon'. I'm not sure if this does what you want, but following the pattern of this kind of Lerp(), it should be:
transform.localPosition = Vector3.Lerp(transform.localPosition, editingPosition, 1f * Time.deltaTime * (timeToTake * 10));
Note, unless you are 'editingRotation' somewhere, I don't understand why your Slerp() is working. Also note, that if you really want a linear movement, you can use Vector3.MoveTowards() instead of Lerp().
Thanks for the reply. Ideally I'd like an eased movement, which is why I attempted to use a Lerp. Originally I used a predeter$$anonymous$$ed value (originalPosition) rather than 'transform.localPosition' because I wanted to ensure the gun always moves from the same location to the same location. It's a fall back even though it should move the same amount no matter what.
Just tried the 'transform.localPosition', though, and it didn't work.
I am perfor$$anonymous$$g a smooth rotation as well which is the reason for the Slerp. I'll try the Vector3.$$anonymous$$oveTowards, however...
Nope, it doesn't work for me at the moment with:
transform.localPosition = Vector3.$$anonymous$$oveTowards (transform.localPosition, editingPosition, 10f);
I don't understand why.
For $$anonymous$$oveTowards, you want this:
transform.localPosition = Vector3.$$anonymous$$oveTowards (transform.localPosition, editingPosition, Time.deltaTime * speed);
'speed' will be units per second. Lerp() should also work. You are using localPosition, so I have to wonder if anything is impacting the parent.
It is also helpful to me when something does not work, to describe how it is not working.
Right, I've got pictures to help describe it now.
On '$$anonymous$$ouse 1', hold
Basically, the second picture should look like:
On 'Return' down, toggle **should be this**
The third picture is my working script using Vector3.Lerp, using almost exactly the same script as my OP but without the Quaternion.Slerps.
I don't understand your pictures. What I can tell you is that the code I outlined is structurally correct. $$anonymous$$y first guess at the potential problem is that 'editingPosition' is a world position rather than a local position. If you are going to using localPosition, then 'editingPosition' needs to also be a local coordinate. If that is not the problem, then I suggest you start with a clean scene, a couple of simple objects, and a simple script to see if you have problems in a more controlled environment.
Okay, I'm pretty sure I've figured out the problem; I have two FixedUpdate functions in two different scripts attempting to translate the model if conditions are met. Ideally I need to stop the translation attempt as soon as it is finished. I think I can get the progression of the Lerp which I could use, couldn't I? Then I can just use it to ensure the Lerp stops when it finishes, correct? Thanks for all your help though, guys.