Search Unity

  1. Get all the Unite Berlin 2018 news on the blog.
    Dismiss Notice
  2. Unity 2018.2 has arrived! Read about it here.
    Dismiss Notice
  3. Improve your Unity skills with a certified instructor in a private, interactive classroom. Learn more.
    Dismiss Notice
  4. ARCore is out of developer preview! Read about it here.
    Dismiss Notice
  5. Magic Leap’s Lumin SDK Technical Preview for Unity lets you get started creating content for Magic Leap One™. Find more information on our blog!
    Dismiss Notice
  6. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Assets [WIP] Odin Inspector & Serializer Looking for Feedback

Discussion in 'Works In Progress' started by jorisshh, Feb 22, 2017.

  1. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    165
    You can use OnInspectorGUI and property ordering to achieve this. Essentially, just put a method like this anywhere in your class, and it will draw an info box at the very top of your inspector.

    Code (CSharp):
    1. #if UNITY_EDITOR
    2.     [OnInspectorGUI, PropertyOrder(int.MinValue)]
    3.     private void DrawInfoBox()
    4.     {
    5.         Sirenix.Utilities.Editor.SirenixEditorGUI.InfoMessageBox("Message here");
    6.     }
    7. #endif
     
    zzzzzz789 likes this.
  2. SuneT

    SuneT

    Joined:
    Feb 29, 2016
    Posts:
    41
    A bit of news
    We've decided to turn our own forums at forum.devdog.io to "read-only" and instead switch to our own Discord server.

    The Discord server will allow for faster support and quicker messaging back and forth! ;)

    So if you're experiencing any issues, have feedback, or just want to show-off whatever you've made using any of our tools and hang out with us, come join: https://discord.gg/zjNj5zZ
     
  3. jorisshh

    jorisshh

    Joined:
    Oct 6, 2009
    Posts:
    1,509
    Great news, everyone!

    First of all, Odin is on sale in case you haven't noticed.
    We're going to increase the price after this sale, so Odin will never be cheaper than this (even during future sales).

    And also - Odin is a finalist in the Unity Awards, and we need YOUR help!
    You can go vote for Odin right here: https://awards.unity.com/
     
  4. MaddoScientisto

    MaddoScientisto

    Joined:
    Jan 30, 2015
    Posts:
    62
    Hello, first I got to say that I really like this addon, it quickly became one of my essential assets for any new project of mine.
    So I've been wondering if there's any way to do the following custom editor field with just an attribute:
    m_DefaultSprite = EditorGUILayout.ObjectField("Default Sprite", tile.m_DefaultSprite, typeof(Sprite), false) as Sprite;

    basically showing the sprite field rather than the generic one
     
  5. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    165
    That sounds like it would be something like this:

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3.  
    4. #if UNITY_EDITOR
    5. using Sirenix.OdinInspector.Editor;
    6. using UnityEditor;
    7. #endif
    8.  
    9. [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
    10. public class DrawSpriteFieldAttribute : Attribute { }
    11.  
    12. #if UNITY_EDITOR
    13. [OdinDrawer]
    14. public class SpriteDrawer : OdinAttributeDrawer<DrawSpriteFieldAttribute, Sprite>
    15. {
    16.     protected override void DrawPropertyLayout(IPropertyValueEntry<Sprite> entry, DrawSpriteFieldAttribute attribute, GUIContent label)
    17.     {
    18.         entry.SmartValue = EditorGUILayout.ObjectField("Default Sprite", entry.SmartValue, typeof(Sprite), false) as Sprite;
    19.     }
    20. }
    21. #endif
    And then you would just put [DrawSpriteField] on your member. It's a little odd that Odin isn't doing that correctly, though - it should. We'll have to look into that. Thanks for the heads up!
     
  6. MaddoScientisto

    MaddoScientisto

    Joined:
    Jan 30, 2015
    Posts:
    62
    Thank you that did the trick, on the plus side now I know how to make attributes for custom things!

    While I'm here another thing: is there a way to expand serialized scriptableobjects instead of editing them in a separate window?

    Also I noticed that all the elements in a BoxGroup are hidden (for instance with ShowIf) the box still shows, is there a way to hide it?
     
    Last edited: Oct 11, 2017
  7. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    165
    If you mean when you have a reference to them, and you want to draw the whole ScriptableObject instead of just the object field, you can use [InlineEditor] for that - draws inspectors for Unity object values inline in the inspector itself. Works on anything - Meshes, Materials, Components, ScriptableObjects, AudioClips, etc.
     
  8. MaddoScientisto

    MaddoScientisto

    Joined:
    Jan 30, 2015
    Posts:
    62
    Very nice! I love this asset more and more! I have more questions but I guess I'll get on the discord and ask there so I don't end up cluttering the thread too much
     
  9. Celtc

    Celtc

    Joined:
    Jan 19, 2014
    Posts:
    5
    Is there any way to serialize Stack<> and Queue<> classes? Thanks! Great asset!

    PD.: When using UnityEvents inside of non monobehaviour classes, I can't get them to be drawn properly (as Unity does).

    Here is my code:

    Code (CSharp):
    1. [SerializeField]
    2. [PropertyOrder(0)]
    3. [DrawWithUnity]
    4. [TabGroup("Events")]
    5. public UnityEvent_GameObject OnSpawn = new UnityEvent_GameObject();
    6.  
    7. [SerializeField]
    8. [PropertyOrder(1)]
    9. [TabGroup("Events")]
    10. public UnityEvent_GameObject OnRecycle = new UnityEvent_GameObject();
    And this is how it gets drawn:

     
    Last edited: Oct 13, 2017
  10. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    165
    This is a known issue, and is related to limitations how Unity draws UnityEvents. It's a hard one to fix, and it looks like we're essentially just going to have to make our very own UnityEvent drawer, which I'm afraid is a little bit in the future. For now, you'll have to make sure that your UnityEvents are serialized by Unity, and are in a Component. The next patch does have an improved error message that essentially states this, though.
     
  11. gbarnes

    gbarnes

    Joined:
    Mar 25, 2014
    Posts:
    3
    Hello,

    so far I'm lovin Odin. However I asked myself if it's possible to somehow group togther list elements visually. For Example we have a list of different objects. Objects could be weapons, armor or other stuff. Would it be possible to group elements by their "type" (I'm not speaking of the programming type but some abitrary we would like to specify).

    This would it make easier for designers to maintain a specific subset of the list.
     
  12. vudong

    vudong

    Joined:
    Feb 6, 2015
    Posts:
    38

    I lost data!
     
  13. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    206
    Not sure what you mean by you lost data, could you provide a little more information in regards to that?

    But thank you for posting that error message, it should be fixed now. If you will send us an email with your Odin Invoice Nr. (for verification) via our website www.sirenix.net I can send you the hotfix right away. Until then, you can go into Odin preferences and prevent the persistent cache from storing to disk.
     
    Last edited: Oct 17, 2017
  14. Meceka

    Meceka

    Joined:
    Dec 23, 2013
    Posts:
    295
    Hello,
    I am using Odin inspector only for attributes. So I disabled serialization as recommended in manual.
    However, although it's not mentioned in the manual I am adding a "using Sirenix.OdinInspector;" line in my scripts to make attributes work. And I don't know what assemblies I am adding into the build by doing that.
    In the FAQ section, there is this question:
    "Can I use Odin for its editors only, without using the serialization?"
    it claims that
    "The only Odin code that will be included, is the small Sirenix.OdinInspector.Attributes assembly"
    I tried using Sirenix.OdinInspector.Attributes but there isn't such a namespace
    Is my workflow correct by adding "using Sirenix.OdinInspector" to only add attributes to scripts?
    I also tried adding it like this, but the build fails because of attributes,
    #if UNITY_EDITOR
    using Sirenix.OdinInspector;
    #endif
     
  15. Celtc

    Celtc

    Joined:
    Jan 19, 2014
    Posts:
    5
    I'll really looking forward for your UnityEvent drawer. I think is quite a big deal, since lot of games are event driven. And being able to inspect them is invaluable for designers, and even programmers.
     
    Last edited: Oct 20, 2017
  16. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    165
    You should indeed just write "using Sirenix.OdinInspector;" - that includes the attributes, which are declared under that namespace, despite actually being in an assembly named Sirenix.OdinInspector.Attributes. We just thought having to type "using Sirenix.OdinInspector.Attributes;" was a little bit much, so we just declared it under a shorter namespace.
     
  17. Abuthar

    Abuthar

    Joined:
    Jul 12, 2014
    Posts:
    81
    Hey there, i need a little help. Trying to serialize a class with Odin. I keep getting this error:

    Code (CSharp):
    1. SerializationException: Type Sirenix.OdinInspector.SerializedMonoBehaviour in assembly Sirenix.Serialization, Version=1.0.5.1, Culture=neutral, PublicKeyToken=null is not marked as serializable.
    2. System.Runtime.Serialization.FormatterServices.GetSerializableMembers... etc
    my Scripts look like this (I'm using an empty project to figure this out before using in my real project).

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System.Runtime.Serialization.Formatters.Binary;
    5. using System.IO;
    6. using System;
    7. using Sirenix.Serialization;
    8. using Sirenix.OdinInspector;
    9.  
    10. public class DataManager : MonoBehaviour
    11. {
    12.     public LightData[] _lightData;
    13.  
    14.     public void SaveProjectData()
    15.     {
    16.  
    17.         BinaryFormatter bf = new BinaryFormatter();
    18.         FileStream file = File.Create((Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "/file01.dat"));
    19.         SaveIndex index = new SaveIndex();
    20.  
    21.         index.data = _lightData;
    22.  
    23.         bf.Serialize(file, index);
    24.         file.Close();
    25.         Debug.Log("Saved");
    26.     }
    27.  
    28.     public void LoadProjectData(int targetFile)
    29.     {
    30.         if (File.Exists((Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "file01.dat")))
    31.         {
    32.             BinaryFormatter bf = new BinaryFormatter();
    33.             FileStream file = File.Open((Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "file01.dat"), FileMode.Open);        
    34.             SaveIndex index = (SaveIndex)bf.Deserialize(file);
    35.  
    36.             for(int i = 0; i < index.data.Length; i++)
    37.             {
    38.                 _lightData[i].LoadData(index.data[i]);
    39.                 Debug.Log("Loading Data . . .");
    40.             }
    41.  
    42.             file.Close();
    43.  
    44.         }
    45.         else
    46.         {
    47.             Debug.Log("File is Null");
    48.         }
    49.     }
    50. }
    51.  
    52. [System.Serializable]
    53. public class SaveIndex
    54. {
    55.     public LightData[] data;
    56. }
    57.  
    The serialized file looks like this:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System.Runtime.Serialization.Formatters.Binary;
    5. using System.IO;
    6. using System;
    7. using Sirenix.Serialization;
    8. using Sirenix.OdinInspector;
    9.  
    10. [System.Serializable]
    11. public class LightData : SerializedMonoBehaviour
    12. {
    13.     [OdinSerialize]
    14.     public float lightIntensity;
    15.     [OdinSerialize]
    16.     public float lightX;
    17.     [OdinSerialize]
    18.     public float lightY;
    19.     [OdinSerialize]
    20.     public float lightZ;
    21.  
    22.     public void LoadData(LightData reader)
    23.     {
    24.         lightIntensity = reader.lightIntensity;
    25.         lightX = reader.lightX;
    26.         lightY = reader.lightY;
    27.         lightZ = reader.lightZ;
    28.     }
    29.  
    30. }
    31.  
    can anyone tell me what i'm doing wrong??
     
  18. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    165
    I'm afraid there's a few misunderstandings going on in that code!

    Let's take them one at a time:
    1. Using BinaryFormatter doesn't invoke Odin's serialization. Your code isn't actually calling into Odin's serialization anywhere. BinaryFormatter is a built-in class that comes with the runtime that the scripting part of Unity is built on, and doesn't actually have anything to do with how either Odin or Unity do serialization. You can read more about how to actually invoke Odin's serialization here - the link includes an example of how to do essentially what you're trying, only with Odin instead.

    2. You cannot serialize any instance of a type that inherits from UnityEngine.Object to a file, due to how Unity works. Odin's SerializedMonoBehaviour inherits from UnityEngine.MonoBehaviour, which is a component that you put on a GameObject. UnityEngine.MonoBehaviour derives from UnityEngine.Object. So you cannot make any class that you want to serialize to a file inherit from SerializedMonoBehaviour. The SerializationException you're getting, in fact, is exactly because the class is not meant to be used in that way.

      A SerializedMonoBehaviour cannot be serialized from the "outside". How you're supposed to use it, is that you put it on a GameObject as a component, and that component can now be used as any other regular Unity component, except it magically has extra serialization capabilities built in, so it can save and show things that a regular Unity component could not. These serialization capabilities are invoked from deep within Unity's own serialization system, which also has nothing to do with BinaryFormatter.

      In short, SerializedMonoBehaviour is a convenience class for using Odin's serialization in your Unity components in an inspector-friendly way.

    3. You don't actually need Odin to do what you're trying, there. In fact, that code should work perfectly, if you just change "public class LightData : SerializedMonoBehaviour" to "public class LightData" and remove the [OdinSerialize] attributes. The BinaryFormatter class will take your LightData and save/load it just fine on its own, without any involvement from Odin at all.

      If you do want to use Odin to do the serialization instead, see the FAQ link in point 1 for some example code.
    I hope that helps explain the issues you're getting! And of course, if you have any more questions, feel free to ask :)
     
  19. brisingre

    brisingre

    Joined:
    Nov 8, 2009
    Posts:
    317
    A few quick questions:

    1. Can I make a boolean that looks like a button instead of a check box?
    2. Can I inspect a static variable?
    3. Can I make a range that doesn't enforce it's min and max on associated number entry field? That is, the slider goes from, say, 0 to 1, but if you put 2 in the text field it won't change it to 1 unless you mess with the slider.
    And just for fun, a before and after on the first thing I've Odin-ized

    Before:
    upload_2017-11-10_16-12-39.png

    After:
    upload_2017-11-10_16-13-0.png
     
    Last edited: Nov 11, 2017
  20. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    165
    1. Can I make a boolean that looks like a button instead of a check box?

    You can! You just need to create an attribute and a drawer for it:

    Code (CSharp):
    1. // Declare an attribute to use
    2. [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
    3. public class ButtonBoolAttribute : Attribute
    4. {
    5. }
    6.  
    7. // In an editor script somewhere, declare the drawer
    8. [OdinDrawer]
    9. public class ButtonBoolAttributeDrawer : OdinAttributeDrawer<ButtonBoolAttribute, bool>
    10. {
    11.     protected override void DrawPropertyLayout(IPropertyValueEntry<bool> entry, ButtonBoolAttribute attribute, GUIContent label)
    12.     {
    13.         bool value = entry.SmartValue; // Value in the first selected object
    14.         GUIStyle style = value ? SirenixGUIStyles.ButtonSelected : SirenixGUIStyles.Button;
    15.  
    16.         if (GUILayout.Button(label, style))
    17.         {
    18.             entry.SmartValue = !value;
    19.         }
    20.     }
    21. }
    2. Can I inspect a static variable?

    Currently, not directly. In Odin 1.1, we will add this ability. Meanwhile, what you can do is, essentially, make an instance property that references the static variable:

    Code (CSharp):
    1. private string MyStaticVariable { get { return myStaticVariable; } set { myStaticVariable = value; } }
    3. Can I make a range that doesn't enforce it's min and max on associated number entry field? That is, the slider goes from, say, 0 to 1, but if you put 2 in the text field it won't change it to 1 unless you mess with the slider.

    Yes, you can make your own range attribute with a drawer that is unconstrained:

    Code (CSharp):
    1. // Declare an attribute to use
    2. [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
    3. public sealed class UnconstrainedRangeAttribute : Attribute
    4. {
    5.     public readonly float Min;
    6.     public readonly float Max;
    7.  
    8.     public UnconstrainedRangeAttribute(float min, float max)
    9.     {
    10.         this.Min = min;
    11.         this.Max = max;
    12.     }
    13. }
    14.  
    15. // In an editor script somewhere, declare the drawer
    16. [OdinDrawer]
    17. public sealed class UnconstrainedRangeAttributeFloatDrawer : OdinAttributeDrawer<UnconstrainedRangeAttribute, float>
    18. {
    19.     /// <summary>
    20.     /// Draws the property.
    21.     /// </summary>
    22.     protected override void DrawPropertyLayout(IPropertyValueEntry<float> entry, UnconstrainedRangeAttribute attribute, GUIContent label)
    23.     {
    24.         entry.SmartValue = label == null ?
    25.             EditorGUILayout.Slider(entry.SmartValue, attribute.Min, attribute.Max) :
    26.             EditorGUILayout.Slider(label, entry.SmartValue, attribute.Min, attribute.Max);
    27.     }
    28. }
     
    brisingre likes this.
  21. brisingre

    brisingre

    Joined:
    Nov 8, 2009
    Posts:
    317
    Thanks for the quick response!

    ButtonBool and the workaround for statics worked perfectly.

    UnconstrainedFloat is giving me problems. The value clamps to max even if I type a larger number in the text field. I made some changes and got something that technically has the functionality I'm looking for, but it's super awkward to use.

    Code (CSharp):
    1. // Declare an attribute to use
    2. [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
    3. public sealed class UnconstrainedRangeAttribute : Attribute
    4. {
    5.     public readonly float Min;
    6.     public readonly float Max;
    7.  
    8.     public UnconstrainedRangeAttribute(float min, float max)
    9.     {
    10.         this.Min = min;
    11.         this.Max = max;
    12.     }
    13. }
    14.  
    15. // In an editor script somewhere, declare the drawer
    16. [OdinDrawer]
    17. public sealed class UnconstrainedRangeAttributeFloatDrawer : OdinAttributeDrawer<UnconstrainedRangeAttribute, float>
    18. {
    19.     /// <summary>
    20.     /// Draws the property.
    21.     /// </summary>
    22.     protected override void DrawPropertyLayout(IPropertyValueEntry<float> entry, UnconstrainedRangeAttribute attribute, GUIContent label)
    23.     {
    24.         if(entry.SmartValue < attribute.Max)
    25.         {
    26.             entry.SmartValue = label == null ?
    27.                 EditorGUILayout.Slider(entry.SmartValue, attribute.Min, attribute.Max) :
    28.                 EditorGUILayout.Slider(label, entry.SmartValue, attribute.Min, attribute.Max);
    29.  
    30.         }
    31.         else
    32.         {
    33.  
    34.             entry.SmartValue = label == null ?
    35.                 EditorGUILayout.FloatField(entry.SmartValue) :
    36.                 EditorGUILayout.FloatField(label, entry.SmartValue);
    37.         }
    38.     }
    39. }
    40.  
     
  22. brisingre

    brisingre

    Joined:
    Nov 8, 2009
    Posts:
    317
    Odin seems to be stopping me from building for OSX.
    upload_2017-11-25_15-39-14.png
     
  23. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    165
    It looks like you've enabled Odin's Editor Only Mode. When you do so, then, as noted in the description above the button you activate it with, you should delete Odin's demo scripts since they reference code that will no longer be available in builds.
     
  24. brisingre

    brisingre

    Joined:
    Nov 8, 2009
    Posts:
    317
    Thank you!
     
  25. AnAppGames

    AnAppGames

    Joined:
    Jan 3, 2017
    Posts:
    133
    Does anyone know how to make a dropdown with Tags using Odin inspector?
     
  26. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    165
    There is no built-in way of doing that in Odin, currently, but you can easily make your own attribute drawer for strings with that behaviour. See our manual for creating custom drawers, and also see the demo scene "2 - Custom Drawers Example" that comes with Odin, to learn how to create custom drawers.
     
  27. cooloon

    cooloon

    Joined:
    Nov 25, 2014
    Posts:
    2
    Hello,

    Thanks for the great inspector and serialization asset. Specially serialization works great!

    Now, is it possible to download SerializedScriptableObject in AssetBundle dynamically and deserialize it with IL2CPP?
     
  28. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    165
    It should work exactly as a regular ScriptableObject does - you just need to make sure there's AOT support enabled for the types serialized in the SerializedScriptableObject asset you're loading dynamically.
     
  29. cooloon

    cooloon

    Joined:
    Nov 25, 2014
    Posts:
    2
    Sounds like a magic!

    In that case, to serialize dynamically downloaded SerializedScriptableObject from Binary format, I need to configure the "Editor Serialization Format" settings to "Binary", right?
     
  30. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    165
    That shouldn't be necessary - leaving just the build format as binary should be good enough.
     
  31. jura_wd

    jura_wd

    Joined:
    Jan 28, 2014
    Posts:
    28
    Hey guys! Thanks for your great asset.. But I have a problem with it:

    ```
    System.TypeInitializationException: An exception was thrown by the type initializer for Sirenix.OdinInspector.Editor.DrawerLocator ---> System.ArgumentException: An element with the same key already exists in the dictionary.
    at System.Collections.Generic.Dictionary`2[System.Type,Sirenix.OdinInspector.Editor.DrawerPriority].Add (System.Type key, DrawerPriority value) [0x0007e] in /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:404
    at Sirenix.OdinInspector.Editor.DrawerLocator..cctor () [0x00031] in C:\Sirenix\Sirenix Solution\Sirenix.OdinInspector.Editor\Core\Children\GroupPropertyChildren.cs:30
    --- End of inner exception stack trace ---
    at (wrapper managed-to-native) System.Runtime.CompilerServices.RuntimeHelpers:RunClassConstructor (intptr)
    at System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor (RuntimeTypeHandle type) [0x00026] in /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.CompilerServices/RuntimeHelpers.cs:101
    at UnityEditor.EditorAssemblies.ProcessEditorInitializeOnLoad (System.Type type) [0x00008] in C:\buildslave\unity\build\Editor\Mono\EditorAssemblies.cs:136
    UnityEditor.EditorAssemblies:processInitializeOnLoadAttributes()
    ```

    I have my own InitializeOnLoad static constructors stuff that somehow interfere with Odin. But I don't see any problem. Did you faced this before? (if I use Odin from sources - everything works as expected)
     
  32. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    1,514
    I'm using PropertyTree.Create to give odin the object to use and then Draw, which works fine. But when I added some TabGroup attributes I started seeing this error message, although it appears to still work.

    Code (csharp):
    1.  
    2. Exception: Tabs must be registered in Layout first.
    3. Sirenix.Utilities.Editor.GUITabGroup.RegisterTab (System.String title) (at C:/Sirenix/Sirenix Solution/Sirenix.Utilities.Editor/GUI/GUITabGroup.cs:162)
    4.  
     
  33. artaka

    artaka

    Joined:
    Feb 19, 2013
    Posts:
    116
    I've been using Odin for a few months now and it's simply awesome!

    I did come across an issue though that I hope to resolve. I'm using Odin with a relatively complex object that has hierarchies of lists and other object references. Odin does a wonderful job of organizing the inspector and making it look much more user friendly. Unfortunately, it's so slow that it's practically unusable. Is there a resource of tips or trick I can refer to for optimizing its performance?
     
  34. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    165
    What you describe should work, but the error message implies that perhaps you are creating a new PropertyTree every frame and drawing that, rather than retaining a single PropertyTree and then drawing that repeatedly. If that isn't the case, can you perhaps post some example code that replicates your issue?

    We are currently working on a feature that will optimize this, so that Odin evaluates data lazily, and thus only spends effort "inspecting" the things that are actually drawn. Currently, if Odin is inspecting an array with 1000 elements in it, but list paging means that it only draws 20 of those elements are drawn, the data in every single one of those 1000 elements is actually fetched and processed, and this is why you see a lot of lag in inspectors with a lot of data.

    This feature will ship in Odin patch 1.1, along with a major rebuild of the property system that facilitated this and many other upgrades. When exactly this patch will be released is quite uncertain. We are currently at the point where we have a working experimental version of the property rebuild with lazy evaluation built in, but it is not ready for release yet, and still needs a lot of work and some very thorough testing. There will likely be a long beta period for this feature - so if you're interested in testing it, keep an eye out for that!
     
    Last edited: Jan 10, 2018
  35. artaka

    artaka

    Joined:
    Feb 19, 2013
    Posts:
    116
    Thanks for the rapid response! Looking forward to the 1.1 patch...
     
  36. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    368
    Is there a way to make an infobox that doesn't show without exposing the modifiable string to the inspector?

    In the examples the infoboxes are only on public member variables so there's always the infobox + the member variable. I'd like to just have the infobox. Is that possible?

    upload_2018-1-12_14-32-41.png


    Code (CSharp):
    1.     [Title("Info")]
    2.     [InfoBox("$InfoBoxMessage")]
    3.     public string InfoBoxMessage; // if private, it shows nothing
     
  37. Zionmoose

    Zionmoose

    Joined:
    Oct 17, 2012
    Posts:
    237
    Out of curiosity, does the HideInInspector attribute work for you? Not sure if it just hides the property or also the info box.
     
  38. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    206
    HideInInspector hides the entire property, including the InfoBox, but you could do something like this:

    Code (CSharp):
    1. [OnInspectorGUI, PropertyOrder(x), InfoBox("x")]
    2. private void DrawInfoBox() { }
    or

    Code (CSharp):
    1. [OnInspectorGUI, PropertyOrder(x)]
    2. private void DrawInfoBox()
    3. {
    4.      // Draw it manually using EditorGUILayout or SirenixEditorGUI.
    5. }
     
    FeastSC2 likes this.
  39. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    368
    That did the trick, thanks!
     
    bjarkeck likes this.
  40. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    368
    I have a list of a class of Serializable class objects. These objects have sliders and colors.

    https://i.imgur.com/2R2Pgjq.gifv

    Undo (Ctrl+Z) doesn't revert the slider's position to when the slider first started moving (nothing gets written to the Undo stack). But when choosing a color undo reverts to the original color.
    Is this a bug and/or can I do something about it?

    I see that sliders that don't come from Odin (vanilla Unity) actually register undos but it gets registered throughout the movement of the slider, meaning it generates a lot of Undo's when moving the slider.


    On another note: Can I display a ScriptableObject's inspector in a normal MonoBehaviour script?
     
    Last edited: Jan 13, 2018
  41. somosky

    somosky

    Joined:
    Feb 15, 2014
    Posts:
    81
    Hi I had a quick question about Arrays. By default in Unity when a array is created you get the # next to each element in the array. For example if you have a array with 5 gameobjects you will see element #1 , #2 etc. With Odin you no longer get a visual representation of what number a object is in an array. I have quite a large array and it would be very helpful to be able to number them so I can quickly debug instead of having to count them. Is that possible?
     
  42. jorisshh

    jorisshh

    Joined:
    Oct 6, 2009
    Posts:
    1,509
    Odin v. 1.0.6 is now live - go update if you haven't already. There are some real treats in there ;)

    In fact, here's a quick overview of just a few of the improvements available in the latest update:


    You can find the full patch notes right here - I really encourage you to especially try playing around with the new fancy Odin Editor Windows!

    What do you think about the latest update? Be sure to let us know here or even better; on our Discord server.
     
    FeastSC2 likes this.
  43. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    368
    It's really great to be able to use Custom Editor with OdinEditor now, really great addition with v1.0.6 good job.

    Does someone know how can I add methods to this menu?
    upload_2018-2-7_22-12-20.png
     
  44. Shnayzr

    Shnayzr

    Joined:
    Aug 31, 2014
    Posts:
    16
    BUG: List<List<CUSTOMOBJECT>> gets cleared after starting the game but Dictionary<XXX,List<List<CUSTOMOBJECT>>> doesnt get cleared.

    Anyone knows how to fix?
     
    Last edited: Feb 10, 2018
    bjarkeck likes this.
  45. ledbetterman

    ledbetterman

    Joined:
    May 5, 2015
    Posts:
    53
    Is it possible to represent tab groups within a foldout group? I know you can have foldout groups within tab groups. I tried mimicking the same declaration as foldouts-within-tabs, except the other way around, and it didn't work.
     
  46. hungrybelome

    hungrybelome

    Joined:
    Dec 31, 2014
    Posts:
    111
    Is it possible to use the ShowIf attribute with multiple enum values? E.g.
    Code (CSharp):
    1. [ShowIf(nameof(Level.GameLevelType), GameLevelType.Normal), ShowIf(nameof(Level.GameLevelType), GameLevelType.Boss)]
    Multiple HideIf attributes seem to work correctly.
     
  47. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    206
    Yup, you can do [CustomContextMenu] attribute.
     
    FeastSC2 likes this.
  48. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    206
    This is a bug, that should be fixed in 1.0.6.0

     
  49. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    206
    Yup so instead of:
    Code (CSharp):
    1. [TabGroup("MyTabGroup", "MyTab")]
    2. member
    3.  
    4. [FoldoutGroup("MyTabGroup/MyTab/My Foldout Group")]
    5. member
    You just do:

    Code (CSharp):
    1. [TabGroup("MyTabGroup/MyTabGroup", "MyTab")]
    2. member
    3.  
    4. [FoldoutGroup("My Foldout Group")]
    5. member
     
    ledbetterman likes this.
  50. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    206
    Not really, the way it works right now is, that if anyone those ShowIf returns false. It will be hidden.

    But instead of referencing an enum, you could just reference a property that combines the logic for you.

    Code (CSharp):
    1. [ShowIf(nameof(ShowMember))]
    2. someField
    3.  
    4. bool ShowMember { get { return someField == GameLevelType.Normal || someField == GameLevelType.Etc.. } }
     
    ledbetterman and hungrybelome like this.