Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
3
Question by MediaGiant · May 27, 2015 at 09:49 PM · meshmeshesundosolutionsharedmesh

Undo/Redo on Meshes - This code works, but how?

From reading many questions asking whether it is possible to perform an undo and redo on Unity meshes the typical answers are no, because they are not serializable, or you need to use the SerializedObject class, derive from the ScriptableObject or MonoBehaviour classes, and many other suggestions like custom mesh classes, etc.

I've been after a solution to this that is simple and reliable for a long time and have now come up with a working solution, but, I don't know how it works. The following code demonstrates a custom editor window that takes a game object and transforms the vertices of the mesh. After clicking apply you can then use ctrl-z and ctrl-y to undo and redo the operation.

The magic is in the Undo.undoRedoPerformed callback called MyUndoRedoCallback. It simply copies the vertices and assigns them straight back to the mesh. It only works when placed in this callback and nowhere else.

I'm going to go ahead and use this as it is and also wanted to share the solution with others, but maybe someone can explain how or why this works.

Thanks.

 using UnityEngine;
 using UnityEditor;
 
 public class MeshUndoRedo: EditorWindow
 {
     [MenuItem("Window/Undo Redo", false, 0)]
     static void ShowTheWindow()
     {
         MeshUndoRedo myWindow = (MeshUndoRedo)EditorWindow.GetWindow(typeof(MeshUndoRedo), false, "Undo Redo");
         myWindow.minSize = new Vector2(200.0f, 150.0f);
     }
 
     public GameObject theObject = null;
     public Vector3 factor = new Vector3(1f, 1f, 1f);
 
     void OnFocus()
     {        
         Undo.undoRedoPerformed -= this.MyUndoRedoCallback;
         Undo.undoRedoPerformed += this.MyUndoRedoCallback;
     }
     
     public void MyUndoRedoCallback()
     {
         if (theObject == null)
             return;
 
         MeshFilter meshFilter = theObject.GetComponent<MeshFilter>();
         UnityEngine.Mesh mesh = meshFilter ? meshFilter.sharedMesh : null;
         
         if (mesh)
         {            
             Vector3[] copyVertices = new Vector3[mesh.vertices.Length];
             copyVertices = mesh.vertices;                
             mesh.vertices = copyVertices;
         }
 
         SceneView.RepaintAll();
     }
 
     public void ApplyVertexFactors(Vector3 factor)
     {
         if (theObject == null)
             return;
         
         MeshFilter meshFilter = theObject.GetComponent<MeshFilter>();
         UnityEngine.Mesh mesh = meshFilter ? meshFilter.sharedMesh : null;
         
         Undo.RecordObject(mesh, "Modify Vertices");
         
         if (mesh)
         {            
             Vector3[] copyVertices = new Vector3[mesh.vertices.Length];
             copyVertices = mesh.vertices;
             
             for (int i = 0; i < copyVertices.Length; i++)
             {
                 copyVertices[i].x *= factor.x;
                 copyVertices[i].y *= factor.y;
                 copyVertices[i].z *= factor.z;
             }
             
             mesh.vertices = copyVertices;
         }
         SceneView.RepaintAll();            
     }
     
     public void OnGUI()
     {
         GUILayout.Space(5);
 
         theObject = (GameObject)EditorGUILayout.ObjectField(theObject, typeof(GameObject), true);
         
         GUILayout.Label("Current Factors");
 
         GUILayout.Label("X: " + factor.x.ToString() + " Y: " + factor.y.ToString() + " Z: " + factor.z.ToString());
         
         if (GUILayout.Button("Expand", GUILayout.Height(17)))
         {
             factor *= 2f;
         }
 
         if (GUILayout.Button("Shrink", GUILayout.Height(17)))
         {
             factor /= 2f;
         }
 
         if (GUILayout.Button("Apply", GUILayout.Height(20)))
         {
             ApplyVertexFactors(factor);
         }
     }
 }    
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by IgorAherne · Oct 12, 2016 at 09:02 PM

It will work without the callback as well. Copying of vertices in MyUndoRedoCallback doesn't do anything useful. It only repaints quickly after ctr+z was pressed, without us having to manually do something in the scene viewport (to update screen and display changes).

It works because of Undo.RecordObject(mesh, "Modify Vertices"); on line 47, which records the mesh (that comes from UnityEngine, and hence can be used by Undo), prior to its modification

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image VarunMhatre · May 27, 2021 at 12:16 PM 0
Share

I tested @MediaGiant's code and it doesn't seem to work at all without MyUndoRedoCallback.

After looking around on unity forums, it seems that Undo.RecordObject doesn't work for a sharedMesh.

I still don't know how or why this works the way it's setup, though.

avatar image
0

Answer by VarunMhatre · May 27, 2021 at 12:28 PM

Hi @MediaGiant, thanks for sharing your post, it helped me implement a solution for undoing vertex changes on my meshes.

Your code gets even more bizarre: look at the block Line 30-35

 if (mesh)
 {            
    Vector3[] copyVertices = new Vector3[mesh.vertices.Length];
    copyVertices = mesh.vertices;                
    mesh.vertices = copyVertices;
 }

This section seems to be critical for the Undo/Redo to work at all. And you can change it to the following and it works the same.

 if (mesh)
 {
    mesh.vertices = mesh.vertices;
 }



Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

21 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

moving hole 3 Answers

When meshes are loaded ? 1 Answer

How do I use the same material on 2 meshes without distortion? 2 Answers

The best way to have multiple models with only one material 2 Answers

Prioritizing Visibility of Meshes 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges