Search Unity

[Editor Tool] Better ScriptableObject Inspector-Editing

Discussion in 'Assets and Asset Store' started by TheVastBernie, Jul 21, 2017.

  1. Fydar

    Fydar

    Joined:
    Feb 23, 2014
    Posts:
    69
    Hay @spesifikbrush, are you sure you're using my iteration of the script? I draw a background around the children objects.

    This was an issue that appeared in some of the earlier scripts in this thread.

    If you need a hand finding it then let me know :) Good luck!
     
  2. MasonWheeler

    MasonWheeler

    Joined:
    Apr 2, 2016
    Posts:
    219
    Will the Expandable attribute work on a ScriptableObject array, to make all the objects within expandable?
     
  3. Fydar

    Fydar

    Joined:
    Feb 23, 2014
    Posts:
    69
    @MasonWheeler Yeah :) My implementation of it handles arrays no-problem. Goodluck!
     
  4. MasonWheeler

    MasonWheeler

    Joined:
    Apr 2, 2016
    Posts:
    219
    Unfortunately, that doesn't appear to extend to arbitrary list-like types.

    I'm trying to create a system with an abstract base class and several classes that inherit from it, and an array/list/whatever of these objects. I have four constraints that must be met:

    1. All the objects within the array need to be editable in the inspector.
    2. The array needs to have a reorderable list with + and - buttons
    3. Because this is a bunch of descendants of an abstract type, the + button needs to open a list of classes so you can choose which one to add.
    4. The system needs to be extensible, with third parties able to add new classes, which will smoothly integrate into the existing system.

    Point 4 means I can't statically create a list of all possible types and some easy way to create them; instead I need to rely on reflection and some type of CreateInstance instantiator.

    Points 2 and 3 ought to be handled by this editor, but the only way I can get instantiation to work properly is if the base class is a ScriptableObject descendant, which I don't particularly want but nothing else seems to work. But I can't edit ScriptableObjects inline in the inspector.

    The custom editor I linked to works by using a custom
    ReorderableArray<T>
    class which is basically a wrapper around
    List<T>
    . But putting
    [Expandable]
    on a property of that class type doesn't make the ScriptableObjects inside expandable.

    This whole thing is driving me up the wall. Every time I solve one problem, it just creates some new one. Any idea how I could implement this and get it working?
     
  5. villevli

    villevli

    Joined:
    Jan 19, 2016
    Posts:
    87
    You could try to put the
    Expandable
    attribute on the array property inside the ReorderableArray class. This would be in the https://github.com/cfoulston/Unity-Reorderable-List/blob/master/Runtime/ReorderableArray.cs file.
    Code (CSharp):
    1.     [Serializable]
    2.     public abstract class ReorderableArray<T> : ICloneable, IList<T>, ICollection<T>, IEnumerable<T> {
    3.  
    4.         [Expandable]
    5.         [SerializeField]
    6.         private List<T> array = new List<T>();
    7. ...
     
  6. MasonWheeler

    MasonWheeler

    Joined:
    Apr 2, 2016
    Posts:
    219
    That almost works. It can draw them expanded now, but they aren't expanded inline, but rather below the rest of the control. I can fix that, but I need to know the height in pixels of the expanded box. How would I go about finding out what that is?
     
  7. Fydar

    Fydar

    Joined:
    Feb 23, 2014
    Posts:
    69
    Are you sure your using my implementation of the [Expandable] attribute? Some implementations in this thread use GUILayout which doesn't work for PropertyDrawers!
     
  8. MasonWheeler

    MasonWheeler

    Joined:
    Apr 2, 2016
    Posts:
    219
    Yes. Thankfully, though, I was able to work out a different implementation that doesn't require them to descend from ScriptableObject. Having
    [SerializeReference]
    available in 2019.3 is really nice; it makes the polymorphism suddenly work the way it should have all along.
     
  9. SerializeField

    SerializeField

    Joined:
    May 22, 2017
    Posts:
    22
    I really like this, it's great! But when I change a scriptable object's value in the editor, it doesn't trigger OnValidate().
    Does anyone know how to enable this?
     
  10. Deleted User

    Deleted User

    Guest

    Please help. I'm clearly misunderstanding something. I have the Expandable code as provided (the later version).
    I have a simple ScriptableObject:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class TestSO_1 : ScriptableObject
    4. {
    5.     public int item1;
    6.  
    7.     public string item2;
    8. }
    And a simple MonoBehaviour:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class TestMonoBehaviour : MonoBehaviour
    4. {
    5.     [Expandable]
    6.     public TestSO_1 so1;
    7. }
    When I add the MonoBehaviour to a GameObject, instead of the expanded ScriptableObject, I get:

    upload_2020-6-23_14-18-30.png

    What have I missed?
     
  11. inkletom

    inkletom

    Joined:
    Oct 13, 2016
    Posts:
    63
  12. BPR

    BPR

    Joined:
    Jan 4, 2013
    Posts:
    56
    You need to set the reference to an actual scriptable object instance first to expand it in inspector, right now your reference is null. Create scriptable object of the type TestSO_1 under Assets and link it first, to create it via the right click context menu, add the following code at the top of your class:

    Code (CSharp):
    1.  
    2. [CreateAssetMenu(fileName = "TestSO_1", menuName = "SO/Test", order = 0)]
    3. public class TestSO_1 : ScriptableObject
    Great tool guys, thanks a lot!
     
  13. Sagna

    Sagna

    Joined:
    Mar 28, 2019
    Posts:
    1
    Hello @Fydar , first of all, thanks everyone for this, was just the thing i was looking for, but i noticed one thing, if i update the value on a scriptable object in runtime, the inspector doesn't auto update, but if i click on another object and then click back on the object that has the script and SO, it updates.
     
    Last edited: Aug 4, 2020
  14. Deleted User

    Deleted User

    Guest

    Thanks, your timing is perfect as I've just returned to this part of the code.
     
  15. Linaran

    Linaran

    Joined:
    Dec 14, 2017
    Posts:
    4
    I'd recommend someone (probably one of the authors) collect the scripts, unify them in a working unit and publish it on github. Having the code on github would make sure people are getting the latest version (not something pieced together from a forum thread), it would be easy for people to check how to install the code into your project and Github has a designated place for all issues and per-issue discussions.

    I mean what I said is a bit captain obvious but as far as I can tell no attempt was made to put this on github?
     
    WAYNGames, gasppol and Fydar like this.
  16. Pilchardo

    Pilchardo

    Joined:
    Aug 10, 2014
    Posts:
    2
    This is great! Thanks for all the hard work that's gone into it. I'm having one small issue. I have a series of nestable 'reports' that look like this:

    Code (CSharp):
    1. public class Report : ScriptableObject {
    2.  
    3.     [SerializeField]
    4.     private List<string> messages = new List<string>();
    5.  
    6.     [Expandable]
    7.     [SerializeField]
    8.     private List<Report> reports = new List<Report>();
    9.  
    10.     public List<string> Messages { get => messages; }
    11.     public List<Report> Reports { get => reports; }
    12.     public string Name { get => name; }
    13.  
    14.     public static new Report CreateInstance(string name) {
    15.         var report = CreateInstance<Report>();
    16.         report.name = name;
    17.         return report;
    18.     }
    19.  
    20.     public void Log(string message) {
    21.         messages.Add(message);
    22.     }
    23.  
    24. }
    When I include one of these reports on a MonoBehaviour and expand its nested reports in the editor, I get this error coming from Unity's EditorGUI class:

    Despite this, the nested reports appear to render correctly. The only strange thing is that the first element of each nested list expands automatically right down into the tree when I expand the top-level one. Is it perhaps trying to expand an element at the bottom of the structure that doesn't have any children? I've just added a catch for the ArgumentOutOfRangeException for the time being as that allows everything to work acceptably well, but I wonder if there's a more elegant solution?
     
  17. nratcliff

    nratcliff

    Joined:
    Jul 5, 2014
    Posts:
    66
    +1 for this. I see a lot of "are you sure you have the right version?" in this thread. That could be solved by publishing a simple package on GitHub. Plus, it would allow people to create issues instead of hashing it all out in this single thread.

    I'm happy to set this up if the original authors/maintainers (@Fydar, @TheVastBernie) don't mind.
     
  18. kiilljoy

    kiilljoy

    Joined:
    Sep 26, 2020
    Posts:
    1
    So glad I found this thread. I'm still pretty fresh to the C# and Unity, and making one of these on my own would have been a long process, and not look near as nice. Thanks to all the contributors. The part I missed when trying to get it working at first was the addition of a "Attribute" folder and class to get the [Expandable] to work.
     
  19. Bizio

    Bizio

    Joined:
    Apr 3, 2015
    Posts:
    11
    The expandable assets seem to be broken in newer unity version with new reordable lists unity implemented. If you have a list of serialized class objects you can't expand specifc objects in the list unfortunatelly. Any solution?
     
    Last edited: Jun 6, 2021
  20. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    991
    Hello, thank you for this very useful script. Based on that script and the fact that it's under MIT license, I took the liberty of wrapping it into a unity package for "easier" use in my (and hopefully anyone's) project.


    I did make 2 minor changes to your script:

    1) abstract the class

    2) remove the class CustomPropertyDrawer attribute.


    This was done to avoid applying by default the property drawer on all scriptable object, which can be confusing if the project makes heavy use of scriptable object (like including the Localization package) or simply to avoid confusing user when importing to existing projects. to compensate I provide a script template to easily create property drawer for wanted scriptable object (you can still make it work for all with a single file if you want).


    I tried to make good notice of your original work (in the file, the readme and third party notice), let me know if you want some changes.


    Code available here https://github.com/WAYNGROUP/WAYN-Editor-Extension


    If anyone has any feedback it's more than welcomed.

    I'll probably work on making it available in OpenUPM by the end of the week begining of next week.
     
    jmortiger, RiverINN and Smithy43 like this.
  21. YggdrasilGames

    YggdrasilGames

    Joined:
    Dec 12, 2019
    Posts:
    1
    It interacts perfectly well. I use it and I tested it on some extreme cases such as Dictionaries of dictionaries etc.
    Your script saved quite a lot of trouble for me. Thnaks
     
  22. HercDotMe

    HercDotMe

    Joined:
    Sep 27, 2017
    Posts:
    12
    Almost 5 years since the original post, thank you very much, sir!
     
  23. WonkyDonky

    WonkyDonky

    Joined:
    Aug 24, 2014
    Posts:
    65
    Editing individual float works but it seems I can't edit list or array elements, it immediately snaps back to previous value?
     
  24. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    302
    "The expandable assets seem to be broken in newer unity version with new reordable lists unity implemented. If you have a list of serialized class objects you can't expand specifc objects in the list unfortunatelly. Any solution?" - I'm having this issue as well. :(

    @Fydar do you know of a solution for this issue or is this a Unity bug?

    A workaround is to mark the lists in question as NonReordable, but that sucks!


    EDIT:
    Actually found this issue: https://issuetracker.unity3d.com/is...s-not-open-arrays-that-are-of-different-level

    And just trying real quickly, this seems to fix the issue, change to this in the OnGUI method:
    Code (CSharp):
    1. targetObject = targetObject == null ? new SerializedObject(property.objectReferenceValue) : targetObject;
    Unsure what issues this might cause going forward (as I'm not very familiar with how PropertyDrawers work), so there's probably a better way to do this, especially now knowing that this is the issue!
     
    Last edited: Feb 17, 2022
  25. AustinMclEctro

    AustinMclEctro

    Joined:
    May 3, 2017
    Posts:
    16
    This is exactly what I needed for my use case, thank you so much @Maisey.

    I've got an EditorWindow that I'm using as a special scriptable object editor. I'm using this to show the parameters of the scriptable object so I can edit them from the EditorWindow.

    Here's the piece in my window's OnGUI method doing this:

    Code (CSharp):
    1.  
    2. ...
    3. public class DefinitionEditorTool : EditorWindow
    4. {
    5. ...
    6.     private void OnGUI()
    7.     {
    8.             ...
    9.             _editedDefinitionObject = EditorGUILayout.ObjectField(new GUIContent("Definition To Edit"), _editedDefinitionObject, typeof(Definition), false);
    10.             if (_editedDefinitionObject != null)
    11.             {
    12.                 var editor = Editor.CreateEditor(_editedDefinitionObject);
    13.                 editor.OnInspectorGUI();
    14.             }
    15.             ...
    16.     {
    17. ...
    18. }
    19.  
    The problem I was having:
    • Unable to edit scriptable object List contents specifically through the EditorWindow when showing the scriptable object's properties via an inline editor.
      • The edited scriptable object contains a list. When using editor.OnInspectorGUI() to show the scriptable object's properties in the EditorWindow, the contents of the list could not be edited through the EditorWindow.

        The list shown in the EditorWindow refreshes with updates when I edit the scriptable object directly in the regular Inspector, but trying to modify it from the EditorWindow does nothing. However, I can change the size of the List from the EditorWindow successfully.
    Adding the [NonReorderable] attribute above the list in my scriptable object takes away the ability to reorder its items, but in my case it does not matter. I just need to edit the list's contents.

    Code (CSharp):
    1.  
    2. ...
    3. public class Definition : ScriptableObject
    4. {
    5.     ...
    6.     [NonReorderable]
    7.     public List<DefinitionVariant> Variants;
    8.     ...
    9.  
    Follow up open question:
    • What exactly would we do here to keep the list reorderable, but then able to edit the scriptable object's list contents via the EditorWindow?

      Maisey, I'm not sure that the quick fix you posted works with my example here. I've debugged the list when I set it, and it looks like the edited scriptable object's list never receives objects from the EditorWindow, regardless of what is selected for its contents (selecting None, or any other DefinitionVariant object). Otherwise we could just set the property.objectReferenceValue to the chosen object (property being the scriptable object's list in this case).
     
    Last edited: Jun 22, 2022
  26. jmortiger

    jmortiger

    Joined:
    Sep 2, 2018
    Posts:
    5
    Currently, in Unity 2021.3.4f1, this doesn't seem to work. Both during installation and when attempting to use the template option in the Create/WAYN/Editor/ExtendedScriptableObjectDrawer context menu, errors pop up.
    Install Errors:
    InstallErrors.png
    Usage Error:
    upload_2022-9-6_10-39-40.png
    I'd assume it's simply a packaging problem. Having a simple package source for this would be great, here's hoping this is changed.
     
  27. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    991
    Are you by any chance working from a networked folder ? It does not seem to be related to the package itself but to a lack of permission of the user importing the package or creating a script from template.
    I add the issue when working from a local NAS. I solved the issue by granting full permission to everyone which confirmed the source of the issue but isn't great for security.
    I ended up moving back to a local project folder.

    Second message may be because the package was not imported properly but the mention of Wayn_group is odd. I'll have look at that after work.
     
  28. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    991
    @jmortiger , git repositaory has been updated to fix the template creation error. thanks for the report.
    I tested in a new 3D project with unity 2021.3.6f1 and it works.
     
    Last edited: Sep 6, 2022
    jmortiger likes this.
  29. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    991
  30. jmortiger

    jmortiger

    Joined:
    Sep 2, 2018
    Posts:
    5
    Glad to hear, thank you.
    I'm not using any cloud storage, and I'm certain I never have (unless you count installing/updating packages to local storage via git repos and source control through Plastic & GitHub, which I'm almost certain you don't). I'll give it another go and let you know (assuming I remember to).
     
  31. Leyren

    Leyren

    Joined:
    Mar 23, 2016
    Posts:
    29
    One issue I noticed: my scriptable object contains a list of enum-values. I can add and remove values from that list, I can also access the enum dropdown as usual - but I can't change the value. When clicking on the enum value in the dropdown it is just ignored.

    Structure:
    Gameobject
    |-- Scriptableobject
    ___|-- List<Foo>
    where Foo is an enum.
     
  32. jmortiger

    jmortiger

    Joined:
    Sep 2, 2018
    Posts:
    5
    TL;DR Have you looked into @AustinMclEctro 's post?

    Doing some quick tests using a version that's (almost) identical to WAYN_Games' package (or Tom Kail's gist, don't recall which I started from), that doesn't seem to be the case. Could you show your scriptable object script and the monobehviour that's holding the scriptable object?
    My test looked like this:

    Code (CSharp):
    1.  
    2. public class PIDSettingsObj : ScriptableObject, IPIDSettingsFull//, JMor.Utility.Inspector.IHasPropertyInspectors
    3.     {
    4.         public System.Collections.Generic.List<EventModifiers> test;
    5. ...
    6. }
    My MonoBehaviour looked like this:
    Code (CSharp):
    1.  
    2.     public class Targeter : MonoBehaviour
    3.     {
    4.  
    5.         [Expandable] public PIDSettingsObj pidSettings;
    6. ...
    7. }
    And everything worked correctly. It's possible you're having a similar problem with whichever of the 50 versions you're using/derived your implementation from as AustinMclEctro. The [NonReorderable] attribute might solve the problem.
     
  33. jmortiger

    jmortiger

    Joined:
    Sep 2, 2018
    Posts:
    5
    Btw, if anyone is toying with this and wants a different solution to the foldout drawn as a label to combat interactivity issues with the , you might be able to simply draw the object field twice. I had a problem with control weirdness due to elements overlapping before, and this fixed it.

    For my example, I was drawing buttons over an ObjectField. Drawing the buttons before the ObjectField allows the buttons interaction to take precedence, but draws the object field over them. Drawing the buttons after the ObjectField draws the the buttons over the object field. but then the object field interaction takes precedence. Removing the object field during attempts to draw the buttons won't erase the editor window, but will stop the change check from setting the values. Drawing the buttons twice, first to prioritize their interactions, then to draw them over the object field visually, gives the intended behavior.

    Figured I'd post it here in case it comes up for anyone else.
     
  34. alikun

    alikun

    Joined:
    Oct 17, 2018
    Posts:
    17
    Hey

    I saw several snippets + remakes
    So which approach is works the best?
     
  35. mm1982

    mm1982

    Joined:
    Apr 28, 2015
    Posts:
    35