Search Unity

EditorUtility.SetDirty() functionality change isn't in the docs

Discussion in 'Documentation' started by skalev, Jun 27, 2015.

  1. skalev

    skalev

    Joined:
    Feb 16, 2012
    Posts:
    264
    EditorUtility.SetDirty() has changed, and no longer does it set the scene dirty.

    This was a major change for anyone going over form 4 to 5.

    Only after finding a thread on the forums ( in the beta 5 portion, not even something official ) did I learn I have to either use the Undo system, or call EditorApplication.MakeSceneDirty() to have changes I made to objects be marked properly.

    As a side note, this function should probably be marked obsolete, since it basically doesn't really help anymore, you set an object dirty, but if the user doesn't know to save the scene/project, it will not get saved.
     
    as87dgs6asg0a likes this.
  2. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    Can we get a confirmation on this?

    There's a lot of editor scripts that used to work just fine which now doesn't apply changes. Usually, when I change a script, I also change something else in the scene which marks the scene dirty, which then "picks up" the EditorUtility.SetDirty call.

    There are exactly zero instances where I write EditorUtility.SetDirty and don't want the scene to be set dirty, but I'd like to know if this is a bug (and I should report it as such), or if this is a "feature" (in case I should put something for you to ignore in the feedback).
     
  3. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    The change is mentioned here:
    http://docs.unity3d.com/Manual/UpgradeGuide53.html
    But not here:
    http://docs.unity3d.com/ScriptReference/EditorUtility.SetDirty.html

    And there are a lot of examples that are still using the old SetDirty. Did someone submit a bug report?
     
    OUZEAU likes this.
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    Could @duck or some other Unity dev confirm that this is intended behaviour? Ie. that EditorUtility.SetDirty should not set the object's scene dirty?


    My level designers are losing work over this change/bug, as it breaks every single Editor script. I need to know if we should roll back and wait until this is fixed (in case of a bug), or accept the change and create a workaround.

    If this is an intended change, you'll have to look over every example in the docs, as tons of them use EditorUtility.SetDirty with the assumption that it sets the scene dirty as well. You're also breaking every third party editor scripting tutorial out there.
     
  5. duck

    duck

    Unity Technologies

    Joined:
    Oct 21, 2008
    Posts:
    358
    Thanks for flagging this up, this looks like an important problem. I'll check with the multi-scene-editor guys that it's intended, and if it's something which simply hasn't been properly propagated through all the areas of the docs I'll make sure this gets fixed asap.
     
    Baste and Dantus like this.
  6. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
  7. josephknightcom

    josephknightcom

    Joined:
    Oct 17, 2015
    Posts:
    1
    hello? asap? are you sure? I just wasted hours trying to solve this silent error. the docs suck. Why is proper documentation not more of a priority? I wish i had a list of the problems ive run into lately all doc related.

    docs.

    docs.

    fix the docs.
     
  8. duck

    duck

    Unity Technologies

    Joined:
    Oct 21, 2008
    Posts:
    358
    Working on it - it's a non-trivial fix with a number of code examples to be updated and clarifications from talking with the MSE devs.

    I hope to get the docs updated within the next couple of days with these fixs in. Our whole docs team (4 people & 1 QA) had a rather vital week-long meeting last week, which meant that we now have concrete plans for new hires, better infrastructure and workflow internally, and many other important shake-ups of the docs process sorted, which means this year you should start seeing a big increase in doc quality. However we didn't actually get much doc-fixing done in that week, hence the delay!

    Thanks for your patience.
     
    Junuxx likes this.
  9. Dan2013

    Dan2013

    Joined:
    May 24, 2013
    Posts:
    200
    This is so important.
    I think Unity docs really need some big updates.
     
  10. duck

    duck

    Unity Technologies

    Joined:
    Oct 21, 2008
    Posts:
    358
    This is now fixed in the online docs. There were a lot of pages throughout the manual which used this.

    The short story is that this function is in fact slated to become deprecated, but due to time constraints, that deprecation won't be in 5.4. I have therefore added appropriate warnings to the function's script reference page here:
    http://docs.unity3d.com/ScriptReference/EditorUtility.SetDirty.html

    I've updated all the examples here :
    http://docs.unity3d.com/Manual/editor-CustomEditors.html

    And there were over a dozen other examples throughout the manual which used it SetDirty which I had to fix, particularly in the handles section. Interestingly pretty much every example which needed fixing didn't have a c# version - now they do! For example:
    http://docs.unity3d.com/ScriptReference/Handles.RotationHandle.html

    Thanks for your patience all.
     
    Last edited: Feb 9, 2016
    landon912 and Dantus like this.
  11. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    @duck, thanks a lot for your work!
     
  12. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
  13. duck

    duck

    Unity Technologies

    Joined:
    Oct 21, 2008
    Posts:
    358
    whoops, yes that was a link to our staging server (the step before the pages get pushed to the live server!) and yes it's an internal thing. I've edited the post to show the correct public link. :)
     
    Last edited: Feb 9, 2016
  14. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    I've been looking at this for a month now, and deprecating the method seems to be a very bad idea. I need some way to tell Unity that an object should set as dirty, without providing the possibility for an Undo. This is necessary very often when I change the fields of MonoBehaviours, but need some information to be transferred.

    Example; say I have this MB:

    Code (csharp):
    1. public class Foo : MonoBehaviour {
    2.  
    3.     public GameObject target;
    4.  
    5.     ...
    6. }
    Later on, I realize that I need a list of targets instead. Problem is, the script has been used in a bunch of scenes, and I want to keep the already assigned target as the first element of the list. This is pretty simple to do with SetDirty. I simply change the class to:

    Code (csharp):
    1. public class Foo : MonoBehaviour {
    2.  
    3.     [FormerlySerializedAs("target"), HideInInspector]
    4.     public GameObject deprecatedTarget;
    5.  
    6.     public GameObject[] targets;
    7. }
    And then write this editor script:

    Code (csharp):
    1. [CustomEditor(typeof(Foo))]
    2. public class FooEditor : Editor {
    3.  
    4.     void OnEnable() {
    5.         Foo foo = (Foo) target;
    6.  
    7.         if (foo.deprecatedTarget != null) {
    8.             foo.targets = new[] {
    9.                 foo.deprecatedTarget
    10.             };
    11.  
    12.             foo.deprecatedTarget = null;
    13.             EditorUtility.SetDirty(foo);
    14.         }
    15.     }
    16. }
    That's really convenient! From how I'm reading your changes to the SetDirty page, my choices here are:
    1: change the SerializedObject, and ApplyModifiedProperties (?)
    2: use Undo.RecordObject(foo);
    3: use SceneManager.SetDirty(foo.gameObject.scene).

    1 I couldn't figure out how to make work. As far as I can tell, SerializedProperty allows the user to add empty space to an array, delete elements in an array, and move elements in an array around, but I couldn't find a way to insert an object. I could create the array and then assign that the the objectReferenceValue of the property, but that reads poorly, and it's not obvious from the API what I have to do next - Update and then ApplyModifiedProperties?

    In short, SerializedProperties work well when you're laying out objects, but is horrible when it comes to modify objects through code. The API is not a good replacement for working directly with objects.

    2 is just bad - the example code is meant to ensure that the script is put in a valid state - if the user presses undo, that assumption is thrown out the window.

    3 reads really poorly. What I'm trying to express is "this object has been changed and needs to be saved", but what I'm writing is "the entire scene has been changed, and needs to be saved". The readability of the code is a lot worse, and I haven't gained anything.

    In my opinion, the easiest fix would be to keep EditorUtility.SetDirty around, and have it automatically set whatever scene it is in dirty. It would function like 3, but keep the expressiveness of the old API.

    Learning to create Editor scripts up to now has been very easy - you have a target variable, you edit the target variable, you set the target variable dirty. That's intuitive for both experienced programmers trying out Unity, and for beginners that's trying to learn. Having to know about either the scene abstraction or the SerializedProperty abstraction first puts a big barrier in the way.


    @duck - this is probably not something that's your responsibility, but could you pass this on to whomever's in charge? This is a pretty major change, and I figured that feedback from users would be helpful to whomever maintains this part of the API.
     
    angrypenguin and Alverik like this.
  15. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    +1.. don't remove.

    I create tools which create default prefabs when they initialise or make changes to private assets/ prefabs while the user uses it. Those things should not be undone so I can't use Undo system to mark them dirty. Using SerializedObject is also just over complicating things in many situations.

    I'll live with using SceneManager.SetDirty() where undo do not make sense for something I do in the scene.
     
    Alverik likes this.
  16. jorrit-de-vries

    jorrit-de-vries

    Joined:
    Aug 7, 2009
    Posts:
    71
    I also have to say it is not clear what to do when one is not using SerializedObject and its properties, but is calling methods on an the target of the editor. I used EditorUtility.SetDirty, which pretty much worked, but changed it as recommended to use Undo.

    But now the changes to the scene object are not reflected in the SceneView (I see data being updated in the inspector, so I know that works), unless I trigger via script or in the editor a redraw of the SceneView. Not seeing any changes directly is not really a workable situation.

    All the examples are using EditorGUILayout.PropertyField, with properties retrieved by strings which is asking for trouble. Are there any examples not using this, but modify the target of the editor in another fashion? Or is using the undocumented SceneView.RepaintAll() the way to go for such view refreshes?
     
  17. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    SceneView.RepaintAll() is what I use in TileEd when I made changes that needs a scene repaint. I guess it is similar to how you might want to repaint the Inspector or your own Editor widow when it is not focused or is focused but you do not want to wait for Unity to one day call that OnGUI.
     
  18. Discipol

    Discipol

    Joined:
    May 6, 2015
    Posts:
    83
    Hello Duck, is it possible to set a scene dirty without having to use Find ? I don't want to commit to a string for my property. if it where possible to have a GetSerializedReference from the member directly or something. or just have a single method to make an object dirty no matter what changes, it would help. The old SetDirty worked just fine.