# 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:

Using Vector3.Lerp() correctly in Unity — One Man’s Trash is Another Man’s Blog (archive.org)

It’s working fine but what I would need is to add some curves between the different lerps.

A little scheme to explain my problem:
[48503-curves.jpg|48503]

My script so far:

``````IEnumerator StartOverview()
{
//those are not important
cameraScript=GameObject.FindGameObjectWithTag("Camera").GetComponent<GravityChange>();
cameraScript.SetControl(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*, positions[i-1]);
else
_timeTakenDuringLerp=Vector3.Distance(positions*, positions[positions.Length-1]);
timeTakenDuringLerp/=10;
//initiating values
_timeStartedLerping = Time.time;
_startPosition = cameraTrans.position;
_endPosition = positions*;
_startRotation = cameraTrans.rotation;
_endRotation = Quaternion.Euler(rotations*);
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);
}
``````

What I’ve tried without success:

``````//where _nextposition is positions[i+1] or position[0] if we have to finish the loop
_endPosition = positions(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!

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 formula 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;
}
``````

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, 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, positions[i-1]+(positions-positions[i-1])*2)+ Vector3.Distance(positions[i-1]+(positions_-positions[i-1])*2, positions[i+1])+Vector3.Distance(positions[i+1], positions[i+2]);
else
timeTakenDuringLerp=Vector3.Distance(positions, positions[i-1]+(positions-positions[i-1])*2)+ Vector3.Distance(positions[i-1]+(positions_-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;
if(i!=0 && i!=positions.Length-1)
{
P1=positions[i-1]+(positions_-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_-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.