Everything about interpolation in Unity with C# code

2. Generate a Bezier curve

The Bezier curve is the most common spline, and is used to design streamlined cars (that's why the algorithm was invented), in Photoshop, and to make roads in the game Cities: Skylines. The basic idea is that you have 2 end points and 2 control points. To form the final spline you need to interpolate linearly in different layers with De Casteljau's algorithm. But why is it called a Bezier curve if we are using De Casteljau's algorithm? The answer is that poor De Casteljau came up with the algorithm and Bezier stole it a few years later and renamed it to Bezier! Anyway, the algorithm is best explained with a picture:

Explanation of the Bezier curve

A and D are the end points, and B and C are the control points. This will form a cubic curve. It is possible to add just one control point and you will end up with a quadratic curve, which is useful if you have limited processing power. For example, the game Quake 3 used quadratic Bezier curves. But a quadratic curve is less flexible than a cubic curve. You may also add more dimensions, so you can have as many control points as you want.

If A and D are fixed, you can move B and C to change the shape of the curve. But to make the curve itself, you first have to interpolate linearly between A and B, B and C, C and D. Now you have 3 new positions: Q, R, S. Now you are at a different "layer," so you have to interpolate linearly between Q and R, and R and S. To get the final point U you need on the Bezier curve, you interpolate linearly one final time between P and T. All these interpolations use the same t value. This is how it looks like in a script (To make it work you just need 4 spheres that make up the end points and control points):

using UnityEngine;
using System.Collections;

//Interpolation between 2 points with a Bezier Curve (cubic spline)
public class BezierCurve : MonoBehaviour 
{
    //Has to be at least 4 so-called control points
    public Transform startPoint;
    public Transform endPoint;
    public Transform controlPointStart;
    public Transform controlPointEnd;

    //Easier to use ABCD for the positions of the points so they are the same as in the tutorial image
    Vector3 A, B, C, D;

    //Display without having to press play
    void OnDrawGizmos()
    {
        A = startPoint.position;
        B = controlPointStart.position;
        C = controlPointEnd.position;
        D = endPoint.position;

	//The Bezier curve's color
        Gizmos.color = Color.white;

        //The start position of the line
        Vector3 lastPos = A;

        //The resolution of the line
        //Make sure the resolution is adding up to 1, so 0.3 will give a gap at the end, but 0.2 will work
        float resolution = 0.02f;

        //How many loops?
        int loops = Mathf.FloorToInt(1f / resolution);

        for (int i = 1; i <= loops; i++)
        {
            //Which t position are we at?
            float t = i * resolution;

            //Find the coordinates between the control points with a Catmull-Rom spline
            Vector3 newPos = DeCasteljausAlgorithm(t);

            //Draw this line segment
            Gizmos.DrawLine(lastPos, newPos);

            //Save this pos so we can draw the next line segment
            lastPos = newPos;
        }
		
	//Also draw lines between the control points and endpoints
        Gizmos.color = Color.green;

        Gizmos.DrawLine(A, B);
        Gizmos.DrawLine(C, D);
    }

    //The De Casteljau's Algorithm
    Vector3 DeCasteljausAlgorithm(float t)
    {
        //Linear interpolation = lerp = (1 - t) * A + t * B
        //Could use Vector3.Lerp(A, B, t)

        //To make it faster
        float oneMinusT = 1f - t;
        
        //Layer 1
        Vector3 Q = oneMinusT * A + t * B;
        Vector3 R = oneMinusT * B + t * C;
        Vector3 S = oneMinusT * C + t * D;

        //Layer 2
        Vector3 P = oneMinusT * Q + t * R;
        Vector3 T = oneMinusT * R + t * S;

        //Final interpolated position
        Vector3 U = oneMinusT * P + t * T;

        return U;
    }
}

That wasn't too difficult? If you go to the editor you should see this:

Final Bezier curve