How to edit mesh/vertices in Unity

Christopher Lovell picture Christopher Lovell · Sep 23, 2015 · Viewed 21.6k times · Source

I would like to edit 1 vertex on a cube, but I don't know how to. I've tried looking everywhere for this function, but I can't find a solution.

Here is an image of what I want to achieve:

enter image description here

Answer

Ambroise Rabier picture Ambroise Rabier · Jun 12, 2017

http://answers.unity3d.com/questions/14567/editing-mesh-vertices-in-unity.html

This code is not mine. Bellow is the same code as the link above. I just separated it into two files. (one per class)

It work quite good. BUT make sure to save you scene before using it, it's a bit buggy.

  • Don't forget to leave edit mode when you are done whit your modification.

  • You don't need to add "editMesh" tag to the gameobject you are modifying, or it will be erased when you leave edit mode.

  • Lastly, if you modify a primitive from unity, the modification will be applied for every instance of that primitive ! (if you change a cube for a pyramid, every cube will become a pyramid)

To avoid that make a copy of your primitive mesh, change the mesh you are using in your mesh renderer by your copy and then modify it. (bellow a script to add simple copy function in unity menu)

EditMesh.cs

#if UNITY_EDITOR
using UnityEngine;
using System.Collections;

/// <summary>
/// http://answers.unity3d.com/questions/14567/editing-mesh-vertices-in-unity.html
/// </summary>
[AddComponentMenu("Mesh/Vert Handler")]
[ExecuteInEditMode]
public class EditMesh : MonoBehaviour {

    public bool _destroy;

    private Mesh mesh;
    private Vector3[] verts;
    private Vector3 vertPos;
    private GameObject[] handles;

    private const string TAG_HANDLE = "editMesh";

    void OnEnable() {
        mesh = GetComponent<MeshFilter>().sharedMesh; // sharedMesh seem equivalent to .mesh
        verts = mesh.vertices;
        foreach (Vector3 vert in verts) {
            vertPos = transform.TransformPoint(vert);
            GameObject handle = new GameObject(TAG_HANDLE);
            //         handle.hideFlags = HideFlags.DontSave;
            handle.transform.position = vertPos;
            handle.transform.parent = transform;
            handle.tag = TAG_HANDLE;
            handle.AddComponent<EditMeshGizmo>()._parent = this;

        }
    }

    void OnDisable() {
        GameObject[] handles = GameObject.FindGameObjectsWithTag(TAG_HANDLE);
        foreach (GameObject handle in handles) {
            DestroyImmediate(handle);
        }
    }

    void Update() {
        if (_destroy) {
            _destroy = false;
            DestroyImmediate(this);
            return;
        }

        handles = GameObject.FindGameObjectsWithTag(TAG_HANDLE);

        for (int i = 0; i < verts.Length; i++) {
            verts[i] = handles[i].transform.localPosition;
        }

        mesh.vertices = verts;
        mesh.RecalculateBounds();
        mesh.RecalculateNormals();


    }

}

#endif

EditMeshGizmo.cs

#if UNITY_EDITOR
using UnityEngine;
using System.Collections;

/// <summary>
/// http://answers.unity3d.com/questions/14567/editing-mesh-vertices-in-unity.html
/// </summary>
[ExecuteInEditMode]
public class EditMeshGizmo : MonoBehaviour {

    private static float CURRENT_SIZE = 0.1f;

    public float _size = CURRENT_SIZE;
    public EditMesh _parent;
    public bool _destroy;

    private float _lastKnownSize = CURRENT_SIZE;

    void Update() {
        // Change the size if the user requests it
        if (_lastKnownSize != _size) {
            _lastKnownSize = _size;
            CURRENT_SIZE = _size;
        }

        // Ensure the rest of the gizmos know the size has changed...
        if (CURRENT_SIZE != _lastKnownSize) {
            _lastKnownSize = CURRENT_SIZE;
            _size = _lastKnownSize;
        }

        if (_destroy)
            DestroyImmediate(_parent);
    }

    void OnDrawGizmos() {
        Gizmos.color = Color.red;
        Gizmos.DrawCube(transform.position, Vector3.one * CURRENT_SIZE);
    }

}
#endif

CopyMesh.cs (put it in a directory named "Editor") (you should then find it in your menu bar)

using UnityEditor;
using UnityEngine;

namespace Assets {

    /// <summary>
    /// 
    /// </summary>
    public class CopyMesh : MonoBehaviour {

        [MenuItem("Assets/CopyMesh")]
        static void DoCopyMesh() {
            Mesh mesh = Selection.activeObject as Mesh;
            Mesh newmesh = new Mesh();
            newmesh.vertices = mesh.vertices;
            newmesh.triangles = mesh.triangles;
            newmesh.uv = mesh.uv;
            newmesh.normals = mesh.normals;
            newmesh.colors = mesh.colors;
            newmesh.tangents = mesh.tangents;
            AssetDatabase.CreateAsset(newmesh, AssetDatabase.GetAssetPath(mesh) + " copy.asset");
        }

        [MenuItem("Assets/CopyMeshGameObject")]
        static void DoCopyMeshGameObject() {
            Mesh mesh = (Selection.activeGameObject.GetComponent<MeshFilter>()).sharedMesh;
            Mesh newmesh = new Mesh();
            newmesh.vertices = mesh.vertices;
            newmesh.triangles = mesh.triangles;
            newmesh.uv = mesh.uv;
            newmesh.normals = mesh.normals;
            newmesh.colors = mesh.colors;
            newmesh.tangents = mesh.tangents;
            print(AssetDatabase.GetAllAssetPaths()[0]);
            AssetDatabase.CreateAsset(newmesh, AssetDatabase.GetAllAssetPaths()[0] + "/mesh_copy.asset");
        }
    }
}