- Home /
Curve between Lerps
Hi,
I'm doing an overview of my level before starting it so I set some Vector3 array for positions and another for rotations. I'm using the method posted here so I can have lerps that occurs with a constant speed: http://www.blueraja.com/blog/404/how-to-use-unity-3ds-linear-interpolation-vector3-lerp-correctly
It's working fine but what I would need is to add some curves between the different lerps.
A little sheme to explain my problem:
My script so far:
IEnumerator StartOverview()
{
//those are not important
cameraScript=GameObject.FindGameObjectWithTag("Camera").GetComponent<GravityChange>();
cameraScript.SetControl(false);
GameControl.Instance.canAccessMenu=false;
Transform cameraTrans = cameraScript.transform;
//it starts here by declaring some variables
int i=1;
float _timeStartedLerping;
Vector3 _startPosition;
Vector3 _endPosition;
Quaternion _startRotation;
Quaternion _endRotation;
float timeSinceStarted;
float percentageComplete;
float timeTakenDuringLerp;
Quaternion rot=Quaternion.Euler(rotations[0]);
//setting the camera position+rotation to the first position+rotation
cameraTrans.position=positions[0];
cameraTrans.rotation=rot;
while(!HUDScript.instance.touch) //while screen is not touched
{
//those are ensuring the lerp is going the same speed all along (time according to distance)
if(i!=0)
timeTakenDuringLerp=Vector3.Distance(positions[i], positions[i-1]);
else
timeTakenDuringLerp=Vector3.Distance(positions[i], positions[positions.Length-1]);
timeTakenDuringLerp/=10;
//initiating values
_timeStartedLerping = Time.time;
_startPosition = cameraTrans.position;
_endPosition = positions[i];
_startRotation = cameraTrans.rotation;
_endRotation = Quaternion.Euler(rotations[i]);
percentageComplete=0;
while(percentageComplete<1)
{
//the lerp with the method I provided in the link
timeSinceStarted = Time.time - _timeStartedLerping;
percentageComplete = timeSinceStarted / timeTakenDuringLerp;
cameraTrans.position = Vector3.Lerp (_startPosition, _endPosition, percentageComplete);
cameraTrans.rotation=Quaternion.Lerp(_startRotation, _endRotation, percentageComplete);
yield return null;
}
i++;
if(i==positions.Length)
i=0;
}
//not important
HUDScript.instance.overviewOver=true;
cameraScript.SetControl(true);
GameControl.Instance.canAccessMenu=true;
}
What I've tried without success:
//where _nextposition is positions[i+1] or position[0] if we have to finish the loop
_endPosition = positions[i]*(1-percentageComplete) + _nextPosition*percentageComplete;
cameraTrans.position = Vector3.Lerp (_startPosition, _endPosition, percentageComplete)*(1-percentageComplete) + _nextPosition*percentageComplete;
cameraTrans.position = Vector3.Lerp (_startPosition, _endPosition, percentageComplete)*(1-percentageComplete) + Vector3.Lerp (_endPosition, _nextPosition, percentageComplete)* percentageComplete;
All of these 3 methods lead to quite the same result being the lerps aren't regular anymore since I play with the end of the lerp. But i don't see how I would do without playing with it.
All help would really be appreciated!
I found a part of the solution here: http://devmag.org.za/2011/04/05/bzier-curves-a-tutorial/ Now I'm about to find a good way to implement this.
Answer by barbe63 · Jun 20, 2015 at 04:10 AM
Fixed it after a night struggling!
Here is my new script for those who would be interested to do the same thing (uncommented):
IEnumerator StartOverview()
{
int i=0;
float _timeStartedLerping;
float timeSinceStarted;
float percentageComplete;
float timeTakenDuringLerp;
Vector3 _P0, _P1, _P2, _P3;
Vector3 lastPosition=cameraTrans.position;
Vector3 direction=cameraTrans.position;
bool mustChangeDirection=true;
cameraTrans.position=positions[0];
cameraTrans.rotation=Quaternion.LookRotation(CalculateBezierPoint(0.05f, positions[0], positions[1], positions[2], positions[3])-cameraTrans.position);
while(!HUDScript.instance.touch) //while screen is not touched
{
if(i==0)
timeTakenDuringLerp=Vector3.Distance(positions[i], positions[i+1])+ Vector3.Distance(positions[i+1], positions[i+2])+Vector3.Distance(positions[i+2], positions[i+3]);
else if(i!=positions.Length-1)
timeTakenDuringLerp=Vector3.Distance(positions[i], positions[i-1]+(positions[i]-positions[i-1])*2)+ Vector3.Distance(positions[i-1]+(positions[i]-positions[i-1])*2, positions[i+1])+Vector3.Distance(positions[i+1], positions[i+2]);
else
timeTakenDuringLerp=Vector3.Distance(positions[i], positions[i-1]+(positions[i]-positions[i-1])*2)+ Vector3.Distance(positions[i-1]+(positions[i]-positions[i-1])*2, positions[1]+(positions[0]-positions[1])*2)+Vector3.Distance(positions[1]+(positions[0]-positions[1])*2, positions[0]);
timeTakenDuringLerp/=10;
_timeStartedLerping = Time.time;
_P0 = positions[i];
if(i!=0 && i!=positions.Length-1)
{
_P1=positions[i-1]+(positions[i]-positions[i-1])*2;
_P2=positions[i+1];
_P3=positions[i+2];
}
else if(i==0)
{
_P1=positions[1];
_P2=positions[2];
_P3=positions[3];
}
else
{
_P1=positions[i-1]+(positions[i]-positions[i-1])*2;
_P2=positions[1]+(positions[0]-positions[1])*2;
_P3=positions[0];
}
percentageComplete=0;
while(percentageComplete<1)
{
timeSinceStarted = Time.time - _timeStartedLerping;
percentageComplete = timeSinceStarted / timeTakenDuringLerp;
cameraTrans.position = CalculateBezierPoint(percentageComplete, _P0, _P1, _P2, _P3);
if(mustChangeDirection)
direction=cameraTrans.position-lastPosition;
else
mustChangeDirection=true;
cameraTrans.rotation=Quaternion.Lerp(cameraTrans.rotation, Quaternion.LookRotation(direction), Time.deltaTime);
lastPosition=cameraTrans.position;
yield return null;
}
mustChangeDirection=false;
if(i!=0)
i+=2;
else
i+=3;
if(i>=positions.Length)
i=0;
}
}
Vector3 CalculateBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
{
float u = 1 - t;
float tt = t * t;
float uu = u * u;
float uuu = uu * u;
float ttt = tt * t;
Vector3 p = uuu * p0;
p += 3 * uu * t * p1;
p += 3 * u * tt * p2;
p += ttt * p3;
return p;
}
The rotations are now handled based on the direction of the camera.
The array positions is to be set like this: The first point, the first bezier anchor of the first point, the second bezier anchor of the first point, the second point, the second bezier anchor of the second point, the third point, the second bezier anchor of the third point ...etc and finally the last point.
Answer by Bunny83 · Jun 20, 2015 at 01:28 AM
Bezier curves are actually quite simple. Your example is a quadratic bezier curve and could be calculated with 3 lerps as you can see in the animated image on the wiki page. However usually you use a single folmula to directly get the position for a certain "t" value based on the 3 points: (start, contol1, end).
public static Vector3 Bezier2(Vector3 s, Vector3 p, Vector3 e, float t)
{
float rt = 1-t;
return rt*rt * s + 2 * rt * t * p + t*t* e;
}
Yes I found a degree-three version of that and I solved my issue with it. Thanks anyway!
Answer by iluqmansharif · Dec 16, 2017 at 09:22 PM
Hey! @barbe63 Can you send me your whole script? I kinda need it for similar task. Thanks in advance!
Your answer
![](https://koobas.hobune.stream/wayback/20220613201204im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
crouch Uncrouch speed with animation curve 1 Answer
How can I make a Lerp move in an arc instead of a straight line? 2 Answers
moving a gamobject in vacum 2 Answers
Vector3.Lerp doesn't work on build 0 Answers
Lerp tutorial missing variable value 1 Answer