Search Unity

Custom Editor problem in Unity 5.3

Discussion in 'Editor & General Support' started by kamuro-shou, Dec 10, 2015.

  1. kamuro-shou

    kamuro-shou

    Joined:
    Apr 15, 2013
    Posts:
    3
    Dear Unity developers,

    I found a change of Custom Editor's behaviour in Unity 5.3.0.
    Please check the attached sample project.

    In my custom editor script(SantaEditor.cs), I call EditorUtility.SetDirty to save changes on Inspector.

    Code (CSharp):
    1. public override void OnInspectorGUI()
    2. {
    3.         Santa test = target as Santa;
    4.  
    5.     GUI.changed = false;
    6.     {
    7.         // some gui layout codes
    8.     }
    9.  
    10.     if (GUI.changed) {
    11.         EditorUtility.SetDirty(test);
    12.     }
    13. }
    In 5.2.3 and before, this script works as intended.
    However, it doesn't in 5.3.0.
    It seems SetDirty work nothing and Editor can't notice changes in Custom Editor.

    To reproduce:
    1. Open TestScene01 in the attached project.
    2. Select GameObject in Hierarchy, and make some changes on Santa(Script) in Inspector.
    3. Save and re-open the TestScene01 scene.
    4. You will find
    -> Santa has modified values in 5.2.3 and before.
    -> Santa has default values in 5.3.0.

    To workaround, we have to make additional changes and save the scene.
    In the attached project, for example, changes of Transform values or GameObject(1)'s Reindeer-"Is Nose Red" flag will make sense.
    (Reindeer has no Custom Editor.)

    I'm not sure this behaviour is intentional or not.
    Welcome any comments or suggestions.

    Thank you
     

    Attached Files:

  2. pigasksky

    pigasksky

    Joined:
    Dec 10, 2015
    Posts:
    3
    Same problem.
     
  3. pigasksky

    pigasksky

    Joined:
    Dec 10, 2015
    Posts:
    3
    Maybe you can delete 'Library' and 'Temp' folders first. I don't know if it works because I reinstalled 5.2.3.
     
  4. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,657
    EditorUtility.SetDirty has actually never done what you think it has done, and your custom editor has been broken since Unity 5.0, but you haven't noticed. (Your data has been saved when the user saves the scene, but it hasn't caused the scene to prompt the user "you have unsaved changes, do you want to save them?" or similar). EditorUtility.SetDirty only works with assets, not with GameObjects/Components.

    Fortunately the fix is easy: Instead of calling EditorUtility.SetDirty at the end of your editor code, call Undo.RecordObject at the beginning.
     
    chingwa, karl_jones and kamuro-shou like this.
  5. kamuro-shou

    kamuro-shou

    Joined:
    Apr 15, 2013
    Posts:
    3
    This fix finely works.
    Since 5.3.0, calling Undo.RecordObject seems definitely required for Custom Editor.

    Thank you for your answer!
     
  6. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,657
    Note that there is another approach you could use, which we recommend: instead of using Undo.RecordObject and then editing fields on the target object directly, use the SerializedObject/SerializedProperty API. This will automatically take care of dirtying the scene and supporting undo, and will also give you support for things like multi-object editing, correct styling for prefab overrides, PropertyDrawers, and so on.
     
    Greviouss likes this.
  7. pigasksky

    pigasksky

    Joined:
    Dec 10, 2015
    Posts:
    3
    Good.
     
  8. timlly

    timlly

    Joined:
    Aug 20, 2015
    Posts:
    5
    It works well, thanks guy~
     
  9. chingwa

    chingwa

    Joined:
    Dec 4, 2009
    Posts:
    3,790
    Just saved me! Thank you!
     
  10. drahz

    drahz

    Joined:
    Dec 28, 2015
    Posts:
    1
    I spent about an hour researching this after having issues with setDirty. This is what I've come up with so far, seems to be working great. Also, I'm loving how it automatically pulls the datatype of the SerializedProperty. Hopefully this helps someone.



    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEditor;
    4. using System.Collections;
    5.  
    6. [CustomEditor(typeof(SpriteSheetAnimator))] //custom editor targeting my type SpriteSheetAnimator class
    7. public class SpriteSheetAnimatorEditor : Editor //inheriting from Editor
    8. {
    9.     SerializedObject spriteScript;
    10.  
    11.     SerializedProperty columnProperty; //a field contained in my SpriteSheetAnimator class which will be of type          SerializedProperty
    12.     SerializedProperty rowsProperty; //a field contained in my SpriteSheetAnimator class which will be of type SerializedProperty
    13.     SerializedProperty spriteSheetProperty; //a field contained in my SpriteSheetAnimator class which will be of type SerializedProperty
    14.  
    15.     void OnEnable()
    16.     {
    17.         spriteScript = new SerializedObject(target);
    18.  
    19.         columnProperty = spriteScript.FindProperty("columns"); /*finding that field in the SpriteSheetAnimator class and assigning it to a SerializedProperty.
    20.                                                                  columns is the name of that field*/
    21.  
    22.         rowsProperty = spriteScript.FindProperty("rows");
    23.  
    24.         spriteSheetProperty = spriteScript.FindProperty("spriteSheet");
    25.     }
    26.  
    27.     public override void OnInspectorGUI()
    28.     {
    29.         spriteScript.Update(); //update serialized objects representation
    30.  
    31.  
    32.         EditorGUILayout.PropertyField(columnProperty); /*for the next 3 lines
    33.                                                          this automatically pulls the serialized field type and creates in in the inspector window
    34.                                                           so if columnProperty was an int it would be created in the inspector as type int*/
    35.  
    36.         EditorGUILayout.PropertyField(rowsProperty);
    37.  
    38.         EditorGUILayout.PropertyField(spriteSheetProperty);
    39.  
    40.  
    41.         spriteScript.ApplyModifiedProperties(); /*applies the modified properties for the Serialized Object - IE: I type 1 into the columns field which was created earlier
    42.                                                   in the inspector, this saves that into the columns variable*/
    43.  
    44.  
    45.         if(GUILayout.Button("Process"))
    46.         {
    47.             //call some method
    48.         }
    49.     }
    50. }