**Section 1 – Implement Bézier Curve using C# in Unity**

Download the assets needed for this tutorial from https://faramira.com/downloads/jigsaw/assets_to_dowmload.zip.

You can find the entire source code of this project in the GitHub repo. https://github.com/shamim-akhtar/jigsaw-puzzle/tree/main

## View the Tutorial on YouTube

This tutorial is divided into four broad sections, with each containing one or more subsections.

**Section 1 – Implement Bézier Curve using C# in Unity****Section 2 – Create a Jigsaw Tile from an Existing Image****Section 3 – Create a Jigsaw Board from an Image****Section 4 – Create a Jigsaw Puzzle Game in Unity**

You are now reading the first section, **Section 1 – Implement Bézier Curve using C# in Unity**.

In the first section, we will learn how to implement the Bézier curve using C# in Unity.

We will then create a sample scene that displays the Bézier curve. We are starting with the Bézier curve, as we will use it to cut an image to create a jigsaw tile.

**What is a Bézier curve?**

A Bézier curve is a type of parametric curve that is used in computer graphics and animation to define smooth, continuous curves through a set of control points. Bézier curves are named after their inventor, Pierre Bézier, who used them to design car bodies at Renault in the 1960s.

A Bézier curve is defined by a set of control points, which are points that lie on or near the curve itself. The number of control points determines the degree of the curve, with a higher degree producing a more complex curve. The most common Bézier curves are cubic Bézier curves, which are defined by four control points.

To generate a Bézier curve, a series of intermediate points are calculated between the control points. These intermediate points are then used to connect the control points, creating a smooth, continuous curve. For a more detailed understanding of Bézier curves, refer to the **Wikipedia** page.

The generic definition of a point in the Bézier curve is

where* t* is a parameter that ranges from 0 to 1. It is often referred to as the “parameter of the curve” or the “curve parameter.”

When *t*=0, the Bézier curve evaluates to the starting point defined by the first control point P0. When t=1, the curve evaluates to the ending point defined by the last control point, Pn. Intermediate values of t produce points along the curve between the control points, resulting in the smooth interpolation characteristic of Bézier curves.

In essence, *t* controls the position along the curve and is used to generate points on the curve by interpolating between the control points.

** n** is the degree of the curve, and.

are the Binomial coefficients.

We can represent the Binomial coefficients as below.

We can simplify the main equation at the top to

where

are known as Bernstein basis polynomials of degree ** n. **In plain English, this equation defines a basis function used in spline interpolation, where

**is a parameter ranging from 0 to 1,**

*t***represents the index of the basis function, and**

*i***represents the degree of the B-spline curve. The equation calculates the contribution of each control point to the final curve position at parameter**

*n***.**

*t*For an* *** n**-degree curve, there will be

*n**+ 1*control point. When the number of control points is two (or a degree of one;

**= 1), a Bézier curve becomes a straight line and is equivalent to linear interpolation. When the number of control points is three (or a degree of 2; n = 2), a Bézier curve becomes a parabola.**

*n*Our first task will be to implement a Bézier curve given a set of control points. For the sake of this tutorial, we will implement the Bézier curve in C# using a predefined lookup table of values.

**The Unity Project**

Let’s create a new Unity2D project and name it **JigsawPuzzleGame**. Create a new scene or rename the default scene to **Scene_Bézier Curve**.

Now, please make a new folder in the **Assets **directory and call it **Scripts**. This folder is where we will put all our C# script files.

Right-click on the **Scripts **folder in the Unity Editor’s Project window and create a new C# script. Name it **Bézier Curve**. Double-click and open it in Visual Studio or your favourite editor. Remove **Monobehavior **(as we do not want this class to derive from Monobehavior), the **Start **and the **Update **methods.

Let’s create a class called Bézier Curve.

Right-click on the **Scripts **folder in the Unity Editor’s Project window and create a new C# script. Name it **BezierCurve**. Double-click and open it in Visual Studio or your favourite IDE. Remove **Monobehavior **(we do not want this class to derive from Monobehavior), the **Start **and the **Update **methods. The class should look like the one below.

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BezierCurve
{
}
```

Code language: C# (cs)

Now, let’s see what needs to be there in this class. At the least, we will require a function that returns an interpolated Bezier point given t, where t can be between 0 and 1 (both inclusive), and a list of control points. This function will correspond to the equation:

We can see that the inputs to the function are t and the list of control points. Go ahead and create the procedure that will return us a Bezier point given these two inputs.

```
public class BezierCurve
{
public static Vector3 Point3(float t, List<Vector3> controlPoints)
{
}
}
```

Code language: C# (cs)

Note that we made the function static so that we do not have to instantiate a BezierCurve class to get the Bezier points given a set of control points. This function should be self-sustainable and should do our job of calculating the Bezier point.

We now want to implement the actual calculation of the Bezier point. To do so, let’s analyse and break down the function below.

where

and

If we look from below to up, we will find that the three diagrams do not seem too difficult to implement. Let’s start from the bottom. Calculate the Binomial coefficient with inputs ** n** and

**; both integer values.**

*i*To do so, we will have to calculate the values of

- The Factorial of
*n,* - The Factorial of
, and*i* - The Factorial of
.*(n – i)*

We can implement a function called Factorial that calculates the factorial value given an integer input. Even better, we can precalculate the Factorial values of numbers up to a maximum value of ** n** (let’s say 16 or 20) and use that. So any Bezier curve that has a degree of this maximum value or less will be able to create the Bezier curve. Now, we can go beyond this maximum value and make a generic factorial function, but this value will suffice for our job for now.

```
public class BezierCurve
{
// a look up table for factorials. Capped to 16.
private static float[] Factorial = new float[]
{
1.0f,
1.0f,
2.0f,
6.0f,
24.0f,
120.0f,
720.0f,
5040.0f,
40320.0f,
362880.0f,
3628800.0f,
39916800.0f,
479001600.0f,
6227020800.0f,
87178291200.0f,
1307674368000.0f,
20922789888000.0f,
};
****
}
```

Code language: C# (cs)

With this lookup table, we are okay with proceeding with the implementation of the Binomial coefficient.

```
private static float Binomial(int n, int i)
{
float ni;
float a1 = Factorial[n];
float a2 = Factorial[i];
float a3 = Factorial[n - i];
ni = a1 / (a2 * a3);
return ni;
}
```

Code language: C# (cs)

Note that the function is private, as we will only allow internal access to this function. We did not do a validation check if n <= 16. We want the caller of this function to ensure that n <= 16.

Next, we will calculate the Bernstein basis polynomials shown by the following equation.

To do so, we will need to calculate the Binomial coefficient and the two power terms. We have already calculated the Binomial coefficient above. The below function shows the implementation of the calculation of Bernstein basis polynomials.

```
private static float Bernstein(int n, int i, float t)
{
float t_i = Mathf.Pow(t, i);
float t_n_minus_i = Mathf.Pow((1 - t), (n - i));
float basis = Binomial(n, i) * t_i * t_n_minus_i;
return basis;
}
```

Code language: C# (cs)

Finally, we calculate the Bezier point as given by the equation below.

This calculation is just the summation of the Bernstein basis polynomials for all the control points. We can implement it as follows.

```
public static Vector3 Point3(float t, List<Vector3> controlPoints)
{
int N = controlPoints.Count - 1;
if (N > 16)
{
Debug.Log("You have used more than 16 control points. The maximum control points allowed is 16.");
controlPoints.RemoveRange(16, controlPoints.Count - 16);
}
if (t <= 0) return controlPoints[0];
if (t >= 1) return controlPoints[controlPoints.Count - 1];
Vector3 p = new Vector3();
for (int i = 0; i < controlPoints.Count; ++i)
{
Vector3 bn = Bernstein(N, i, t) * controlPoints[i];
p += bn;
}
return p;
}
```

Code language: C# (cs)

We have successfully implemented the calculation of a Bezier point for a given set of control points at an interval ** t**.

If we want to get a whole list of Bezier points that represents the Bezier curve, then we will need to calculate the Bezier points for the entire duration starting from ** t = 0** (where the point is the same at the start control point) to

**(where the point is the same as the end control point). The interval duration will depend on the nature of the problem and the distance of the points. For simplicity, we can use 0.01 as the interval. Choosing 0.01 as an interval will mean that there will be 100 points in the Bezier curve.**

*t = 1*Let’s implement the method that returns the list of points representing the Bezier curve.

```
public static List<Vector3> PointList3(
List<Vector3> controlPoints,
float interval = 0.01f)
{
int N = controlPoints.Count - 1;
if (N > 16)
{
Debug.Log("You have used more than 16 control points. " +
"The maximum control points allowed is 16.");
controlPoints.RemoveRange(16, controlPoints.Count - 16);
}
List<Vector3> points = new List<Vector3>();
for (float t = 0.0f; t <= 1.0f + interval - 0.0001f; t += interval)
{
Vector3 p = new Vector3();
for (int i = 0; i < controlPoints.Count; ++i)
{
Vector3 bn = Bernstein(N, i, t) * controlPoints[i];
p += bn;
}
points.Add(p);
}
return points;
}
```

Code language: C# (cs)

Similarly, we can implement the same for Vector2, as shown below.

```
public static Vector2 Point2(float t, List<Vector2> controlPoints)
{
int N = controlPoints.Count - 1;
if (N > 16)
{
Debug.Log("You have used more than 16 control points. The maximum control points allowed is 16.");
controlPoints.RemoveRange(16, controlPoints.Count - 16);
}
if (t <= 0) return controlPoints[0];
if (t >= 1) return controlPoints[controlPoints.Count - 1];
Vector2 p = new Vector2();
for (int i = 0; i < controlPoints.Count; ++i)
{
Vector2 bn = Bernstein(N, i, t) * controlPoints[i];
p += bn;
}
return p;
}
public static List<Vector2> PointList2(
List<Vector2> controlPoints,
float interval = 0.01f)
{
int N = controlPoints.Count - 1;
if (N > 16)
{
Debug.Log("You have used more than 16 control points. " +
"The maximum control points allowed is 16.");
controlPoints.RemoveRange(16, controlPoints.Count - 16);
}
List<Vector2> points = new List<Vector2>();
for (float t = 0.0f; t <= 1.0f + interval - 0.0001f; t += interval)
{
Vector2 p = new Vector2();
for (int i = 0; i < controlPoints.Count; ++i)
{
Vector2 bn = Bernstein(N, i, t) * controlPoints[i];
p += bn;
}
points.Add(p);
}
return points;
}
```

Code language: C# (cs)

We have concluded our implementation of the **BezierCurve **class.

## Testing Bezier Curves

Rename the scene to **BezierTest**. We want to create a display for our control points. In the next section, we will create a prefab that we will use to display our control points on the scene.

### Point Prefab

Right-click and add a new Circle Sprite.

We will use this sprite to represent our control points. Rename the sprite to **Point**.

Select this sprite and click on **Add Component** from the **Inspector**. Select New Script and name it **Point_Viz**. Double-click the Point_Viz script and open it in Visual Studio or your favourite IDE.

We want this sprite to be able to be selected and dragged using our mouse. Go ahead and add the following code to your **Point_Viz.cs**.

Add a private variable named **mOffset**.

Add **OnMouseDown**, **OnMouseDrag **and **OnMouseUp **methods and implement the necessary code to use mouse click to select the sprite and drag to move it.

```
void OnMouseDown()
{
if (EventSystem.current.IsPointerOverGameObject())
{
return;
}
mOffset = transform.position - Camera.main.ScreenToWorldPoint(
new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0.0f));
}
void OnMouseDrag()
{
if (EventSystem.current.IsPointerOverGameObject())
{
return;
}
Vector3 curScreenPoint = new Vector3(
Input.mousePosition.x,
Input.mousePosition.y, 0.0f);
Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint) + mOffset;
transform.position = curPosition;
}
void OnMouseUp()
{
if (EventSystem.current.IsPointerOverGameObject())
{
return;
}
}
```

Code language: C# (cs)

To select this sprite, we will also need to add a Collider to the sprite. Select this sprite and add a new component called **Circle Collider 2D**.

Create a new folder called **Resources **in **Assets**. Now, create a new folder called **Prefabs **in the **Resources **folder.

Drag and drop this **Point **sprite into the **Prefabs **folder, name it **PointPrefab** and then remove **Point **from the scene.

### Bezier Curve Visualization

Right-click on the Hierarchy window and add a new **Empty **GameObject.

Rename this empty game object to **Bezier_Viz**. We will use this game object to display our Control Points and the Bezier curve.

Select **Bezier_Viz **and add a new script component called **Bezier_Viz**. Double-click on the **Bezier_Viz **script and open it in Visual Studio or your favourite IDE.

Add the following variables to the **Bezier_Viz.cs **file.

First of all, we add a public variable of type List<Vector2> called **ControlPoints. **This will hold the first few control points that we set from the Unity Editor.

Then, we will use a public variable that will hold the **PointPrefab**. We will create instances of this prefab to display our control points.

We will use **LineRenderer **to show our lines and curves. We want to have two LineRenderer; the first one is to show straight lines connecting the various control points, and the second one is to show the Bezier curve.

Then, we want to have a List<GameObject> to hold our instantiated control point game objects.

The final few parameters are for decorative purposes. We will allow setting the line width and line colour from the Unity editor.

We are now all set to implement the necessary functionality. Now we are all set. Before we run the program, we will need to do some settings in our Unity editor.

### Setting Values in Unity Editor

Go to your Unity editor. Select the **Bezier_Viz **game object from the hierarchy. Drag and drop the **PointPrefab **to the **Point Prefab** field of the **Bezier_Viz **script component (shown below).

Also, add an **EventSystem **so that we can capture mouse inputs.

Create **three** control points, as shown below. Set the values for each of these control points. Set the **Line Width** to be **0.05**.

Click Play. You should see it as shown below.

## Enhancements

In the following section, we will implement one new functionality. This functionality allows for the addition of new control points. We will allow the addition of new control points by double-clicking on the screen (up to a maximum number of 16).

Open the **Bezier_Viz.cs **file and add the following code

```
void OnGUI()
{
Event e = Event.current;
if (e.isMouse)
{
if (e.clickCount == 2 && e.button == 0)
{
Vector2 rayPos = new Vector2(
Camera.main.ScreenToWorldPoint(Input.mousePosition).x,
Camera.main.ScreenToWorldPoint(Input.mousePosition).y);
InsertNewControlPoint(rayPos);
}
}
}
void InsertNewControlPoint(Vector2 p)
{
if (mPointGameObjects.Count >= 16)
{
Debug.Log("Cannot create any new control points. Max number is 16");
return;
}
GameObject obj = Instantiate(PointPrefab, p, Quaternion.identity);
obj.name = "ControlPoint_" + mPointGameObjects.Count.ToString();
mPointGameObjects.Add(obj);
}
```

Code language: C# (cs)

Run the program by clicking on the Play button in Unity. Double-click to add new control points, as shown below.

We have completed Section 1 of the tutorial. In the next section, we will learn how to create a Jigsaw tile from an existing image using the Bezier curve.

A committed and optimistic professional who brings passion and enthusiasm to help motivate, guide and mentor young students into their transition to the Industry and reshape their careers for a fulfilling future. **The past is something that you cannot undo. The future is something that you can build**.

*I enjoy coding, developing games and writing tutorials. *Visit my GitHub to see the projects I am working on right now.

Educator | Developer | Mentor

Hii sir, thanks for the tutorials, they are great. And one question, when will you release the rest of the tutorial 4?

Hello Akshit. It’s good to hear that you found the tutorials helpful. I plan to complete the remaining part of the tutorial but couldn’t find the time to complete it. The remaining portions are loading and saving the game, the state machine to control the game states. The codes for this is available on my GitHub https://github.com/shamim-akhtar/jigsaw-puzzle repo.

I intend to complete the remaining part of the tutorial by November.

Hi!! Thanks for the tutorial. I would like to ask how to make to work with Render Texture?

I would like to take the image for the puzzle from Render Texture.

Highly descriptive blog, I enjoyed that bit. Will there be a part 2?

Hi there. Thank you. The tutorial has multiple pages.

Section 1 – Implement Bézier Curve using C# in Unity

Section 2 – Create a Jigsaw Tile from an Existing Image

Section 3 – Create a Jigsaw Board from an Image

Section 4 – Create a Jigsaw Puzzle Game in Unity

The last section is under development and I intend to complete it by this week. Hope that it helps.

Hi colleagues, nice post and nice urging commented here, I am truly enjoying by these.

I am extremely impressed with your writing skills

as well as with the format in your blog. Is that this a paid subject

or did you modify it your self? Anyway stay up the excellent quality writing, it is uncommon to peer a great weblog like this one these days..