Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[RELEASED] Odin Inspector & Serializer - The Ultimate Workflow Tool ★★★★★

Discussion in 'Assets and Asset Store' started by jorisshh, Jun 15, 2017.

  1. RecursiveRuby

    RecursiveRuby

    Joined:
    Jun 5, 2013
    Posts:
    163
    As in when the gameobject with the inspector is selected? I hadn't thought of that actually. Would it be possible to do both? I can see various use cases where both would be desirable.
     
  2. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Yes, it is. And it'll be out very soon. If you need it ASAP, feel free to send us a message from our website with your Odin invoice ID, then I can send it to you right away.

    Hmm, not entirely sure what you mean, but it does sound like that what you're asking for would require a new formatter. But there may be other options. Could you throw together an example where it messes complicate things in git?
     
  3. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Exactly my thinking as well - and that's where it gets a bit difficult for Odin. Because with 1.1 properties are not created or evaluate if they are not actually being rendered in the inspector. So in order for that attribute to work properly, we would have to add a special special case where we scan the entire tree and somehow make it work somehow make it work from there, only to add support for that attribute, so we're not a fan of adding it atm.
     
  4. RecursiveRuby

    RecursiveRuby

    Joined:
    Jun 5, 2013
    Posts:
    163
    Ah yea I can understand how that would be complicated. Well even functionality to only show while the inspector is selected would greatly help with some things I was trying to achieve. Assuming its not overly complicated for you to implement in that case of course.
     
  5. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Noted :) No promises though.
     
  6. vzlomvl

    vzlomvl

    Joined:
    Jun 25, 2016
    Posts:
    43
    I have class TreeData:

    public class TreeData : ScriptableObject, ISerializationCallbackReceiver
    {
    [SerializeField, HideInInspector]
    private SerializationData serializationData;
    [OdinSerialize]
    private List<ActionNode> nodes = new List<ActionNode>();

    void ISerializationCallbackReceiver.OnBeforeSerialize()
    {
    UnitySerializationUtility.SerializeUnityObject(this, ref serializationData);
    }

    void ISerializationCallbackReceiver.OnAfterDeserialize()
    {
    UnitySerializationUtility.DeserializeUnityObject(this, ref serializationData);
    }
    }

    The average size of nodes array in project is 250-300 elements. If I add in existing tree a new element I get 250 changes of ID. This makes unreadable changes in commit. For example in Source Tree its look like with:
    upload_2018-3-6_13-43-38.png
    upload_2018-3-6_13-45-35.png
    upload_2018-3-6_13-44-56.png
    And another problem is if two developers change same file it is much harder to resolve conflicts.
     
    Last edited: Mar 6, 2018
  7. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Thanks a lot for that, exactly what I was looking for. I've opened up an issue here: https://bitbucket.org/sirenix/odin-inspector/issues/301/make-the-node-format-more-merge-friendly Our serialization guy is not with us at the moment but he'll be back to work on Odin in two months time. I know he also have been talking about adding a new and improved node format. So this is definitely something we'll look into.

    But until then, there is not much I can recommend sorry. To clean things up, you could call an overload that forces Binary serialization or implement the IOverridesSerializationFormat. That would clean things up in the source-tree, as the byte array is stored as a base64 string. But the drawback is of course that merging conflicts of members serialized by Odin would no longer be possible.

    Code (CSharp):
    1.  
    2. public class TreeData : ..... , Sirenix.Serialization.IOverridesSerializationFormat
    3. {
    4.     ...
    5.     public DataFormat GetFormatToSerializeAs(bool isPlayer)
    6.     {
    7.         return DataFormat.Binary;
    8.     }
    9. }
     
  8. joaobsneto

    joaobsneto

    Joined:
    Dec 10, 2009
    Posts:
    152
    Hi,

    I'm about to buy Odin and I have this decision point. I need to add handles and custom gizmos to my editors. I can see by these messages that OnSceneGUI is not supported, but can I use Odin custom inspector and write my editor class that implements OnSceneGUI?

    Thanks
     
  9. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    You can still use OnSceneGUI like you're used to in Unity. We don't prevent you from doing it, this was just a request for an OnSceneGUI attribute which would make life a little easier. But you can just just inherit from OdinEditor instead of Editor and do you OnSceneGUI logic in there. Or use the OnDrawGizmos if you prefer. All of that still works.
     
    joaobsneto likes this.
  10. joaobsneto

    joaobsneto

    Joined:
    Dec 10, 2009
    Posts:
    152
    Thanks! I just bought the asset, great tool! I trying to use OnDrawGizmos and let the user change in the inspector only, but if I change a property, it does not redraw. There is a way to do that?
     
  11. emrys90

    emrys90

    Joined:
    Oct 14, 2013
    Posts:
    755
    I just started using this asset today, but I'm running into some issues with existing custom property drawers that I have. It appears to be using the drawer for the list, instead of just the elements like Unity does. Is there a way to say that a property drawer/attribute is only for a lists elements?

    Also, it appears that I cannot collapse classes/structs that are in an array? Is there a way I can change that?
     
    Last edited: Mar 9, 2018
  12. Oxeren

    Oxeren

    Joined:
    Aug 14, 2013
    Posts:
    120
    Hey guys!
    Odin is awesome and really increases the workflow efficiency.
    The only thing that slightly bothers me is that it couples the code with it's inspector representation. I mean, I understand that it is the point and it is what speeds up the workflow, but it would be cool if there was a way to somehow decouple Odin's attributes from actual scripts - maybe the ability to specify attributes in separate file or somewhere in script metadata or somethings.

    Thanks!
     
    Last edited: Mar 9, 2018
  13. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    1,276
    Hello :)

    I have some data with scriptableobjects inside of it, and some more scriptableobjects inside of those. I'm wanting to save and load this data to a JSON, but Unity's JSON serializing does not support this :(

    Does Odins, and if so, is there any documentation on this?

    Thank you so much!

    EDIT: Looks like I found my answer. I just use
    Code (csharp):
    1.  
    2. byte[] bytes = SerializationUtility.SerializeValue(masterSave, DataFormat.JSON);
    3. File.WriteAllBytes(filepath, bytes);
    4.  
    However, sadly it looks like I'll need to redesign some stuff... when I use the binary save, the file ends up being 12 kb, which sounds small now, but if the player explored the whole world that could easily add up to many many mb, perhaps even gigabytes. Clearly I need to figure out a way to not save uneeded data.

    Thank you ^_^
     
    Last edited: Mar 10, 2018
  14. blitzvb

    blitzvb

    Joined:
    Mar 20, 2015
    Posts:
    284
    Hey,

    Do you have an example on how to draw a banner icon at the top of an inspector?

    Thanks in advance.
     
  15. joaobsneto

    joaobsneto

    Joined:
    Dec 10, 2009
    Posts:
    152
    Why?!?!? I think it's pretty straight forward the way it is. Using an external file to represent the editor of an Unity component will be pretty annoying. It's like Unity standard behaviour of having another script to do the editor, two files for one thing.
     
  16. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    There is an example of that attributes overview demo scene where we showcase the OnInspectorGUI method. But if it's something you need a lot, then you could easily make your own Banner attribute :) Or say Draw all these types with a banner above. There is lots of options :)
     
  17. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    You can just call SceneView.RepaintAll in the OnDrawGiszmos, but it was actually a bug, that changing values didn't trigger it, It's is fixed in 1.0.6.1 So, thanks!
     
    joaobsneto likes this.
  18. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Hmm, that sounds strange, we'll look into that. Could you share some code that reproduces the issue? The only workaround I can think of right now is to convert it to Odin drawers or try your luck with using the [DrawWithUnity] attribute on the list.
     
  19. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    You literally summarized what patch 1.1 is all about :D We talk a bit about it in the latest patch notes down at the bottom:

    http://sirenix.net/odininspector/releasenotes/1-0-6-1

    But to quote:

    So in your case, to start off with, you would just make an AttributeResolver<YourType>() and customize it from there. Later we could also make an easier way of doing it, but the focus is just to get the systems in place first that lets us do it, then we can figure out later how to make it nice and convenient.
     
    Alex_May likes this.
  20. hungrybelome

    hungrybelome

    Joined:
    Dec 31, 2014
    Posts:
    336
    Hi,

    Is there a way to serialize a dictionary to a field via script, and not through the inspector? I am pulling down a dictionary from a server and then attempting to serialize it as a field within a scriptable object (only from within the editor, not runtime). I'm not sure which APIs to use, and I assume that Odin uses a different workflow than the built-in https://docs.unity3d.com/ScriptReference/SerializedProperty.html.

    Thanks!

    *EDIT*
    Wow, just saving to the field directly and then calling EditorUtility.SetDirty on the scriptableobject seems to serialize it just fine. So awesome! Odin Inspector is working great with Google Sheets.
     
    Last edited: Mar 13, 2018
    bjarkeck and joshcamas like this.
  21. dantonel

    dantonel

    Joined:
    Dec 7, 2015
    Posts:
    8
    Is there a way to change the order that enum values are sorted in the dropdown without changing the order/values of the enum items themselves? I want to sort alphabetically, but cannot change the numerical values of enum items because they are serialized and saved in prefabs/scenes already.
     
  22. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    978
    1) I would like to create a button with a Sprite as GuiContent (not a texture) in an OdinEditor script, is that possible?

    I want sprites instead of textures because it displays my altas instead of the individual sprites spliced up in the altas.

    upload_2018-3-15_0-4-4.png

    2) Additionally, when I click on the button I'd like the ObjectField's picker to come up instead of having to clutter my inspector with both a button and an ObjectField. Can that be achieved?

    Great tool guys, really enjoying it.
     
  23. Deleted User

    Deleted User

    Guest

    Hello! Is it possible to colorize list elems depending on the value?
     
  24. Alex_May

    Alex_May

    Joined:
    Dec 29, 2013
    Posts:
    198
    This way is working out well for me. I now want to add a new menu item at the bottom where if I click on it, a new instance of the scriptable object type Form is created in the asset database and added to the menu tree just above that item (and then selected). I thought of inheriting from OdinMenuItem and intercepting the mouse event - will that work? It doesn't look like I can override HandleMouseEvents:
    Screen Shot 2018-03-15 at 15.49.03.png

    Not sure what to do - any hints?
     
  25. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,204
    @bjarkeck I have a Generic custom object I created which doesn't seem to Serialize in the Unity inspector due to inheritance issues. Thus, I'm using the [OnInspectorGUI] attribute to have a method that shows the object's members in the inspector using EditorFields, so I can edit them as if they were a supported type. So far this has worked for the individual objects.

    I seem to be running into an issue when I want to display the Objects as an editable List, and I'm unsure of how to do that with Odin. I tried SirenixEditorGUI.BeginVerticalList(), but this only lists them as a List that is non-editable. Is there a way to draw an editable List of objects with the +/- button in the inspector?

    EDIT: Not sure if this is worth mentioning, but due to the being part of a larger company, I'm not able to upgrade to the latest version yet, and we're running Odin Inspector Version 1.0.5.3.
     
    Last edited: Mar 16, 2018
  26. PlutDem

    PlutDem

    Joined:
    Dec 5, 2013
    Posts:
    4
    Hi, is it possible to somehow draw OdinInspector for a class that is not derrived from UnityEngine.Object?
    Code (CSharp):
    1. public class MyObject // not a MonoBehaviour!
    2. {
    3.     [Title("MyObject")]
    4.     public List<float> FloatList;
    5. }
    6. ...
    7. Editor = OdinEditor.CreateEditor(myObject); ///???
    8. Editor.DrawDefaultInspector();
     
  27. hungrybelome

    hungrybelome

    Joined:
    Dec 31, 2014
    Posts:
    336
    I'm seeing a bug with enum-keyed dictionaries, where I am unable to add more keys, and trying to add a new key will result in changing the key-value of an existing entry. I believe this happens when there are 2 enum-keyed dictionaries that have keys of the same enum type, but in this video there is only one serialized enum-keyed dictionary. Video: https://imgur.com/a/xNa0f. As a work-around for now I am just using int-keyed dictionaries, and then casting. But this is for non-performance critical code, so I'd prefer actual enum keys over ints.
     
  28. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,204
    Try doing what I did. Create a an inspector that shows the EditorFields for each member of the Object.
     
    bjarkeck likes this.
  29. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Sounds like a custom drawer together with the new Odin Selectors :)

    Code (CSharp):
    1. [OdinDrawer]
    2. public class CustomEnumDrawer : OdinValueDrawer<MyEnum>
    3. {
    4.     protected override void DrawPropertyLayout(IPropertyValueEntry<MyEnum> entry, GUIContent label)
    5.     {
    6.         var rect = EditorGUILayout.GetControlRect(label != null);
    7.  
    8.         if (label == null)
    9.         {
    10.             rect = EditorGUI.IndentedRect(rect);
    11.         }
    12.         else
    13.         {
    14.             rect = EditorGUI.PrefixLabel(rect, label);
    15.         }
    16.  
    17.         if (GUI.Button(rect, entry.SmartValue.ToString(), EditorStyles.popup))
    18.         {
    19.             EnumSelector<MyEnum> selector = new EnumSelector<MyEnum>();
    20.             selector.SetSelection(entry.SmartValue);
    21.             selector.SelectionTree.SortMenuItemsByName();
    22.             selector.ShowInPopup(rect.position);
    23.             selector.SelectionConfirmed += x =>
    24.             {
    25.                 entry.SmartValue = x.FirstOrDefault();
    26.                 entry.ApplyChanges();
    27.             };
    28.         }
    29.     }
    30. }
     
  30. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Glad you like it, thanks! Sounds like more of a general Unity Editor question? Unless I misunderstood something? But you can get the texture of an asset by doing: AssetPreview.GetAssetPreview(sprite) which will give you a texture for that particular sprite. Hope that helps.
     
    FeastSC2 likes this.
  31. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    You can use the ListDrawerSettings, and use the OnBegin/EndListElement field for that, and set the GUI.color from there. We also have a GUIHelper.Push/PopColor which makes it a bit simpler:

    Code (CSharp):
    1.  
    2.     [ListDrawerSettings(OnBeginListElementGUI = "BeginDrawListItem", OnEndListElementGUI = "EndDrawListItem")]
    3.     public int[] list;
    4.  
    5.     private void BeginDrawListItem(int index)
    6.     {
    7.         var val = this.list[index];
    8.         GUIHelper.PushColor(val % 2 ? Color.red : Color.greed);
    9.     }
    10.  
    11.     private void EndDrawListItem(int index)
    12.     {
    13.         GUIHelper.PopColor();
    14.     }
     
    Deleted User likes this.
  32. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    I don't see why we could make the HandleMouseEvents virtual as well. Might do that.

    But there is the also the OnDrawMenuItem which sounds like exactly what you are looking for. From the API documentation: http://sirenix.net/odininspector/documentation/sirenix/odininspector/editor/odinmenuitem

     
    Alex_May likes this.
  33. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    It doesn't work like that I'm afraid. Property drawers are a bit more involved so they can't really be called like you call EditorGUILayout.TextField etc...

    But could you share a bit more about your problem, some code would be helpful. Why is it not serialized? Why doesn't it show up? How does the list member look etc.. And are you okay with it not being serialized? Have you tried combining the [OdinSerialize] together with the [NonSerialized] to force Odin to handle the serialization? Is the member serialized on a SerializedScriptableObject? If not, would [ShowInInspector] work for you perhaps if serialization doesn't matter?
     
  34. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Absolutely!

    Code (CSharp):
    1. PropertyTree tree;
    2. void SomeGUI()
    3. {
    4.     tree = tree ?? PropertyTree.Create(myObject);
    5.     tree.Draw(false);
    6. }
    Edit: What @PlutDem suggests works as well. Might even work better :)
     
    Last edited: Mar 17, 2018
    PlutDem likes this.
  35. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Thanks for reporting, and the vid. What version of Odin are you using? Sounds a bit like a bug we fixed in 1.0.6.0
    Just tried it in 1.0.6.1 and no issues there.
     
  36. Alex_May

    Alex_May

    Joined:
    Dec 29, 2013
    Posts:
    198
    That's great, thanks. In the end I have done this much more simply in the window class:

    Code (CSharp):
    1. public class BasicFormaEditor2 : OdinMenuEditorWindow
    2. {      
    3.     [MenuItem("Forma/Simple database editor 2")]
    4.     public static void OpenWindow()
    5.     {
    6.         var window = GetWindow<BasicFormaEditor2>();
    7.         window.titleContent = new GUIContent("Forma database editor 2");
    8.     }
    9.  
    10.     OdinMenuTree tree;
    11.     OdinMenuItem addNewForm;
    12.  
    13.     protected override OdinMenuTree BuildMenuTree()
    14.     {
    15.         tree = new OdinMenuTree(false);
    16.         tree.AddAllAssetsAtPath("", "Assets/Forma", typeof(Form), true, true);
    17.         foreach (OdinMenuItem m in tree.MenuItems)
    18.         {
    19.             Form f = m.ObjectInstance as Form;
    20.             if (f.realName == null || f.realName == "") f.realName = f.name;
    21.             m.Name = f.realName;
    22.         }
    23.         addNewForm = new OdinMenuItem(tree, "Add new", null);
    24.         tree.MenuItems.Add(addNewForm);
    25.         return tree;
    26.     }
    27.  
    28.     protected override void OnGUI()
    29.     {
    30.         if (Event.current.type == EventType.Repaint)
    31.         {
    32.             foreach (OdinMenuItem m in MenuTree.MenuItems)
    33.             {
    34.                 if (m.ObjectInstance is Form)
    35.                 {
    36.                     Form f = m.ObjectInstance as Form;
    37.                     m.Name = f.realName;
    38.                 }
    39.             }        
    40.         }
    41.         base.OnGUI();
    42.         if (tree.Selection.Contains(addNewForm))
    43.         {
    44.             Add();
    45.         }
    46.     }
    47.  
    48.  
    49.     void Add()
    50.     {
    51.         Form newForm = ScriptableObject.CreateInstance<Form>();
    52.         // count the number of form assets in the forma dir
    53.         int numForma = AssetDatabase.FindAssets("t:Form").ToList().Count;
    54.         AssetDatabase.CreateAsset(newForm, "Assets/Forma/Forma" + numForma + ".asset");
    55.         OdinMenuItem newItem = new OdinMenuItem(tree, "New Form", newForm);
    56.         tree.MenuItems.Insert(tree.MenuItems.Count - 1, newItem);
    57.         tree.Selection.Clear();
    58.         tree.Selection.Add(newItem);
    59.     }
    60. }
     
    bjarkeck likes this.
  37. Alex_May

    Alex_May

    Joined:
    Dec 29, 2013
    Posts:
    198
    I've decided I want to add a toolbar to the menu window, is that possible? Something I can put in OnGUI that shifts the rest of the GUI downwards?
     
  38. hungrybelome

    hungrybelome

    Joined:
    Dec 31, 2014
    Posts:
    336
    I am indeed using 1.0.6.0, with 2017.3.1p1, OSX. I'll try out 1.0.6.1 when it is released on the store!
     
    bjarkeck likes this.
  39. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Yeah, you can override BeginDrawEditors and inject stuff there. There is an example of this in the new sample project as well. And we've changed that slightly btw. From the 1.0.6.1 patch notes

     
    Alex_May likes this.
  40. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Hey the new dropdowns with integrated search, that's been at the top of my wishlist for I don't know how long. Thanks!
     
    bjarkeck likes this.
  41. blitzvb

    blitzvb

    Joined:
    Mar 20, 2015
    Posts:
    284
    Any plan to support ECS in the inspector ?
     
    bjarkeck and Cuku_ like this.
  42. EddieChristian

    EddieChristian

    Joined:
    Oct 9, 2012
    Posts:
    725
    Your FAQ mentions a dll that would allow us to use Odin on scripts we sell in the asset store. When is this coming out??
     
  43. vzlomvl

    vzlomvl

    Joined:
    Jun 25, 2016
    Posts:
    43
    Hello. I try to use EnumSelector like in sample. It's work fine, but changes of value not makes asset dirty. Do I need to use EditorUtility.SetDirty after ApplyChanges? I am using Odin1.0.6.1 and Unity 2017.4.0f1. Thanks.
     
  44. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Right forgot about that sorry. Will take a look and see if we can make code like that work out of the box. Problem is that changes need to be registered while actually drawing the tree, and the selection confirmed, is being invoked form a nother window. For a workaround try doing:

    Code (CSharp):
    1.  
    2.                 selector.SelectionConfirmed += x =>
    3.                 {
    4.                     entry.Property.Tree.DelayAction(() =>
    5.                     {
    6.                         entry.SmartValue = x.FirstOrDefault();
    7.                         entry.ApplyChanges();
    8.                     });
    9.                 };
     
  45. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Sadly, we don't have any official news on that yet, but we would love to hear which kind of model you think could work for both parties? You're more than welcome to join us on Discord, send a mail or PM me here, and then we can chat a bit about it.
     
  46. vzlomvl

    vzlomvl

    Joined:
    Jun 25, 2016
    Posts:
    43
    That helped. Thank you :)
     
  47. MrG

    MrG

    Joined:
    Oct 6, 2012
    Posts:
    363
    Discord? Where, please?
     
  48. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    851
    Is it possible to use another property to drive the min/max values for progress bars? like instead of [ProgressBar(0, 100)] it would be [ProgressBar(minHealth, maxHealth)]?
     
  49. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    thelebaron and MrG like this.
  50. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Sounds like a job for the CustomValueDrawer attribute :)


    Code (CSharp):
    1. public float minValue, maxValue;
    2.  
    3. [CustomValueDrawer("DrawProgressBar")]
    4. public float test;
    5.      
    6. private float DrawProgressBar(float value, GUIContent label)
    7. {
    8.     return (float)SirenixEditorFields.ProgressBarField(value, minValue, maxValue);
    9. }
     
    Ultroman and thelebaron like this.