- Home /
Behaviour of custom inspector on Undo
Greetings,
I stumbled upon a problem regarding the implementation of custom inspectors (also property drawers) in combination with Undo.
The Problem
If an Undo operation is performed, the inspector is destroyed, the same way as if the inspector loses focus. The consequence is that all local fields are reset to their respective default value. E.g. a private bool foldout is set to false resulting in a folded UI.
This is of course perfectly normal if the inspector loses focus. However, as far as I know this shouldn't be normal for an Undo operation. At least I did not found a clear statement about the consequences of using Undo with respect to custom inspectors.
Most examples regarding custom inspectors and property drawers are using private fields to handle their foldouts and other things.
Even more mystifying is the following Example.
I experienced different behaviour in nearly identical custom inspectors. While the editor of inspector A is destroyed on Undo, the editor of inspector B is not. Both have the following structure:
public class ExampleEditor : Editor
{
// Field
private int selectedCategory;
// Method
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(serializedObject.FindProperty("Foo"));
selectedCategory = GUILayout.Toolbar(
selectedCategory,
new string[] { "Option1", "Option2", "Option3" });
switch (selectedCategory)
{
case 0:
EditorGUILayout.PropertyField(serializedObject.FindProperty("Property1"));
break;
case 1:
EditorGUILayout.PropertyField(serializedObject.FindProperty("Property2"));
break;
case 2:
EditorGUILayout.PropertyField(serializedObject.FindProperty("Property3"));
break;
}
serializedObject.ApplyModifiedProperties();
}
}
The Question
What is the correct behaviour I should expect from Unitys Editor?
Is it possible to have control on weather the inspector destroys itself on Undo or not?
The Solution
Of course there is a very simple way to solve the problem. However, I think it is important to understand the problem and to have it written down so others can find these informations. Especially ambiguous behaviour is always a great concern.
Regarding the foldout example, it is possible to use the .isExpanded flag of a SerializedProperty. In my case, where I need to store an integer field, it is also possible to store the field in the serializedObject instead of the inspector.
Answer by Adam-Mechtley · Jan 09, 2017 at 06:23 PM
If an Undo operation is performed, the inspector is destroyed
This should not be true. Does your inspector also currently display a material editor when this happens? If so, I actually fixed this during the 5.5 cycle. If not, I'd appreciate a bug report.
Edit: For people reading this in future, this bug was in fact fixed for 5.6, not 5.5.
Hi Adam,
thanks for the fast reply. First of all I have to apologize because I forgot to mention that I currently use Unity 5.4.3f1. $$anonymous$$y $$anonymous$$m and I decided that we wait for at least 5.5.1 until we upgrade.
So I downloaded 5.5.0 and tested the same scenario. It does not work. However, I also tested with version 5.0.0.f4 ... here it actually works.
The remaining problem is that we work on a plugin which is already in the store. That means I must ensure that there is a solution which works up from version 5.0.0f4 Thus, I consider sticking to the solution of using serialized fields.
P.S. There was no material editor involved. Our editors just work with references and basic data types (Grouped into serializable classes).
When you see the problem, are there any other components on the object at all? What I meant was that if you have e.g., a $$anonymous$$eshRenderer component on the object, then the inspector will show the $$anonymous$$aterialEditor for the $$anonymous$$eshRenderer's material at the bottom. $$anonymous$$aterialEditor previously registered an UndoRedo callback that would destroy all visible inspectors. I'm just wondering if it's possible there are any other built-in components that might be causing issues here. It strikes me as a bug, so would really appreciate a bug report if you can submit one :)
That said, serializing data on your run-time object that you only really need in the editor can bloat your objects and also ties the inspector's state to individual instances. From a UX perspective it can be a little wonky that the tool mode changes when I pick different instances. Worst case in that situation I would consider something like EditorPrefs
(or better SessionState
in 5.6+) ins$$anonymous$$d.
First of all, I submitted the bug report. :)
Second, thanks for pointing out the fact with the material editor. I missunderstood you previously. And yes this seems to be the source. When having for instance a sprite renderer attached the problem occurs otherwise not.
Regarding the serialization topic, I know that serializing the field is certainly not the best way. What confused me was the fact that a SerializedProperty has a serialized field isExpanded which is used just for inspector purposes.
However, your answer helped me a lot. Now I know that this is a problem which is not in my reach. So I can use the recommended way to implement my inspectors.
Thanks again for the fast reply. :)