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. By Sean Duffy.

4.8 (31) · 2 Reviews

Download materials
Save for later
Share
You are currently viewing page 2 of 5 of this article. Click here to view the first page.

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.
  4. Updates local variables.

Save the file and return to Unity.

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

Gif showing changes to the cube's mesh.

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.

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:

Gif demonstrating the mesh data of a simple Quad mesh.

  • 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.
Note: Unity’s Mesh class keeps track of vertices and triangles with two arrays:

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.

Save the file and return to Unity.

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! :]

Screenshot showing how the Inspector view should look.

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.

SScreenshot showing how the cube looks when you've dragged the dots.

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.

Visual depiction of a cube mesh.

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.

Screenshot of the vertices property on Mesh Study.

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?"]
The simplest answer is:
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].