## Our Biggest Black Friday Sale — Ever!

Introducing unlimited access to all courses, all books, and our new monthly live professional development series! Just \$899 \$399 per year during our Black Friday event

Ends in... ::

# Runtime Mesh Manipulation With Unity

One of the benefits of using Unity as your game development platform is its powerful 3D engine. In this tutorial, you’ll get an introduction to the world of 3D objects and mesh manipulation.

4.8/5 27 Ratings

#### Version

• C# 7.3, Unity 2019.1, Unity
Update note: Sean Duffy updated this tutorial for Unity 2019.1.2. Arai Lanju wrote the original.

Welcome to the world of 3D objects and mesh manipulation! One of the benefits of using Unity as your game development platform is its powerful 3D engine. That 3D engine, along with Unity’s ability to use custom editors, makes the development of 3D games and apps so much easier.

With the growth of virtual reality and augmented reality (VR/AR) technology, most developers will inadvertently find themselves wrestling with the gritty bits of 3D concepts. So let this tutorial be your starting point. Don’t worry, there will be no complicated 3D math here — just lots of hearts, drawings, arrows and loads of fun!

Note: This tutorial is intended for users who are familiar with the Unity editor and have some experience with C# programming. If you need to brush up on these topics, check out Introduction to Unity UI and Introduction to Unity Scripting first.

This tutorial uses a custom editor. You can learn more about custom editors at Extending the Unity Editor.

## Getting Started

### Understanding Meshes

Time to start with the basic vocabulary of 3D rendering. The shape of a 3D object is defined by its mesh. A mesh is like a net of points, or vertices. The invisible lines that connect these vertices form triangles, which define the basic shape of the object.

But in addition to the shape, the engine needs to know how to draw the surface of the object. So a mesh’s data also includes its normals, which are vectors that determine which way a particular triangle is facing, and thus how light bounces off of it. Finally, a UV Map maps a material to an object, specifying how textures wrap around the shape.

In Unity, there are two primary rendering components: The Mesh Filter, which stores the mesh data of a model, and the Mesh Renderer, which combines the mesh data with materials to render the object in the scene.

Got all that? Here’s a cheat sheet for easy reference:

• Vertices: A vertex is a point in 3D space. Often abbreviated to “vert”.
• Lines/Edges: The invisible lines that connect vertices to one another.
• Triangles: Formed when edges connect three vertices.
• UV Map: Maps a material to an object, specifying how textures wrap around the object’s shape.
• Normals: The directional vector of a vertex or a surface. This characteristically points outward, perpendicular to the mesh surface, and helps determine how light bounces off of the object.
• Mesh: Holds all the vertices, edges, triangles, normals and UV data of a model.

Here are the basic steps (in pseudocode) to create a 3D mesh:

• Create a new mesh named “myMesh”.
• Add data to myMesh’s vertices and triangle properties.
• Create a new mesh filter named “myMeshFilter”.
• Assign myMesh to myMeshFilter’s mesh property.

### Setting Up the Project

Now that you have the basics covered, download the project using the Download Materials button at the top or bottom of this page, then unpack the files and open the starter project in Unity. Check out the folder structure in the Project view:

• Prefabs: This contains a CustomHeart prefab, which you’ll use to save your 3D mesh at runtime.
• Scenes: This contains the three scenes that you will use for the different parts of this tutorial.
• Editor: The scripts inside this folder give you special powers in the editor during development.
• Scripts: This contains runtime scripts, or components. When you attach these components to a GameObject, they’ll execute when you click Play.
• Materials: This folder contains the material for the mesh you’ll be working with.

In the next section, you will create a custom editor to visualize the parts of a 3D mesh.

## Poking and Prodding Meshes With a Custom Editor

Open 01 Mesh Study Demo inside RW/Scenes. In the Scene view, you will see a humble cube:

You’re going to build a custom editor to tear this poor cube apart! (And then you’ll learn how to keep it in one piece.)

### Customizing the Editor Script

Select the Editor folder in the Project view. Scripts in this special folder modify how the Unity editor works; they do not become part of the built game.

Open MeshInspector.cs and view the source code. Note that this class inherits from Unity’s base `Editor` class — that’s what makes Unity understand this is a custom editor rather than a game script.

The first step is to tell Unity what kind of objects that this special editor should draw. Add this attribute on the line above the `MeshInspector` class declaration:

```[CustomEditor(typeof(MeshStudy))]
```

Now, when any GameObject with the Mesh Study component attached to it is visible in the Scene view, this class will handle drawing it. But right now, you won’t know if that’s happening.

`OnSceneGUI` is an event method that Unity calls every time it renders the Scene view in the editor. It’s your chance to modify how Unity draws your object in the scene. Add the following at the beginning of `OnSceneGUI`:

```mesh = target as MeshStudy;
Debug.Log("Custom editor is running");
```

The base `Editor` class provides a reference to the object you’re customizing in the `target` variable, which has type `Object`. You can’t do much that’s useful with a plain vanilla `Object`, so this code casts `target` as the type `MeshStudy`. Logging a message allows you to see in the console that the custom editor is indeed running.

Save the file and return to Unity. Go to the RW/Scripts folder and drag MeshStudy.cs onto the Cube GameObject in the Hierarchy to attach the component to it.

Look in the console and make sure your code is running. Then go ahead and remove the `Debug.Log` line so it doesn’t flood your console.

### Cloning a Mesh

When you’re working with a 3D mesh with a custom editor in Edit mode, it is easy to accidentally overwrite Unity’s default mesh — that is, the built-in Sphere, Cube, Cylinder and so on. If that happens, you’ll need to restart Unity.

To avoid this, you’ll clone the mesh before making any changes to it in Edit mode.

Open MeshStudy.cs. This script inherits from `MonoBehaviour`, so its `Start` will not run in Edit mode. Luckily, that’s easy to fix!

In MeshStudy, above the class declaration, add the following:

```[ExecuteInEditMode]
```

When a class has this attribute, its `Start` will fire in both Play mode and Edit mode. Now that you’ve added it, you can instantiate and clone your mesh object before changing anything.

Add the following code to `InitMesh`:

```meshFilter = GetComponent<MeshFilter>();
originalMesh = meshFilter.sharedMesh; //1
clonedMesh = new Mesh(); //2

clonedMesh.name = "clone";
clonedMesh.vertices = originalMesh.vertices;
clonedMesh.triangles = originalMesh.triangles;
clonedMesh.normals = originalMesh.normals;
clonedMesh.uv = originalMesh.uv;
meshFilter.mesh = clonedMesh;  //3

vertices = clonedMesh.vertices; //4
triangles = clonedMesh.triangles;
isCloned = true; //5
Debug.Log("Init & Cloned");
```

Here’s what’s happening:

1. Grabs whatever mesh you’ve originally assigned in `MeshFilter`.
2. Creates a new mesh instance called `clonedMesh` and sets its properties by copying the first mesh.
3. Assigns the copied mesh back to the mesh filter.
4. Updates local variables, which you’ll need later.
5. Sets `isCloned` to `true`; you’ll reference this later.

Save the file and return to Unity. The console should show the message “Init & Cloned”.

Select `Cube` in the Hierarchy and look at the Inspector. The Mesh Filter will show a mesh named clone. Great! This means you have cloned the mesh successfully.

But notice there’s no new Mesh asset in your project — the cloned mesh only lives in Unity’s memory right now, and it will disappear if you close the scene. You’ll learn how to save a Mesh later.

### Resetting a Mesh

For now, you want to give yourself an easy way to reset your mesh so you can play around without fear. Go back to MeshInspector.cs.

`OnInspectorGUI` lets you customize the Inspector for your object with extra GUI elements and logic. In `OnInspectorGUI`, find the comment `//draw reset button` and replace it with the following:

```if (GUILayout.Button("Reset")) //1
{
mesh.Reset(); //2
}
```
1. This code draws a Reset button in the Inspector. The draw function returns `true` when it’s pressed.
2. When pressed, the button calls `Reset` in MeshStudy.cs.

Save the file and return to MeshStudy.cs. Add the following to `Reset`:

```if (clonedMesh != null && originalMesh != null) //1
{
clonedMesh.vertices = originalMesh.vertices; //2
clonedMesh.triangles = originalMesh.triangles;
clonedMesh.normals = originalMesh.normals;
clonedMesh.uv = originalMesh.uv;
meshFilter.mesh = clonedMesh; //3

vertices = clonedMesh.vertices; //4
triangles = clonedMesh.triangles;
}
```

Here’s what this code does step-by-step:

1. Checks that both the original mesh and the clone mesh exist, in case the object’s mesh filter doesn’t have any data in it.
2. Resets all the properties of `clonedMesh` to those of the original mesh.
3. Assigns `clonedMesh` back to the Mesh Filter component.

In the Inspector, click on the Test Edit button to mess with the cube’s mesh, then press the Reset button to restore it.

### Understanding Vertices and Triangles With Unity

As you saw earlier, a mesh consists of vertices connected by edges to form triangles. Triangles define the basic shape of the object.

Note: Unity’s `Mesh` class keeps track of vertices and triangles with two arrays:
• It stores vertices as an array of `Vector3`.
• It stores triangles as an array of integers. Each integer is the index of one of the vertices in the verts array, and each group of three consecutive integers represents one triangle.

For example, the group `triangles[0], triangles[1], triangles[2]` represents one triangle, the group `triangles[3], triangles[4], triangles[5]` represents the next triangle and so on.

So, in a simple Quad mesh that consists of four vertices and two triangles, the Quad’s mesh data would be:

### Visualizing Vertices

It will be easier to see how this works if you can draw and move around the vertices on a mesh with handles. Handles are tools for working with objects in the Scene view, like the draggable sphere for the Rotate tool. Now, you’re going to write your own handle!

In MeshInspector.cs, look for `EditMesh` and add the following:

```handleTransform = mesh.transform; //1
handleRotation = Tools.pivotRotation == PivotRotation.Local ?
handleTransform.rotation : Quaternion.identity; //2
for (int i = 0; i < mesh.vertices.Length; i++) //3
{
ShowPoint(i);
}
```
1. Gets the mesh's transform, which you'll need to know where to draw the vertices in world space.
2. Gets the current pivot Rotation mode, to draw the handle the same way as everything else in the scene.
3. Loops through the mesh's vertices and draws dots with `ShowPoint`.

In `ShowPoint`, replace the `//draw dot` comment with:

```Vector3 point = handleTransform.TransformPoint(mesh.vertices[index]); //1
Handles.color = Color.blue;
point = Handles.FreeMoveHandle(point, handleRotation, mesh.handleSize,
Vector3.zero, Handles.DotHandleCap); //2
```
1. This line converts the vertex's local position into world space.
2. Draws the dot using the `Handles` utility class.

`Handles.FreeMoveHandle` makes an unconstrained movement handle, which you will use in the next section to enable dragging the points around.

Check the Cube's MeshInspector and make sure that you've checked Move Vertex Point.

You should now see the vertices of the mesh marked with blue dots on screen. Try attaching the script to other 3D objects and see the results for yourself! :]

### Moving a Single Vertex

You'll start with the most basic kind of mesh manipulation: Moving a single vertex.

Open MeshInspector.cs. Inside `ShowPoint`, replace the `//drag` comment with the following:

```if (GUI.changed) //3
{
mesh.DoAction(index, handleTransform.InverseTransformPoint(point)); //4
}
```
1. `GUI.changed` monitors any changes made to the dots, which works nicely with `Handles.FreeMoveHandle` to detect a dragging action.
2. On dragging a vertex, call `mesh.DoAction` with the index of the vertex and the vertex's position as parameters. This line also converts the vertex's position back to local space with `InverseTransformPoint`.

Save MeshInspector.cs and go to MeshStudy.cs. Add the following in `DoAction`:

```PullOneVertex(index, localPos);
```

Then add the following to `PullOneVertex`:

```vertices[index] = newPos; //1
clonedMesh.vertices = vertices; //2
clonedMesh.RecalculateNormals(); //3
```
1. Updates the target vertex's position.
2. Assigns the updated vertices array back to the cloned mesh.
3. Tells Unity to re-draw the mesh to reflect the change.

Save the script and return to Unity. Try dragging one of the dots on the cube.

It seems like some of the vertices share the same position, so when you pull only one, the other vertices stay behind and your mesh breaks. You'll learn how to fix this problem shortly. :]

### Looking at the Vertices Array

Visually, a cube mesh consists of eight vertices, six sides and 12 triangles. Time to see if Unity agrees.

Go to MeshStudy.cs, and before `Start`, look for a variable named `vertices`. You'll see that it has the `[HideInInspector]` attribute.

Temporarily comment out that attribute for a quick peek into the array:

```//[HideInInspector]
public Vector3[] vertices;
```

Note: More complicated 3D meshes can have thousands of vertices. Unity will freeze up if it tries to show all those values in the Inspector, so in general, you'll hide the array with `[HideInInspector]`. You're just peeking!

Save the file, return to Unity and look at your cube. You can now see the vertices property on Mesh Study. Click on the arrow icon beside it to show the array of `Vector3` elements.

You can see that the array size is 24, which means that there are definitely vertices sharing the same position! Take a moment and think about why there might be multiple vertices in the same place.

[spoiler title = "Why 24 Vertices?"]
A cube has six sides and each side has four vertices that form a plane. 6 × 4 = 24 vertices.

There are other ways to think about this, if this is hard to grasp. But for now, just know that some meshes will have vertices that share the same position.

[/spoiler]

Since you're done peeking into the verts array, go ahead and uncomment `[HideInInspector]`.

### Finding All Similar Vertices

You can see that manipulating a mesh is going to take more than just moving single vertices — you have to move all the vertices for a particular point in space in order to keep the mesh together. So you're now ready to unbreak your heart, er, mesh.

In MeshStudy.cs, replace all the code inside `DoAction` with:

```PullSimilarVertices(index, localPos);
```

Go to `PullSimilarVertices` and add the following:

```Vector3 targetVertexPos = vertices[index]; //1
List<int> relatedVertices = FindRelatedVertices(targetVertexPos, false); //2
foreach (int i in relatedVertices) //3
{
vertices[i] = newPos;
}
clonedMesh.vertices = vertices; //4
clonedMesh.RecalculateNormals();
```
1. Gets the target vertex position from the `vertices` array.
2. Finds all the vertices that share the same position as the target vertex and puts their indices into a list.
3. Loops through that list and updates the position of all related vertices.
4. Assigns the updated `vertices` back to `clonedMesh.vertices`, then redraws the mesh.

Save the file and return to Unity. Click and drag any of the vertices; the mesh should now retain its form without breaking.

Save the scene. You've taken the first step towards being a mesh magician!

## Manipulating Meshes

Editing meshes in Unity is fun, but what if you could add some "squish" to your game by deforming meshes at runtime? Next, you'll try that out in its most basic form — pushing and pulling some predefined vertices.

No math...

### Collecting the Selected Indices

You'll start by making a custom editor that lets you select the vertices to move around in real time. Open up the 02 Create Heart Mesh scene inside RW/Scenes. You'll see a red sphere in the Scene view.

Select the Sphere in the Hierarchy and look at the Heart Mesh component. This is the script that will store the verts you select.

But right now, there aren't any verts shown in the scene. So next, you're going to fix that!

Open RW/Editor/HeartMeshInspector.cs. In `ShowHandle`, inside the `if` statement, add the following code:

```Handles.color = Color.blue;
if (Handles.Button(point, handleRotation, mesh.pickSize, mesh.pickSize,
Handles.DotHandleCap)) //1
{
}
```
1. This makes Unity draw the vertices of the mesh as buttons, so you can click on them.
2. When you click the button, it adds the selected index to the `mesh.selectedIndices` list.

Add the following code at the end of `OnInspectorGUI`, after the existing `if` statement:

```if (GUILayout.Button("Clear Selected Vertices"))
{
mesh.ClearAllData();
}
```

This adds a custom Reset button in the Inspector. Next, you'll write the code to clear out your selection.

Save the file and open RW/Scripts/HeartMesh.cs. In `ClearAllData`, add the following:

```selectedIndices = new List<int>();
targetIndex = 0;
targetVertex = Vector3.zero;
```

This clears the values in the `selectedIndices` list and sets `targetIndex` to zero. It also resets the `targetVertex` position.

Save the file and return to Unity. Select the Sphere and look at its HeartMesh component. Make sure you've checked Is Edit Mode so you can see the mesh's vertices in the Scene view. Then click on the arrow icon next to Selected Indices to show the array.

Click on a few blue dots and watch new entries appear in Selected Indices. Try out your Clear Selected Vertices button to make sure it clears all values correctly.

Note: You have the option to show/hide the transform handle with Show Transform Handle in the custom Inspector, since it can get in the way of selecting verts. Just remember not to panic when you find the Transform handle missing from your other scenes! Be sure to switch it back on before you exit.

### Deforming the Sphere Into a Heart Shape

Updating mesh vertices in real time requires three steps:

1. Copy the current mesh vertices (before animation) to `modifiedVertices`.
2. Do calculations and update values on `modifiedVertices`.
3. Copy `modifiedVertices` to the current mesh on every step change and get Unity to redraw the mesh.

Go to HeartMesh.cs and add the following variables before `Start`:

```public float radiusOfEffect = 0.3f; //1
public float pullValue = 0.3f; //2
public float duration = 1.2f; //3
int currentIndex = 0; //4
bool isAnimate = false;
float startTime = 0f;
float runTime = 0f;
```

Moving a vertex should have some influence on the vertices around it to maintain a smooth shape. These variables control that effect.

1. Radius of area affected by the targeted vertex.
2. The strength of the pull.
3. How long the animation will run.
4. Current index of the `selectedIndices` list.

In `Init`, before the `if` statement, add:

```currentIndex = 0;
```

This sets `currentIndex` — the first index of the `selectedIndices` list — to 0 at the beginning of the game.

Still in `Init`, before the closing braces of the `else` statement, add:

```StartDisplacement();
```

`StartDisplacement` is what actually moves the vertices. It only runs when `isEditMode` is false.

Right now, this method does nothing, so add the following to `StartDisplacement`:

```targetVertex = originalVertices[selectedIndices[currentIndex]]; //1
startTime = Time.time; //2
isAnimate = true;
```
1. Singles out the `targetVertex` from the `originalVertices` array to start the animation. Remember, each array item is a List of integer values.
2. Sets the start time to the current time and changes `isAnimate` to `true`.

After `StartDisplacement`, create a new method called `FixedUpdate` with the following code:

```protected void FixedUpdate() //1
{
if (!isAnimate) //2
{
return;
}

runTime = Time.time - startTime; //3

if (runTime < duration)  //4
{
Vector3 targetVertexPos =
meshFilter.transform.InverseTransformPoint(targetVertex);
}
else //5
{
currentIndex++;
if (currentIndex < selectedIndices.Count) //6
{
StartDisplacement();
}
else //7
{
originalMesh = GetComponent<MeshFilter>().mesh;
isAnimate = false;
}
}
}
```

Here's what the code is doing:

1. The `FixedUpdate` method runs on a fixed interval, meaning that it's frame rate independent. Read more about it here.
2. If `isAnimate` is false, it won't do anything.
3. Keeps track of how long the animation has been running.
4. If the animation hasn't been running too long, it continues the animation by getting the world space coordinates of `targetVertex` and calling `DisplaceVertices`.
5. Otherwise, time's up! Adds one to `currentIndex` to start processing the animation for the next selected vertex.
6. Checks if all the selected vertices have been processed. If not, calls `StartDisplacement` with the latest vertex.
7. Otherwise, you've reached the end of the list of selected vertices. This line makes a copy of the current mesh and sets `isAnimate` to `false` to stop the animation.

### Making the Vertices Move Smoothly

In `DisplaceVertices`, add the following:

```Vector3 currentVertexPos = Vector3.zero;

for (int i = 0; i < modifiedVertices.Length; i++) //2
{
currentVertexPos = modifiedVertices[i];
float sqrMagnitude = (currentVertexPos - targetVertexPos).sqrMagnitude; //3
{
continue; //4
}
float distance = Mathf.Sqrt(sqrMagnitude); //5
Vector3 translate = (currentVertexPos * force) * falloff; //6
translate.z = 0f;
Quaternion rotation = Quaternion.Euler(translate);
Matrix4x4 m = Matrix4x4.TRS(translate, rotation, Vector3.one);
modifiedVertices[i] = m.MultiplyPoint3x4(currentVertexPos);
}
originalMesh.vertices = modifiedVertices; //7
originalMesh.RecalculateNormals();
```

This code loops over every vertex in the mesh and displaces those that are close to the ones you selected in the editor. It does some math tricks to create a smooth, organic effect, like pushing your thumb into clay. You'll learn more about this later on.

Here's a closer look at what this code does:

1. Gets the square of the radius.
2. Loops through every vertex in the mesh.
3. Finds the distance between the current vertex and the target vertex and squares it.
4. If this vertex is outside the area of effect, exits the loop early and continues to the next vertex.
5. Otherwise, calculates the `falloff` value based on the distance. Gaussian functions create a smooth bell curve.
6. Calculates how far to move based on distance, then sets the rotation (direction of displacement) based on the result. This makes the vertex move "outward", that is, directly away from the targetVertex, making it seem to puff out from the center.
7. On exiting the loop, stores the updated `modifiedVertices` in the original mesh and has Unity recalculate the normals.

Save your file and return to Unity. Select the Sphere, go to the HeartMesh component, and try adding some vertices into your Selected Indices property. Turn off Is Edit mode and press Play to preview your work.

Play around with the Radius Of Effect, Pull Value and Duration settings to see different results. When you are ready, update the settings per the screenshot below.

Press Play. Did your sphere balloon into a heart shape?

Congratulations! In the next section, you will learn how to save the mesh for further use.

### Saving Your Mesh in Real Time

Right now, your heart comes and goes whenever you push the Play button. If you want a love that lasts, you need a way to write the mesh to a file.

A simple way is to set up a placeholder prefab that has a 3D object as its child, then replace its mesh asset with your heart (...er, your Heart mesh) via a script.

In the Project view, find Prefabs/CustomHeart. Double-click the prefab to open it in Prefab Editing mode.

Click on the Arrow icon to expand its contents in the Hierarchy and select Child. This is where you'll store your generated mesh.

Exit prefab editing mode and open HeartMeshInspector.cs. At the end of `OnInspectorGUI`, before the closing braces, add the following:

```if (!mesh.isEditMode && mesh.isMeshReady)
{
string path = "Assets/RW/Prefabs/CustomHeart.prefab"; //1

if (GUILayout.Button("Save Mesh"))
{
Object prefabToInstantiate =
Object referencePrefab =
GameObject gameObj =
(GameObject)PrefabUtility.InstantiatePrefab(prefabToInstantiate);
typeof(Mesh)); //3
if (!prefabMesh)
{
prefabMesh = new Mesh();
}
else
{
prefabMesh.Clear();
}
prefabMesh = mesh.SaveMesh(prefabMesh); //4
gameObj.GetComponentInChildren<MeshFilter>().mesh = prefabMesh; //5
PrefabUtility.SaveAsPrefabAsset(gameObj, path); //6
Object.DestroyImmediate(gameObj); //7
}
}
```

Here's what the code does:

1. Stores the CustomHeart prefab object asset path, which you need to be able to write to the file.
2. Creates two objects from the CustomHeart prefab, one as a GameObject and the other as a reference.
3. Creates an instance of the mesh asset `prefabMesh` from CustomHeart. If it finds the asset, it clears its data; otherwise, it creates a new empty mesh.
4. Updates `prefabMesh` with new mesh data and associates it with the CustomHeart asset.
5. Updates the GameObject's mesh asset with `prefabMesh`.
6. Creates a Prefab Asset at the given path from the given `gameObj`, including any children in the scene. This replaces whatever was in the CustomHeart prefab.
7. Destroys `gameObj` immediately.

Save your file and go to HeartMesh.cs. Replace the body of `SaveMesh`with the following:

```Mesh nMesh = new Mesh();
nMesh.name = "HeartMesh";
nMesh.vertices = originalMesh.vertices;
nMesh.triangles = originalMesh.triangles;
nMesh.normals = originalMesh.normals;
return nMesh;
```

This will return a mesh asset based on the heart-shaped mesh.

Save the file and return to Unity. Press Play. When the animation ends, a Save Mesh button will appear in the Inspector. Click on the button to save your new mesh, then stop the player.

Find Prefabs/CustomHeart again in the Project view and open it in Prefab Editing mode. You will see a brand spanking new heart-shaped mesh has been saved in your prefab!

Good Job!

## Putting It All Together

In the previous section, you learned how to modify a mesh by selecting individual vertices. While this is cool, you can do more interesting things if you know how to select vertices procedurally.

In the previous scene, `DisplaceVertices` uses a Gaussian falloff formula to determine how much to "pull" each vertex within the radius of the effect. But there are other mathematical functions you can use to calculate the 'fall off' point; that is, where the pull strength starts decaying. Each function produces a different shape:

Like cupcake toppings...

In this section, you will learn how to manipulate vertices using a calculated curve.

Based on the principle that velocity equals distance divided by time (v=(d/t)), you can determine the vector's position by referencing its distance divided by its time factor.

### Using the Curve Method

Save your current scene, then open 03 Customize Heart Mesh from the Scenes folder.

Find the instance of your CustomHeart prefab in the hierarchy and click on the arrow icon next to it to expand its content. Select the Child object.

View its properties in the Inspector. You'll see Mesh Filter with the Heart Mesh asset. Attach Custom Heart to Child. The asset should now change from HeartMesh to clone.

Open CustomHeart.cs and add the following right above `Start`:

```public enum CurveType
{
Curve1, Curve2
}

public CurveType curveType;
Curve curve;
```

This creates a public enum named `CurveType` and makes it available in the Inspector.

Go to `CurveType1` and add the following:

```Vector3[] curvepoints = new Vector3[3]; //1
curvepoints[0] = new Vector3(0, 1, 0);
curvepoints[1] = new Vector3(0.5f, 0.5f, 0);
curvepoints[2] = new Vector3(1, 0, 0);
curve = new Curve(curvepoints[0], curvepoints[1], curvepoints[2], false); //2
```

What's going on?

1. The basic curve consists of three points. This code sets and plots the points for the first curve.
2. Generates the first curve with `Curve` and assigns its values to `curve`. You can set the last parameter to `true` to draw the curve as a preview.

Now go to `CurveType2` and add the following:

```Vector3[] curvepoints = new Vector3[3]; //1
curvepoints[0] = new Vector3(0, 0, 0);
curvepoints[1] = new Vector3(0.5f, 1, 0);
curvepoints[2] = new Vector3(1, 0, 0);
curve = new Curve(curvepoints[0], curvepoints[1], curvepoints[2], false); //2
```

This works much like `CurveType1`.

1. Sets and plots the points for the second curve.
2. Generates the second curve with the `Curve` method and assigns its values to `curve`.

In `StartDisplacement`, before the closing braces, add the following:

```if (curveType == CurveType.Curve1)
{
CurveType1();
}
else if (curveType == CurveType.Curve2)
{
CurveType2();
}
```

This will generate different curves depending on what you select as the Curve Type in the Custom Heart component.

In `DisplaceVertices`, inside the `for` loop, before the closing braces, add the following:

```float increment = curve.GetPoint(distance).y * force; //1
Vector3 translate = (vert * increment) * Time.deltaTime; //2
Quaternion rotation = Quaternion.Euler(translate);
Matrix4x4 m = Matrix4x4.TRS(translate, rotation, Vector3.one);
modifiedVertices[i] = m.MultiplyPoint3x4(modifiedVertices[i]);
```

This might look familiar — it's much like the code you added to `HeartMesh`.

1. Gets the curve's position at the given `distance` and multiplies its `y` value by `force` to get `increment`.
2. Creates a new `Vector3` called `translate` to store the new position for the current vertex and applies its Transform accordingly.

Save the file and return to Unity. Check out the properties in Custom Heart on the Child GameObject.

In the Edit Type drop-down menu, you can now select Add Indices or Remove Indices to update your list of vertices. Select None to exit Edit mode, then click Play see the results. Experiment with different settings and vertex selections.

To see an example of the different curve types, enter these values:

Set Curve Type to Curve1, check that Edit Type is set to None and press Play.

You should see how the mesh fans out into a pattern. Move the model around to its side-view so you can see the shape this curve produces. Exit Play and try it again with Curve 2 to compare the results of both curve types:

That's it! You can click Clear Selected Vertices to reset the Selected Indices and experiment with your own patterns. Don't forget that there are several factors that will affect the final shape of the mesh:

• The size of the radius.
• The spread of vertices within the area.
• The pattern position of the selected vertices.
• The method that you choose for displacement.

## Where to Go From Here?

You can get all of the files for the final project by using the Download Materials button at the top and bottom of this tutorial.

Don't stop here! Try out more advanced techniques with Procedural Maze Generation.

I hope you have enjoyed this tutorial and found the information useful. Special credit to Jasper Flick from Catlike Coding for his great tutorials, which helped me put together the demos for this project.

Feel free to join the discussion forum below for any questions or comments!