Search Unity

Advanced Inspector - Never Write An Editor Again

Discussion in 'Assets and Asset Store' started by LightStriker, May 4, 2014.

  1. Miguel-Ferreira

    Miguel-Ferreira

    Joined:
    May 8, 2015
    Posts:
    90
  2. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    Interesting. Well, the obvious work around with existing AI is to group a method and some fields together to be displayed as one.

    Code (CSharp):
    1.         [Inspect, Group("Method")]
    2.         private float param1;
    3.         [Inspect, Group("Method")]
    4.         private string param2;
    5.  
    6.         [Inspect, Group("Method")]
    7.         private void Method()
    8.         {
    9.             Method(param1, param2);
    10.         }
    11.  
    12.         public void Method(float a, string b)
    13.         {
    14.             Debug.LogError(a.ToString() + " : " + b.ToString());
    15.         }
    It's not as clean in code, but could be a useful workaround until I make something more permanent.
     
  3. EMOTION-THEORY

    EMOTION-THEORY

    Joined:
    Jul 16, 2013
    Posts:
    65
    Heya, I just purchased this package, which I'm finding to be great! I did have some questions, though.

    Is there a way to get a similar functionality to [CreateDerived] with ScriptableObjects?

    Let's say I have a ScriptableObject saved as an asset that contains List<AbstractBaseClass>.

    Is it possible to add derived classes to the ScriptableObject?

    What I want is to have a database of objects contained in a ScriptableObject, and each of those objects can have multiple subclasses (in my case I'm using Condition as a parent class and then there are child classes that derive from this, each node contains a list of Conditions that can be any of its children).

    Cheers!
     
  4. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    Not right now... Even if internally we do use something similar.

    Right now, there's safeguard in place that if you delete the owner of a ComponentMonoBehaviour, AI parse the hierarchy and delete the orphan. This is easy to do based on how GameObject and MonoBehaviour works. The GameObject is the trunk, and it always references all the branches.

    In the case of a ScriptableObject, if you delete the parent, there is simply no proper way to retrieve and delete the orphan. There is no trunk to start from to go down the hierarchy. Because there can't be any proper safeguard, someone could easily add dozen of ScriptableObject in the same asset, make them orphan, and be facing the issue that his asset file is growing in size and he doesn't have any way to fix it.

    Even worse, Unity doesn't allow us to dictate which ScriptableObject in an Asset file is primary one.

    We are still investigating ways to do that, but we don't have a proper solution yet.

    For now, I would advise you to use prefab as the role of data container when you need polymorphism.
     
    Last edited: Jul 23, 2016
  5. EMOTION-THEORY

    EMOTION-THEORY

    Joined:
    Jul 16, 2013
    Posts:
    65
    I see, thanks for the quick response. I'm trying to make a container for quests and dialogue. I'll let you know how I go using prefabs :)
     
  6. SFvdB

    SFvdB

    Joined:
    Mar 10, 2014
    Posts:
    12
    Great plugin! Loving it!

    Still somewhat inexperienced (especially when it comes to editor scripting) so this is a fantastic asset.

    However I am somewhat vague on how to style, for instance, a group. Is there a tutorial someplace? Should I use GUIEditor or something else? It wouldn't surprise me if I'm probably missing something :)

    Update
    Found the answers to my question - thanks for the asset - keep up the great work!

    Cheers!
     
    Last edited: Jul 23, 2016
  7. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    Let me know if you need anything.
     
  8. EMOTION-THEORY

    EMOTION-THEORY

    Joined:
    Jul 16, 2013
    Posts:
    65
    Hi @LightStriker, perhaps you can help me with something I'm trying to accomplish.

    So I have my List which looks something like this in Advanced Inspector



    Now, I'm storing a TYPE in a string and then getting a type using that string (you can see a greyed out getter in the inspector which says UnityEngine.Camera).

    In this class there is a field for an Object (UnityEngine.Object). When I pop open the list, I get the usual Assets / Scene list of compatible objects (which is almost everything, basically).

    I was wondering if there was a way to filter that list based on type? To tell it I'm only interested in Camera objects.

    Cheers.
     
  9. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    Why is the "value" field not a Camera type?

    What are you trying to achieve? (not how, but what)
     
  10. EMOTION-THEORY

    EMOTION-THEORY

    Joined:
    Jul 16, 2013
    Posts:
    65
    What I'm doing is storing a bunch of object reference variables in a list, so I can give them a name and stuff. Kind of like variables in PlayMaker, if you're familiar with that. The idea is so that I don't have to write new scripts for different objects and instead can add variables through the inspector. So if I wanted a camera or a collider or some kind of mono object I could add it through the inspector.

    I could write a custom inspector or property drawer and have an object property field and pass in a type parameter to do what I want, but I was wondering if you might know of a way or have a different suggestion. Maybe like an attribute that accepts a function name that returns a type. I wouldn't mind writing it myself if it doesn't exist, if you had any advice on that.

    Cheers :)
     
  11. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    You should look at the "RuntimeResolve" (AIExample29 and AIExample30). It allows you to control which type is displayed in the inspector. For example, you can have a field or a property of "System.Object" type, but display it as a material.
     
  12. EMOTION-THEORY

    EMOTION-THEORY

    Joined:
    Jul 16, 2013
    Posts:
    65
    Thanks, this looks EXACTLY like what I'm looking for. I'll give it a try. Cheers! :)
     
  13. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    Version 1.69 have been submitted to the Asset Store for approval with the following changelist;

    [CHANGES]
    • CreateDerived attribute now has HideClassName property, which hide the class name on the left of the "+" sign. False by default.
    • Don't pass down FieldInfo to PropertyDrawer if it's not a field. Makes some PropertyDrawer works on properties instead of only fields! (See UnityEvent)
    • Added Unity's Audio VU draw at the bottom of MonoBehaviour that have the proper OnAudioFilterRead implementation. Warning; lot of reflection involved.
    [FIXES]
    • Fixed a null exception when applying a Collection attribute on an empty dictionary.
    • Fixed that an object was not properly flagged as dirty when adding a file by drag'n'drop to a inner collection.
    • Fixed an issue where collection of ComponentMonoBehaviour would not duplicate properly in a copy/paste operation.
    • Fixed that multiple version of the same MonoBehaviour on the same GameObject had duplication issues with UnityEvent.
    • Allow copy-pasting objects that don't have a public constructor.
    • Fixed a major performance issue when inspecting deep nesting (level 4+)
    • Major speed boost when selecting very complex object.
    Note that PropertyDrawer working on properties is a feature that works for some drawers and not for others. By example, the drawer of UnityEvent works. However, if a drawer tries to access the "fieldInfo" property, it will return null.

    Also, I was advised to create a "Patreon" account, in case some would like to patron me. So this was done; https://www.patreon.com/user?u=3953035
     
  14. derkoi

    derkoi

    Joined:
    Jul 3, 2012
    Posts:
    2,001
    Hi, I'm getting this error when I use Scion in my project with Advanced Inspector:

     
  15. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    This appear to be fixed in the version 1.69 that was submitted to the store a few days ago. If you don't want to wait for the store approbation, you can send me a mail at admin@lightstrikersoftware.com, and I will send you the latest version.
     
  16. derkoi

    derkoi

    Joined:
    Jul 3, 2012
    Posts:
    2,001
    Thanks I will try the latest version when it's on the asset store.
     
  17. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    Version 1.69 is now available on the store.
     
  18. bomberest0

    bomberest0

    Joined:
    Oct 7, 2012
    Posts:
    12
  19. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    Hi,

    None of the example in the package gives any error. Can you give me a snippet of the code currently generating that issue?
     
  20. bomberest0

    bomberest0

    Joined:
    Oct 7, 2012
    Posts:
    12
    http://take.ms/UGB8j Any GO
     
  21. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
  22. mgmhunt

    mgmhunt

    Joined:
    Apr 1, 2013
    Posts:
    51
    I'm getting the same. Advanced Inspector Example window spits this out if I select any non-standard component.

    Code (csharp):
    1.  
    2. NullReferenceException: Object reference not set to an instance of an object
    3. AdvancedInspector.BehaviourEditor.OnInspectorGUI () (at A:/LightStrikerSoftware/Projet/AdvancedInspector/AdvancedInspector 5/Lib/AdvancedInspector/AdvancedInspector/InspectorEditors/BehaviourEditor.cs:90)
    4. UnityEditor.InspectorWindow.DrawEditor (UnityEditor.Editor editor, Int32 editorIndex, Boolean rebuildOptimizedGUIBlock, System.Boolean& showImportedObjectBarNext, UnityEngine.Rect& importedObjectBarRect) (at /Users/builduser/buildslave/unity/build/Editor/Mono/Inspector/InspectorWindow.cs:1235)
    5. UnityEditor.DockArea:OnGUI()
     
  23. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    Same thing... Which version of Unity are you on? I tried 5.2.0, 5.3.0, 5.3.4 and 5.4.0b19.

    Also, I most likely have a proper fix, so send me an email at admin@lightstrikersoftware.com.
     
  24. AleksLA

    AleksLA

    Joined:
    May 7, 2013
    Posts:
    22
    How can I have a preview of my prefab when I do
    " public GameObject PreviewPrefab;"

    I would like to see a thumbnail preview of that prefab, but not sure how to achieve it. Does anyone knows how ?
     
  25. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    A thumbnail preview? What do you mean?
     
  26. AleksLA

    AleksLA

    Joined:
    May 7, 2013
    Posts:
    22
    For example I have a collection of character skins and they are in a list of custom classes.
    But every object has reference to the actual skin prefab, and I would like to see image thumbnail for every of them in the panel where the collection resides and from there I will have also buttons next to each of the skin that I can click to activate that particular skin.

    Basically I need the ability to have thumbnails or images in that panel so I can stack them and show preview of what that prefab is about, but unlike the IPreview, I want to to be right where the other controls are , not in a separate window below and also I want it to be many previews, not just 1, because there will be many items.

    Not sure if what I am asking is possible, But the terrain editor in unity have something similar where the materials for drawing reside, they look like thumbnails and are even clickable.

    The Tree placement part in the unity built in terrain editor has the ability to see prefabs in thumbnail grid and they are even clickable, which means that the editor receives the event what is selected.
     
    Last edited: Sep 23, 2016
  27. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    Would it be too much to ask if you could make some quick photoshop mokeup? I'm having a hard time to imagine where you would want those image to show up in an Advanced Inspector re-orderable collection....
     
  28. AleksLA

    AleksLA

    Joined:
    May 7, 2013
    Posts:
    22
    I will do it tomorrow, I have been thinking about it , I will post screenshots.

    Thank you
    Aleks
     
  29. AleksLA

    AleksLA

    Joined:
    May 7, 2013
    Posts:
    22
    Here are samples of more or less what I mean.

    The API needed I think is "AssetPreview.GetAssetPreview" .
     

    Attached Files:

  30. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    I see.
    What's the select button?
     
  31. AleksLA

    AleksLA

    Joined:
    May 7, 2013
    Posts:
    22
    It is ability to give default method for that object.

    If we have
    class CollectionItem{
    [DefaultPrefab]
    public GameObject prefab;

    [DefaultAction]
    public void SelectMe(){ ... }

    public override ToString(){
    return "01_object_1"
    }

    }

    So in this case we can be easy to manage all sorts of collections containing prefabs and having custom actions.
     
  32. mcurtiss

    mcurtiss

    Joined:
    Nov 29, 2012
    Posts:
    15
    I'm having an issue with serializing changes made to scriptable objects.

    My use case looks something like this:

    Code (csharp):
    1.  
    2.  
    3. // MyScriptableObject.cs
    4. public class MyScriptableObject : ScriptableObject{
    5.      public Texture2D colorKey;
    6. }
    7.  
    8. // TextureGen.cs
    9. public class TextureGen : MonoBehaviour{
    10.  
    11.     public MyScriptableObject myScriptableObject;
    12.  
    13.     Texture2D colorKey;
    14.  
    15.     [Inspect]
    16.     public void GenColorKey(){
    17.         Color[] pix = new Color[512*512];
    18.         for(int i = 0; i < pix.Length; i++){
    19.              Color col = Color.red;
    20.              pix[i] = col;
    21.         }
    22.         colorKey =  new Texture2D(512,512);
    23.         colorKey.SetPixels(pix);
    24.         colorKey.Apply();
    25.  
    26.         myScriptableObject.colorKey = colorKey;
    27.     }
    28.  
    29. }
    30.  
    The changes show up in the editor - when i open up the scriptable object I can see that a texture has been assigned to it's colorKey property - but when I press play, the texture disappears from the scriptableobject, indicating that it hasn't been serialized. I've tried implementing IDataChanged, but that doesnt seem to do the trick. Any clues?
     
    Last edited: Sep 27, 2016
  33. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    Where is this ScriptableObject saved? You know the common use of ScriptableObject is to save data in files?
     
  34. mcurtiss

    mcurtiss

    Joined:
    Nov 29, 2012
    Posts:
    15
    I don't know the common use. Currently the scriptable object .asset is saved in Assets/ScriptableObjects. I should mention that it works fine with different data types, like Vector2 assignments. It just doesnt seem to want to serialize the textures.
     
  35. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    So you can select your ScriptableObject file in your folders?

    Have you setup that "colorKey" variable from your TextureGen class?
     
  36. mcurtiss

    mcurtiss

    Joined:
    Nov 29, 2012
    Posts:
    15
    Yes to both. I fixed the example code to include the "colorKey = new Texture2D(512,512);"
     
  37. mcurtiss

    mcurtiss

    Joined:
    Nov 29, 2012
    Posts:
    15
    I should note that I'm not getting a null refrence error when I check for the texture on play, but a
    "MissingReferenceException: The object of type 'Texture2D' has been destroyed but you are still trying to access it. Your script should either check if it is null or you should not destroy the object."

    Don't know if that helps or not.
     
  38. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    Well, if you create a new Texture and you don't save it anywhere... Of course it's getting flushed on a memory reload. Texture, if you want them saved, has to exists somewhere, like a texture file (TGA, PNG, JPG). They cannot exist inside a ScriptableObject. An easy way would be to just save a table of color in your ScripableObject and create the texture from it at runtime.

    Honestly, that has very little to do with Advanced Inspector, since, you know, it doesn't change Unity's serialization at all.

    Maybe you would prefer to send me an email if you want help about an unrelated topic?
     
  39. strich

    strich

    Joined:
    Aug 14, 2012
    Posts:
    278
    We're written our own framework that stores data in serialized blobs of our own classes that do not inherit from MonoB. I'd like to display these blobs in the editor as a normal component. We're written a 'container' class that essentially holds this blob, and it inherits MonoB so it can be placed on to prefabs.

    To display the internal blob of data, I assume I simply have to write a custom inspector that inspects the container class, deserializes the blob into instances of our own classes, then display those classes via the custom inspector.

    I was wondering if I could use Advanced Inspector to essentially give it a list of our internal classes sitting in memory and have it inspect and display as normal? Our classes will consist of simple types, so I'm hoping we won't have to manually write out inspector lines for each field, etc.
     
  40. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    With Advanced Inspector, you can inspect anything, not only stuff deriving from UnityEngine.Object.

    A little known - and not documented since it's such an edge case for advanced users - feature is InspectorWrapper. If you do;

    Code (CSharp):
    1. InspectorWrapper.Select(myObject);
    Advanced Inspector forces Unity to select and inspect "myObject" as if it was any normal Unity object.
     
  41. strich

    strich

    Joined:
    Aug 14, 2012
    Posts:
    278
    Rapid response! Cheers! Could you provide a brief summary of how it might look in a custom inspector editor? Currently I'm trying to inherit InspectorEditor. Would I call InspectorWrapper in OnInspectorGUI?

    My first tests just now seem to cause only the InspectorWrapper object to be shown, with everything else (Transform, etc) wiped out.

    EDIT: Okay I see what you mean re InspectorWrapper. I think it is not quite what I need. Almost though. I have an object in memory, and I want to tell AI to essentially parse it and provide the inspection code to fit inside of an OnInspectGUI for an individual component.
     
    Last edited: Sep 28, 2016
  42. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    It's a feature that is used - usually - from another EditorWindow or tool. You need some place to actually provide a way to "select" the data you want to inspect.

    We have a graph node tool like this;



    We can select the wired that connect two node. You can see the top left wire is currently selected.

    Usually, Unity wouldn't allow us to inspect it, because it's a plain normal object;

    Code (CSharp):
    1.     [Serializable]
    2.     public sealed class Wire : IPingable
    3.     {
    4.         [SerializeField]
    5.         private Node sourceNode = null;
    6.  
    7.         internal Node SourceNode
    8.         {
    9.             get { return sourceNode; }
    10.             set { sourceNode = value; }
    11.         }
    12.  
    13.         /* more stuff */
    14.     }
    So in the EditorWindow code that draws those, we do;

    Code (CSharp):
    1.         private void DrawWireControl(Wire wire, Vector2 position)
    2.         {
    3.             Rect rect = new Rect(position - new Vector2(5, 9), new Vector2(16, 16));
    4.             if (rect.position.x + rect.size.x < 0 || rect.position.y + rect.size.y < 0 ||
    5.                 rect.position.x > this.position.width || rect.position.y > this.position.height)
    6.                 return;
    7.  
    8.             Event current = Event.current;
    9.             switch (current.type)
    10.             {
    11.                 case EventType.Repaint:
    12.                     GUIStyle radio = GUI.skin.horizontalSliderThumb;
    13.                     // Is this wire selected?
    14.                     radio.Draw(rect, false, false, false, InspectorWrapper.IsSelected(wire));
    15.  
    16.                     break;
    17.                 case EventType.MouseDown:
    18.                     if (rect.Contains(current.mousePosition))
    19.                     {
    20.                         // Select the wire and trick Unity into thinking it's a proper object
    21.                         InspectorWrapper.Select(wire);
    22.                         current.Use();
    23.                     }
    24.                     break;
    25.             }
    26.         }
    Which gives this result;

     
  43. strich

    strich

    Joined:
    Aug 14, 2012
    Posts:
    278
    Yeah it is a good start. However I want to inspect it in amongst other normal Unity components. I need to be able to select the prefab, have other components render as normal, but for our custom component we need to perform our own deserialization to an object, then inspect and display.
     
  44. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    Then you will need some kind of entry point on the GameObject.

    Why you don't want your component to show up as being part of the MonoBehaviour that deserialized them?
     
  45. strich

    strich

    Joined:
    Aug 14, 2012
    Posts:
    278
    Because it is important that only variables that we use at runtime are on the class. The data is being serialized to and from a file that the class only has a reference to.
     
  46. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    You can show and hide anything you want, based on the condition you want.
     
  47. strich

    strich

    Joined:
    Aug 14, 2012
    Posts:
    278
    Well, no, that field will sit in memory and will be visible to our code team when they're writing runtime code. I'd like to keep this separate. Basically we want to be able to tell AI to draw an inspector for an object that isn't referenced via a field. Exactly like how InspectorWrapper.Select works, except it can work within an OnInspectorGUI() without wiping out the entire inspector.
     
  48. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    No, I mean you can inspect a field of type "object", you know? You can put whatever you want in it. AI is pretty much made to handle polymorphism. You can even flag it with [DisplayAsParent] and all the inner member shows up as being part of the parent object.
     
  49. strich

    strich

    Joined:
    Aug 14, 2012
    Posts:
    278
    So there is no way to tell AI to draw an inspector for objects in memory without fields?

    Check out Editor.CreateEditor(): https://docs.unity3d.com/ScriptReference/Editor.CreateEditor.html
     
  50. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,451
    So you want to inspect something that is unrelated to what is currently selected?

    Like say... The Material editor showing up when you inspect a MeshRenderer?