Search Unity

After several months, I've written a large tutorial on writing editor extensions for Unity

Discussion in 'Immediate Mode GUI (IMGUI)' started by elmar1028, Mar 16, 2016.

  1. elmar1028

    elmar1028

    Joined:
    Nov 21, 2013
    Posts:
    2,359
  2. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Great :) pretty useful
     
  3. shaderbytes

    shaderbytes

    Joined:
    Nov 11, 2010
    Posts:
    900
    You are not using serializedObjects or serializedProperties anywhere?

    Declaring and using Serialized properties is much better because you dont have to write verbose complicated lines like these :
    Code (csharp):
    1. npcScript.npcObject = (GameObject)EditorGUILayout.ObjectField("NPC Object", npcScript.npcObject, typeof(GameObject), true);
    you just use
    Code (csharp):
    1.  EditorGUILayout.PropertyField(mySerializedProperty)
    this works for all objects ( GameObjects , Materials ,Texture2D etc ) and all datatypes. If its an array or List or custom Struct you can pass a second argument of true to show the expanded details.
     
  4. elmar1028

    elmar1028

    Joined:
    Nov 21, 2013
    Posts:
    2,359
    It's the last section.
    I defined serializedProperty through serializedObject.FindProperty("propertyName") and then use EditorGUILayout.PropertyField() to show the property field.
     
  5. shaderbytes

    shaderbytes

    Joined:
    Nov 11, 2010
    Posts:
    900
    ok yes I see that now , but why present 95% the convoluted methods in your tutorial and right at the end only present the best method. I mean I didn't scroll that far purely because of the presentation of all the convoluted methods first... just saying no hard feelings
     
  6. elmar1028

    elmar1028

    Joined:
    Nov 21, 2013
    Posts:
    2,359
    I wanted to showcase as many methods as possible. It's always good to know them. Besides, I have a nice overview table, where users can jump right to topic.

     
  7. shaderbytes

    shaderbytes

    Joined:
    Nov 11, 2010
    Posts:
    900
    Yes it is good to show the other methods what I'm saying is I would present serialized properties first , since its the easiest and most commonly used ( you could even touch on editing multiple objects as well which is also very easy when using serialized objects/properties.) Of coarse it is possible to do it the convoluted manner as well , looping the targets and casting etc.. I have used it before myself so its not a case of right or wrong , just about prioritizing the best and most common methods first
     
  8. elmar1028

    elmar1028

    Joined:
    Nov 21, 2013
    Posts:
    2,359
    Thanks for the feedback! I made a note of that for my future articles :)
     
  9. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,332
    Neat. The official tutorials on this are a bit all over the place.

    You should probably mention Undo.RecordObject at one point - it's a lot more exact than setting the entire scene dirty, and it allows for Undo, which is really convenient. It's also easier to read your intention from:

    Code (csharp):
    1. Undo.RecordObject(myObject);
    2. //editor code
    Than from this:

    Code (csharp):
    1. //editor code
    2. EditorSceneManager.MarkSceneDirty(EditorApplication.currentScene);
    EditorApplication.currentScene might also not be what you want, since multi scene editing is now a thing. If you're sticking with MarkSceneDirty, you should probably change it to:

    Code (csharp):
    1. EditorSceneManager.MarkSceneDirty(targetObject.scene);
    So you're sure that it's the object's scene that gets set dirty. If a user locks the inspector, it would be possible to be editing an object in a different scene from the one that's active.

    I know it's a big subject, but you should probably also cover custom property drawers for types and attributes. They're really nice for decorating your inspectors without having to create an entire custom editor. I've come to use them more and custom editors less as time goes on.

    @shaderbytes I'll have to disagree with serialized properties. Being string-based, using them means that renaming a variable breaks your editor scripts silently, which is never fun. I also very seldom use custom editors in use cases where the default property drawer is what I want, so EditorGUILayout.PropertyField is almost never useful for custom editors. It's also a layer of abstraction between your editor code and the object you're editing, so it's probably a lot harder to understand for inexperienced programmers.

    They're great for PropertyDrawers, or other cases where you're working with code that draws things that you don't know what is. If I'm laying out a specific field, I'd rather just manipulate it directly. True, the ObjectField is ugly, but it's very easy to make a wrapper that makes it much more manageable:

    Code (csharp):
    1. public static class EditorTools {
    2.     public static T ObjectField<T>(string label, T original, bool allowSceneObjects) where T : Object {
    3.         return (T) EditorGUILayout.ObjectField(label, original, typeof (T), allowSceneObjects);
    4.     }
    5. }
    Which turns your example into:

    Code (csharp):
    1. npcScript.npcObject = EditorTools.ObjectField("NPC Object", npcScript.npcObject, true);[Code]
    2.  
    3. Which is very readable, and still allows you to disallow scene objects (which is not the case with properties).
     
    Weendie-Games and flashframe like this.
  10. ashley

    ashley

    Joined:
    Nov 5, 2011
    Posts:
    84
    The page appears to be down. The link just leads to a page that says "pageok". Has it been removed?
     
  11. TheFrozenFires

    TheFrozenFires

    Joined:
    Jul 5, 2013
    Posts:
    8
  12. elmar1028

    elmar1028

    Joined:
    Nov 21, 2013
    Posts:
    2,359
  13. Deleted User

    Deleted User

    Guest

    We really need more in-depth tutorials for writing editor extensions, so I give you my thumbs up for doing this.


    Some critique though:

    Your Serialization section makes no mentions of ISerializationCallbackReceiver and ScriptableObject. They both are almost mandatory for data-heavy extensions. If I still were a complete beginner, I'd miss them. Someone else commented your post on Gamasutra with other relevant criticism regarding serialization. You should probably rewrite that section.