Unity Draw Plane at Runtime

Update note: Sean Duffy updated this tutorial for Unity 2019.1.two. 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 utilize custom editors, makes the evolution of 3D games and apps so much easier.

With the growth of virtual reality and augmented reality (VR/AR) engineering science, near developers volition inadvertently find themselves wrestling with the gritty bits of 3D concepts. Then let this tutorial exist your starting signal. 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 accept some experience with C# programming. If y'all need to brush upward on these topics, cheque out Introduction to Unity UI and Introduction to Unity Scripting kickoff.

You need to have at least Unity 2019.1.three installed. You can download the latest version of Unity hither.

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

Getting Started

Understanding Meshes

Fourth dimension to start with the bones vocabulary of 3D rendering. The shape of a 3D object is defined past its mesh. A mesh is like a cyberspace of points, or vertices. The invisible lines that connect these vertices class triangles, which ascertain the bones shape of the object.

Example of a square's mesh.

But in add-on to the shape, the engine needs to know how to draw the surface of the object. And then a mesh's information too includes its normals, which are vectors that make up one's mind which style a particular triangle is facing, and thus how light bounces off of it. Finally, a UV Map maps a fabric to an object, specifying how textures wrap around the shape.

In Unity, there are two master 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? Hither's a cheat sheet for piece of cake reference:

  • Vertices: A vertex is a point in 3D space. Ofttimes abbreviated to "vert".
  • Lines/Edges: The invisible lines that connect vertices to 1 another.
  • Triangles: Formed when edges connect 3 vertices.
  • UV Map: Maps a cloth to an object, specifying how textures wrap around the object'southward shape.
  • Normals: The directional vector of a vertex or a surface. This characteristically points outward, perpendicular to the mesh surface, and helps determine how low-cal 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 information to myMesh'southward vertices and triangle properties.
  • Create a new mesh filter named "myMeshFilter".
  • Assign myMesh to myMeshFilter'southward mesh property.

Setting Upwards the Project

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

Screenshot of the starter project's folder structure.

  • Prefabs: This contains a CustomHeart prefab, which you lot'll use to save your 3D mesh at runtime.
  • Scenes: This contains the three scenes that you lot will employ 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 yous 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 adjacent section, y'all will create a custom editor to visualize the parts of a 3D mesh.

Poking and Prodding Meshes With a Custom Editor

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

Starting out with a 3D cube.

You're going to build a custom editor to tear this poor cube apart! (And then you'll learn how to go along information technology in i piece.)

Customizing the Editor Script

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

Screenshot of the Editor folder and its contents.

Open MeshInspector.cs and view the source code. Note that this course inherits from Unity's base Editor class — that'due south what makes Unity empathize 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 form announcement:

[CustomEditor(typeof(MeshStudy))]        

At present, when whatsoever GameObject with the Mesh Study component fastened to it is visible in the Scene view, this class will handle cartoon information technology. But right now, yous won't know if that'south 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 post-obit at the outset of OnSceneGUI:

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

The base Editor form provides a reference to the object you lot're customizing in the target variable, which has type Object. Y'all can't practice much that's useful with a plain vanilla Object, so this code casts target as the type MeshStudy. Logging a message allows yous to come across in the console that the custom editor is indeed running.

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

Screenshot showing where to drag MeshStudy.cs.

Await in the console and make sure your lawmaking is running. And then get alee and remove the Debug.Log line so it doesn't inundation 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 congenital-in Sphere, Cube, Cylinder so on. If that happens, you lot'll need to restart Unity.

Image of a frustrated face.

To avoid this, y'all'll clone the mesh before making whatsoever changes to it in Edit way.

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

In MeshStudy, above the course proclamation, add the following:

[ExecuteInEditMode]        

When a class has this attribute, its Get-go will fire in both Play mode and Edit style. Now that you've added information technology, you tin can instantiate and clone your mesh object before changing annihilation.

Add the following code to InitMesh:

meshFilter = GetComponent<MeshFilter>(); originalMesh = meshFilter.sharedMesh; //1 clonedMesh = new Mesh(); //ii  clonedMesh.proper noun = "clone"; clonedMesh.vertices = originalMesh.vertices; clonedMesh.triangles = originalMesh.triangles; clonedMesh.normals = originalMesh.normals; clonedMesh.uv = originalMesh.uv; meshFilter.mesh = clonedMesh;  //three  vertices = clonedMesh.vertices; //4 triangles = clonedMesh.triangles; isCloned = true; //5 Debug.Log("Init & Cloned");        

Here'southward what'due south 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 subsequently.
  5. Sets isCloned to true; you'll reference this later.

Relieve the file and return to Unity. The console should show the message "Init & Cloned".

Select Cube in the Bureaucracy and wait at the Inspector. The Mesh Filter will show a mesh named clone. Great! This means you take cloned the mesh successfully.

Screenshot showing the cloned mesh filter in the Inspector.

But find in that location's no new Mesh asset in your project — the cloned mesh only lives in Unity's memory correct at present, and it will disappear if you shut the scene. You'll learn how to save a Mesh subsequently.

Resetting a Mesh

For now, you want to give yourself an like shooting fish in a barrel manner 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 push and supervene upon it with the following:

if (GUILayout.Push button("Reset")) //1 {     mesh.Reset(); //ii }        
  1. This code draws a Reset button in the Inspector. The describe office returns truthful when it's pressed.
  2. When pressed, the button calls Reset in MeshStudy.cs.

Relieve the file and render to MeshStudy.cs. Add together the post-obit to Reset:

if (clonedMesh != null && originalMesh != null) //1 {     clonedMesh.vertices = originalMesh.vertices; //ii     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 footstep-by-step:

  1. Checks that both the original mesh and the clone mesh exist, in example the object's mesh filter doesn't take any data in information technology.
  2. Resets all the backdrop 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 Examination Edit button to mess with the cube'south mesh, then printing the Reset button to restore it.

Gif showing changes to the cube's mesh.

Understanding Vertices and Triangles With Unity

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

Notation: Unity's Mesh grade keeps track of vertices and triangles with 2 arrays:

  • It stores vertices every bit an array of Vector3.
  • It stores triangles equally an assortment of integers. Each integer is the alphabetize of one of the vertices in the verts assortment, and each group of three sequent integers represents i triangle.

    For example, the group triangles[0], triangles[ane], triangles[2] represents one triangle, the grouping triangles[iii], triangles[4], triangles[5] represents the next triangle and then on.

So, in a simple Quad mesh that consists of 4 vertices and ii triangles, the Quad'southward mesh data would be:

Gif demonstrating the mesh data of a simple Quad mesh.

Visualizing Vertices

Information technology volition exist easier to see how this works if you tin draw and move effectually 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, yous'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; //two 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 describe the vertices in world space.
  2. Gets the current pin Rotation mode, to depict the handle the same way every bit everything else in the scene.
  3. Loops through the mesh's vertices and draws dots with ShowPoint.

In ShowPoint, replace the //draw dot annotate with:

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

Handles.FreeMoveHandle makes an unconstrained movement handle, which you will use in the side by side department to enable dragging the points around.

Save the file and return to Unity.

Bank check the Cube'due south MeshInspector and make sure that you've checked Move Vertex Point.

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

Screenshot showing how the Inspector view should look.

Moving a Unmarried Vertex

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

Open MeshInspector.cs. Within ShowPoint, replace the //elevate comment with the following:

if (GUI.changed) //iii {     mesh.DoAction(alphabetize, 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, telephone call mesh.DoAction with the alphabetize of the vertex and the vertex's position equally parameters. This line also converts the vertex's position dorsum to local infinite with InverseTransformPoint.

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

PullOneVertex(index, localPos);        

So add together the post-obit 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. Endeavor dragging 1 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 but 1, the other vertices stay behind and your mesh breaks. You'll acquire how to fix this problem shortly. :]

Looking at the Vertices Array

Visually, a cube mesh consists of eight vertices, six sides and 12 triangles. Fourth dimension to run into if Unity agrees.

Visual depiction of a cube mesh.

Become to MeshStudy.cs, and before Get-go, wait 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 tin can accept thousands of vertices. Unity will freeze up if it tries to testify 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 expect at your cube. You tin can at present see the vertices property on Mesh Written report. 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 aforementioned position! Take a moment and think about why in that location might be multiple vertices in the same place.

[spoiler title = "Why 24 Vertices?"]
The simplest reply is:
A cube has six sides and each side has four vertices that class a airplane. 6 × 4 = 24 vertices.

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


[/spoiler]

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

Finding All Similar Vertices

You lot tin can run into that manipulating a mesh is going to have more than only moving single vertices — you have to motility all the vertices for a particular point in space in gild to go on the mesh together. Then you're now gear up to unbreak your heart, er, mesh.

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

PullSimilarVertices(alphabetize, localPos);        

Go to PullSimilarVertices and add the following:

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

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

Gif of a Cube mesh that retains its form without breaking.

Salvage the scene. Y'all've taken the get-go step towards being a mesh sorcerer!

Manipulating Meshes

Editing meshes in Unity is fun, just what if you could add some "squish" to your game by deforming meshes at runtime? Side by side, yous'll try that out in its virtually basic grade — 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 effectually in real time. Open up the 02 Create Heart Mesh scene inside RW/Scenes. Yous'll see a reddish sphere in the Scene view.

Screenshot of the red sphere that you'll transform into a heart.

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 at present, there aren't any verts shown in the scene. And then next, you're going to fix that!

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

Handles.colour = Color.blue; if (Handles.Push(betoken, handleRotation, mesh.pickSize, mesh.pickSize,      Handles.DotHandleCap)) //i {     mesh.selectedIndices.Add together(index); //2 }        
  1. This makes Unity draw the vertices of the mesh every bit buttons, then you lot tin can click on them.
  2. When you click the push button, it adds the selected index to the mesh.selectedIndices listing.

Add the post-obit code at the terminate of OnInspectorGUI, after the existing if statement:

if (GUILayout.Push button("Articulate Selected Vertices")) {     mesh.ClearAllData(); }        

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

Save the file and open RW/Scripts/HeartMesh.cs. In ClearAllData, add together the post-obit:

selectedIndices = new Listing<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.

Salvage 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 meet the mesh'southward vertices in the Scene view. So click on the pointer icon next to Selected Indices to show the array.

Click on a few blueish dots and sentinel new entries announced in Selected Indices. Endeavor out your Clear Selected Vertices button to brand sure information technology clears all values correctly.

Gif showing how Selected Indices works.

Note: Yous have the option to prove/hibernate the transform handle with Show Transform Handle in the custom Inspector, since information technology can get in the way of selecting verts. Merely call back not to panic when you notice the Transform handle missing from your other scenes! Exist certain 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 go Unity to redraw the mesh.

Get to HeartMesh.cs and add the post-obit variables earlier Starting time:

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

Moving a vertex should take some influence on the vertices around it to maintain a smooth shape. These variables command that upshot.

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

In Init, before the if statement, add together:

currentIndex = 0;        

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

Withal in Init, before the endmost braces of the else statement, add together:

StartDisplacement();        

StartDisplacement is what actually moves the vertices. Information technology only runs when isEditMode is false.

Correct at present, this method does zip, so add the following to StartDisplacement:

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

Subsequently StartDisplacement, create a new method called FixedUpdate with the post-obit code:

protected void FixedUpdate() //1 {     if (!isAnimate) //2     {         return;     }      runTime = Time.time - startTime; //3      if (runTime < elapsing)  //4     {         Vector3 targetVertexPos =              meshFilter.transform.InverseTransformPoint(targetVertex);         DisplaceVertices(targetVertexPos, pullValue, radiusOfEffect);     }     else //5     {         currentIndex++;         if (currentIndex < selectedIndices.Count) //half dozen         {             StartDisplacement();         }         else //vii         {             originalMesh = GetComponent<MeshFilter>().mesh;             isAnimate = false;             isMeshReady = true;         }     } }        

Here's what the code is doing:

  1. The FixedUpdate method runs on a fixed interval, meaning that it'southward frame rate independent. Read more than nearly it here.
  2. If isAnimate is faux, it won't do annihilation.
  3. Keeps rail of how long the blitheness 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 upward! 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, yous've reached the end of the list of selected vertices. This line makes a copy of the electric current mesh and sets isAnimate to faux to finish the blitheness.

Making the Vertices Motion Smoothly

In DisplaceVertices, add the following:

Vector3 currentVertexPos = Vector3.zero; bladder sqrRadius = radius * radius; //ane  for (int i = 0; i < modifiedVertices.Length; i++) //two {     currentVertexPos = modifiedVertices[i];     float sqrMagnitude = (currentVertexPos - targetVertexPos).sqrMagnitude; //3     if (sqrMagnitude > sqrRadius)     {         continue; //4     }     float distance = Mathf.Sqrt(sqrMagnitude); //5     float falloff = GaussFalloff(distance, radius);     Vector3 translate = (currentVertexPos * force) * falloff; //6     translate.z = 0f;     Quaternion rotation = Quaternion.Euler(translate);     Matrix4x4 thou = 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 shut to the ones you selected in the editor. Information technology does some math tricks to create a smooth, organic result, similar pushing your thumb into clay. You'll learn more about this afterward.

Here's a closer await 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 outcome, 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 bong bend.
  6. Calculates how far to motion 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 information technology 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 holding. Plough off Is Edit manner and press Play to preview your work.

Effects of adding vertices to your Heart Mesh component.

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.

Indices to set to make your sphere turn into a heart.

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

Gif showing the sphere turning into a heart.

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

Saving Your Mesh in Real Time

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

A elementary way is to set up a placeholder prefab that has a 3D object as its kid, and so replace its mesh asset with your heart (...er, your Eye mesh) via a script.

In the Project view, discover Prefabs/CustomHeart. Double-click the prefab to open up 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.

Saving your mesh.

Leave 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 = "Avails/RW/Prefabs/CustomHeart.prefab"; //ane      if (GUILayout.Button("Salve Mesh"))     {         mesh.isMeshReady = false;         Object prefabToInstantiate =              AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)); //2         Object referencePrefab =             AssetDatabase.LoadAssetAtPath (path, typeof(GameObject));         GameObject gameObj =             (GameObject)PrefabUtility.InstantiatePrefab(prefabToInstantiate);         Mesh prefabMesh = (Mesh)AssetDatabase.LoadAssetAtPath(path,             typeof(Mesh)); //iii         if (!prefabMesh)         {             prefabMesh = new Mesh();             AssetDatabase.AddObjectToAsset(prefabMesh, path);         }         else         {             prefabMesh.Clear();         }         prefabMesh = mesh.SaveMesh(prefabMesh); //4         AssetDatabase.AddObjectToAsset(prefabMesh, path);         gameObj.GetComponentInChildren<MeshFilter>().mesh = prefabMesh; //5         PrefabUtility.SaveAsPrefabAsset(gameObj, path); //6         Object.DestroyImmediate(gameObj); //7     } }        

Here'due south what the lawmaking does:

  1. Stores the CustomHeart prefab object nugget 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 nugget prefabMesh from CustomHeart. If it finds the asset, it clears its data; otherwise, information technology 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 Nugget at the given path from the given gameObj, including any children in the scene. This replaces any was in the CustomHeart prefab.
  7. Destroys gameObj immediately.

Save your file and go to HeartMesh.cs. Supervene upon the body of SaveMeshwith the post-obit:

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. Printing Play. When the blitheness ends, a Save Mesh push button volition announced in the Inspector. Click on the button to save your new mesh, so stop the player.

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

Your new heart mesh.

Skilful Chore!

Putting Information technology All Together

In the previous section, you learned how to alter a mesh by selecting individual vertices. While this is cool, you can do more than 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 issue. But there are other mathematical functions you tin use to calculate the 'autumn off' betoken; that is, where the pull forcefulness starts decaying. Each function produces a unlike shape:

Three shapes that different falloff formulas make.

Like cupcake toppings...

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

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

Determining the vector's position mathematically.

Using the Curve Method

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

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

View its properties in the Inspector. You lot'll meet Mesh Filter with the Eye Mesh asset. Adhere Custom Heart to Child. The nugget should now change from HeartMesh to clone.

Attaching a Custom Heart to Child.

Open CustomHeart.cs and add the following correct above Beginning:

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(ane, 0, 0); curve = new Bend(curvepoints[0], curvepoints[one], curvepoints[2], false); //2        

What'south going on?

  1. The basic curve consists of iii points. This code sets and plots the points for the commencement curve.
  2. Generates the first curve with Curve and assigns its values to curve. You tin set the last parameter to true to draw the bend every bit a preview.

At present go to CurveType2 and add the post-obit:

Vector3[] curvepoints = new Vector3[3]; //1 curvepoints[0] = new Vector3(0, 0, 0); curvepoints[1] = new Vector3(0.5f, 1, 0); curvepoints[ii] = new Vector3(ane, 0, 0); bend = new Bend(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 together the following:

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

This will generate different curves depending on what you lot select as the Bend Type in the Custom Center component.

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

bladder increment = curve.GetPoint(distance).y * strength; //ane Vector3 translate = (vert * increment) * Time.deltaTime; //2 Quaternion rotation = Quaternion.Euler(interpret);  Matrix4x4 thousand = Matrix4x4.TRS(translate, rotation, Vector3.i); modifiedVertices[i] = k.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 chosen translate to shop the new position for the current vertex and applies its Transform appropriately.

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

In the Edit Blazon drop-down carte du jour, you can now select Add Indices or Remove Indices to update your listing of vertices. Select None to exit Edit mode, then click Play see the results. Experiment with dissimilar settings and vertex selections.

Effects of different settings and vertex selections.

To encounter an example of the different bend types, enter these values:

Effects of different curve types.

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

How different curve types affect your heart mesh.

You should encounter how the mesh fans out into a pattern. Movement the model around to its side-view and then y'all can see the shape this curve produces. Get out Play and try information technology again with Curve 2 to compare the results of both bend types:

Effect of applying the first curve type.

Effect of applying the second curve type.

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

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

Where to Go From Here?

You tin get all of the files for the final projection by using the Download Materials push at the pinnacle and bottom of this tutorial.

Don't stop here! Try out more avant-garde techniques with Procedural Maze Generation.

I hope yous take 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 projection.

Modified heart mesh.

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

smithantioney.blogspot.com

Source: https://www.raywenderlich.com/3169311-runtime-mesh-manipulation-with-unity

0 Response to "Unity Draw Plane at Runtime"

Postar um comentário

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel