Search Unity

PropertyDrawers for easy Inspector customization

Discussion in 'Developer Preview Archive' started by runevision, Sep 7, 2012.

  1. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    A new editor feature in Unity 4 is the new PropertyDrawer framework. PropertyDrawers let you customize how script properties are shown and work in the Inspector without having to write an entire CustomEditor. They also let you create custom GUI for serializable classes. Lasse and I explain them in this blog post:

    Property Drawers in Unity 4

    You can also read about PropertyDrawers by searching for PropertyDrawer in your local Unity 4 scripting reference.

    We look forward to see what you all make with them. :)

    Rune
     
  2. frarees

    frarees

    Joined:
    Jun 8, 2012
    Posts:
    36
    That's amazing! Far more easy to improve the inspector view of your scripts! Keep up the good work!
     
  3. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    715
    For those who code in Javascript, it works this way:
    Code (csharp):
    1. @Multiline var someText = "some text";
     
  4. Cripple

    Cripple

    Joined:
    Aug 16, 2012
    Posts:
    92
    This is one of the feature i wanted to have the most. I am going to do a bunch of new awesome inspectors and release them on store !
     
  5. Cripple

    Cripple

    Joined:
    Aug 16, 2012
    Posts:
    92
    Will it be possible to get in the script the PropertyDrawer associated to a class. For example if you go an Attribute drawer which just want to decorate the Default (or current) PropertyDrawer.

    [Tooltip ("My tooltip")]
    public float MyProperty;

    With this i just want to add a tooltip but i don't want to code the PropertyDrawer of a float, i just want to add my tooltip code and then call something like "DrawDefaultPropertyDrawer()" or CurrentDrawer!
     
  6. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    The system doesn't support having multiple PropertyDrawers for the same property, so what you describe can't be done as it is. That said, the general concept of using attributes to control more things is something we've only just started looking at with this. It's not the first time the tooltip use-case has been brought up, and we might end up deciding to support it in a special-case way or something at some point. However, the current system is already a big step forward and very flexible. Before we start adding extra things on top we want to see how people use the feature to get a better overview of real-world uses and possible limitations instead of making design decisions based just on speculation. :)

    Rune
     
  7. SevenBits

    SevenBits

    Joined:
    Dec 26, 2011
    Posts:
    1,953
    This is a fantastic system, however, support should be added for tooltips like stated above.
     
  8. Cripple

    Cripple

    Joined:
    Aug 16, 2012
    Posts:
    92
    Yeah tooltip was just an example, I don't really care about it.

    The thing i would like to know the most is the PropertyDrawer for Collections.

    I just want to make a generic PropertyDrawer for arrays and I don't want to recode the entire PropertyDrawer to display items. Will it be possible to call the PropertyDrawer of a given Class inside an other PropertyDrawer in order to handle this special case ???
     
  9. silver-wind

    silver-wind

    Joined:
    May 8, 2007
    Posts:
    19
    It's really handy and faster than coding an entire editor.

    The main problem is to align controls :confused: because I don't want to break default layout of Unity code inspector. (see below)

    Here is my first test: combined attributes + combined properties + label + tooltip + reflection + MinMaxSlider
    Code (csharp):
    1.  
    2. public class Launcher : MonoBehaviour
    3. {
    4.     public string Name="";
    5.    
    6.     [MinMax(0f, 1f)]
    7.     [Label("Attack Range")]
    8.     public float Near = .2f;
    9.     public float Far = .9f;
    10.  
    11.     [Label("Random Speed", "Projectile speed:\npixel per seconds")]
    12.     [MinMax(10, 100)]
    13.     public int LowSpeed = 40;
    14.     public int HiSpeed = 50;
    15. }
    16.  
     

    Attached Files:

    Last edited: Sep 9, 2012
  10. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    You can't make a PropertyDrawer for arrays or generic lists themselves. I do get that our current GUI for managing arrays leave something to be desired, but PropertyDrawers is not the solution to that particular problem I'm afraid.

    On the plus side, elements inside arrays and lists do work with PropertyDrawers. For example, this will make every float in the array be displayed as a slider from 0 to 10:

    Code (csharp):
    1. [Range (0, 10)]
    2. float[] myFloats;
    Apart from the fact that you can't change the GUI for array handling, PropertyDrawers do support nesting. When you call GUI.PropertyField on a SerializedProperty the property will be drawn with its appropriate PropertyDrawer. (Note though that inside the OnGUI function of a PropertyDrawer you should only call PropertyField on child SerializedProperties, not on the main SerializedProperty itself.)

    Rune
     
  11. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    I don't quite understand what's going on here. PropertyDrawers are supposed to only support one PropertyAttribute per variable, and one PropertyAttribute is supossed to affect only the one variable immediately below it; not multiple. So if the code you posted results in the screenshot you posted, then you might be seeing a bug of some kind, a we'd appreciate if you could send us your scripts so we can investigate it further. :)

    So to clarify: Only one PropertyDrawer for one variable is officially supported. Please don't rely on other behavior as it might be bugs.

    Rune
     
  12. silver-wind

    silver-wind

    Joined:
    May 8, 2007
    Posts:
    19
    I didn't break this rule.
    In my code, there are two kinds of attribute:
    - PropertyAttribute call a PropertyDrawer
    - DecoratorAttribute used by PropertyDrawer to decorate the editor : change label, change tooltip, change padding...

    example of PropertyAttribute : MinMaxAttribute
    example of DecoratorAttribute : LabelAttribute, LayoutAttribute

    It's probably because of this code below
    Code (csharp):
    1. var minProp = prop.Copy();
    2. prop.NextVisible(false);
    3. var maxProp = prop.Copy();
    If you plan to fix this, I have to change the MinMax syntax.(see below)
    Code (csharp):
    1. [MinBand(10)] // find MaxBand and show MinMaxSlider control
    2. public int LowSpeed = 40;
    3. [MaxBand(100)] // hide property from editor
    4. public int HiSpeed = 50;
     
    Last edited: Sep 9, 2012
  13. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    Yeah, I was considering if you were perhaps doing your own attributes. Very clever. :)

    I'm not sure hat that second code block is. In any case, I can see how a drawer can peek at the following attributes using NextVisible(), but they should still be drawn (again) by the Inspector below. If that's not the case, then I think that's a bug.

    Rune
     
  14. silver-wind

    silver-wind

    Joined:
    May 8, 2007
    Posts:
    19
    I confirm the side effect of these functions. I sent a bug report.

    But I noticed a critical problem about error handling of custom drawer: any exception causes Unity editor crash even if I wrap the code into a TRY CATCH block.I hope you can fix this in the next beta :rolleyes:
     
  15. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    Thanks. What's the case number? Searching our bug database for PropertyDrawer didn't find your bug report...

    Do you have a case number on this too? The next beta is already in the pipeline, but if we can repro the bug we'll get to it in one of the next betas in any case.

    Rune
     
  16. silver-wind

    silver-wind

    Joined:
    May 8, 2007
    Posts:
    19
    Hi,
    I sent you a private message with case numbers:
    • Error handling in custom attribute
    • SerializeProperty.Next() and SerializeProperty.NextVisible
     
    Last edited: Sep 11, 2012
  17. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    Excellent, thanks.
     
  18. silver-wind

    silver-wind

    Joined:
    May 8, 2007
    Posts:
    19
    Do you plan to support EditorGUILayout utilities (BeginVertical, BeginHorizontal,...) ?
     
  19. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    No, for performance reasons the PropertyDrawers do not support GUILayout and there are no plans to include support for it.

    Rune
     
  20. silver-wind

    silver-wind

    Joined:
    May 8, 2007
    Posts:
    19
    Hi,

    I tried to customize a list of item.
    Is there a way to call the appropriate drawer (custom or default one) for an item property ?
    I need to know heights of properties in order to calculate item size.
     
    Last edited: Sep 20, 2012
  21. Yann

    Yann

    Joined:
    Oct 20, 2007
    Posts:
    432
    Hi,

    Is there a complete list of the JavaScript instructions ? I have tested some of them that work (Range, Multiline) but for example this one doesn't :

    Code (csharp):
    1. @Popup ("Value 1", "Value 2", "Value 3") var choice : String = "Value 1";
    Unity says the type 'Popup" is not a valid attribute.
     
  22. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    JavaScript has nothing to do with it. Only the attributes Range and Multiline are built-in. The other ones mentioned in the blog post are just examples of custom attributes you could make.

    Rune
     
  23. Yann

    Yann

    Joined:
    Oct 20, 2007
    Posts:
    432
    Thanks Rune, it's clear now.
     
  24. Chris-Herold

    Chris-Herold

    Joined:
    Nov 14, 2011
    Posts:
    116
    I have a crazy special case that i hoped to be able to solve in version 4.
    However, since SerializedProperty doesn't recognize structs
    i'm still not able to create a property inspector for this.

    Code (csharp):
    1.  
    2.  
    3. public struct Vector64
    4. {
    5.     public double x;
    6.     public double y;
    7.     public double z;
    8. }
    9.  
    10. public class Transform64 : MonoBehaviour
    11. {
    12.    public Vector64 position;
    13. }
    14.  
    15.  
    I hoped to finally do this using CustomPropertyDrawer,
    but neither of the approaches described in the blog post works out.

    Also: Any plans to support doubles across the board anytime soon? :)
     
    Last edited: Sep 27, 2012
  25. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    PropertyDrawers don't change what things can be serialized using Unity's serialization system.

    I'm not aware of any plans to start supporting serializing structs. According to our CTO it would be far from trivial.

    Rune
     
  26. Chris-Herold

    Chris-Herold

    Joined:
    Nov 14, 2011
    Posts:
    116
    I don't even want to serialize it - i just want to change values in the inspector.
    It's a little sad that so few value types are supported.

    Structs are really important. Using classes for everything pressurizes the heap like crazy, not to mention the GC.

    Please Unity dev team, reconsider your stance towards structs and other primitives like "double" or "long".
    It's a huge pain to find workarounds to this limitation.

    I was hoping for an improved serialization (and therefore inspector support) in Unity4 more than anything else.
     
  27. silver-wind

    silver-wind

    Joined:
    May 8, 2007
    Posts:
    19
    I noticed a custom editor method:
    Do we need to call it in some cases ?
    Code (csharp):
    1. EditorUtility.SetDirty()
     
    Last edited: Oct 3, 2012
  28. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    No, when using SerializedProperties there's no need to call SetDirty. And the PropertyDrawers can only be used through SerializedProperties.

    Rune
     
  29. silver-wind

    silver-wind

    Joined:
    May 8, 2007
    Posts:
    19
    Hi,

    Vector4 cannot be customized.
    Here are missing features :
    Code (csharp):
    1. SerializedPropertyType.Vector4
    2. SerializedProperty.vector4Value
    Is there a technical a reason behind that ? Do you plan to support it ?
     
    Last edited: Oct 10, 2012
  30. HunterPT

    HunterPT

    Joined:
    Nov 11, 2011
    Posts:
    38
    Hi, I took a look at this yesterday and got to say that this is a pretty nice feature, I'm sure it will save a lot of people a lot of trouble, and it's something that can be easily shared, with that in mind I attached 2 different property drawers if someone wants to use them.

    The first one is the Popup that you saw in the blog article but which the implementation wasn't actually shown, the one that I made takes strings, ints and floats (not at the same time obviously), to use it in C# just copy the 2 Popup files to your project and then write [Popup("String","String","String","String","String")], or replace the strings with ints or floats for other variables OFC,

    The second one that I attached is a lot like the range that comes built in unity, but it treats float values as if they were ints, which means you can create a float variable that users in the editor will only be able to treat as if it was an int (questionable use I know), you use in the same way as the normal range except you write [IntRange(1,10)] instead of [Range(1,10)]

    If anyone has any doubts about this 2 property drawers feel free to post here, or send me a PM, I will try and help if I can.
    It goes without saying that you are free to use, distribute or modify the files however you please, if you add features please post them here, especially if those features are good documentation and proper coding to avoid the repetition the code has :)
     

    Attached Files:

    cupsster likes this.