Search Unity

Editing mesh in editor. Changes lost when reloading scene

Discussion in 'Scripting' started by diegzumillo, Aug 12, 2019.

  1. diegzumillo

    diegzumillo

    Joined:
    Jul 26, 2010
    Posts:
    418
    Hey there

    Everything relating to mesh editing in Unity confuses me so I always try to mess with that only when strictly necessary.

    Right now I have a button in the inspector that rotates the UV of a plane mesh I imported and added to the scene. It works fine, until I have to reload the scene, then the original UVs of the mesh are back. This is the function:

    Code (CSharp):
    1. public void RotateUVs(){
    2.         Mesh mesh = RoomMesh.GetComponent<MeshFilter>().sharedMesh;
    3.         Vector2[] uv = mesh.uv;
    4.  
    5.         for (var i = 0; i < uv.Length; i++)
    6.         {
    7.             uv[i]-=new Vector2(0.5f,0.5f);
    8.             uv[i] = new Vector2(-uv[i].y, uv[i].x);
    9.             uv[i]+=new Vector2(0.5f,0.5f);
    10.         }
    11.  
    12.         mesh.uv = uv;
    13.     }
    The details are not that important, what matters is that:
    1. This function gets called in Edit mode (but also works in play mode and changes are kept when back in edit mode)
    2. It takes sharedmesh and gives it a new mesh.uv
    3. It works during this session. That is, I hit play and it's fine, and I can go back and forth between play and edit mode that those changes are preserved.
    4. When I reload the scene the UVs are reverted to the original imported mesh.
    I am 100% it has to do with the use of sharedmesh vs mesh. The results of my experiments are confusing. If I change just mesh then changes made in play mode are lost when back in edit mode but seem preserved when I reload the scene. If I try to modify both to get the best of both worlds (can change in play mode and changes are preserved when reloading scene) then it behaves erratically. Changing in play mode gives a result, back in edit mode it was like I only rotated once instead of twice, then reloading the scene lost the changes completely.

    It's a frustratingly simple thing I want to achieve. I want to rotate UVs of a mesh and keep it that way. Can't be that hard, right?
     
  2. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    Mesh is asset. When modifying assets programmaticaly, call EditorUtility.SetDirty on them or your changes may be lost.
     
  3. diegzumillo

    diegzumillo

    Joined:
    Jul 26, 2010
    Posts:
    418
  4. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
  5. diegzumillo

    diegzumillo

    Joined:
    Jul 26, 2010
    Posts:
    418
    No cigar.

    I tried with setdirty thing and then undo + recordprefabinstanceblalbabla.

    Code (CSharp):
    1. string assetName = AssetDatabase.GetAssetPath(RoomMesh.GetComponent<MeshFilter>().sharedMesh);
    2.         Object asset = AssetDatabase.LoadAssetAtPath(assetName,typeof(Object));
    3. //Undo.RecordObject(asset,"Rotated mesh uv");
    4.      
    5.         Mesh mesh = RoomMesh.GetComponent<MeshFilter>().sharedMesh;
    6.         Vector2[] uv = mesh.uv;
    7.  
    8.         //changes to uvs
    9.      
    10.         mesh.uv = uv;
    11.      
    12.         //PrefabUtility.RecordPrefabInstancePropertyModifications(asset);
    13.         EditorUtility.SetDirty(asset);
    Noting that RecordPrefabInstancePropertyModifications supposedly takes as argument an instance of the prefab, so I shouldn't need to find the asset.
     
    Last edited: Aug 12, 2019
  6. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    Try this

    Code (CSharp):
    1. Debug.Log(assetName);
    2. Debug.Log(asset.GetType().Name);
    put it on lines 14 & 15
     
  7. diegzumillo

    diegzumillo

    Joined:
    Jul 26, 2010
    Posts:
    418
    Oh it's a GameObject, not object! Here is the exact output:
    Code (CSharp):
    1. Assets/Levels/singlecurvemesh.FBX
    2. UnityEngine.Debug:Log(Object)
    3. Room:RotateUVs() (at Assets/Scripts/Room.cs:168)
    4. RoomEditor:OnInspectorGUI() (at Assets/Editor/RoomEditor.cs:32)
    5. UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
    6.  
    7.  
    8. GameObject
    9. UnityEngine.Debug:Log(Object)
    10. Room:RotateUVs() (at Assets/Scripts/Room.cs:169)
    11. RoomEditor:OnInspectorGUI() (at Assets/Editor/RoomEditor.cs:32)
    12. UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
    13.  
    I quickly changed typeof argument to gameobject but that didn't help.
     
  8. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    That will not help. You can't modify mesh inside FBX. You need to save it as separate asset for editing. Fbx importer in unity will override your modifications from file. Also note what assets in Unity may have complex structure. In your script the type of .FBX asset is game object because unity creates prefab asset for displaying meshes from FBX file. Those asses contains meshes, materials, avatars whatever as subasses. You loading and setting dirty the gameobject, leaving mesh intact.
     
  9. diegzumillo

    diegzumillo

    Joined:
    Jul 26, 2010
    Posts:
    418
    Ah, that settles it then. I already found a bunch of topics on dealing with imported FBX. Thanks for the help! I'll see if I can find a way around using fbx or copying the imported mesh into a new asset.
     
  10. wechat_os_Qy0-P918R-7oH767aix6N_7Ec

    wechat_os_Qy0-P918R-7oH767aix6N_7Ec

    Joined:
    Apr 16, 2020
    Posts:
    1
    Hi, diegzumillo . Have you solved this problem?

    I'm working on an app that will change the mesh, and I hope that the changes can be retained when switching between different scenes. We haven't found a viable way.. sad:
     
  11. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    Look up how to write the mesh asset to disk and set a reference to it in your scene or prefab.

    For the writing the asset part, I have an example in my makegeo project as
    Editor/MeshMakerAndSaver.cs
    :

    MakeGeo is presently hosted at these locations:

    https://bitbucket.org/kurtdekker/makegeo

    https://github.com/kurtdekker/makegeo

    https://gitlab.com/kurtdekker/makegeo

    https://sourceforge.net/p/makegeo