Search Unity

  1. Going to #UniteBerlin? Bring a buddy & get 25% off the 2nd ticket! More info here.
    Dismiss Notice
  2. Famed game designer and creator of The Sims, SimCIty, and Spore is looking for a 3D artist to join their team. Join the challenge.
    Dismiss Notice
  3. Unity 2017.4 has arrived! Read about it here.
    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. We've opened a new World Building sub-forum to faciltate all your world building discussions! Drop in and ask any ProBuilder, ProGrids, or PolyBrush questions.
    Dismiss Notice
  7. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

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

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

  1. dantonel

    dantonel

    Joined:
    Dec 7, 2015
    Posts:
    4
    Sweet. Thanks!
     
  2. fidelsoto

    fidelsoto

    Joined:
    Aug 7, 2012
    Posts:
    51
    Hello, I'm new to Odin, loving it so far!
    Question:

    I have this:
    InfoSequence.png

    using System;
    using System.Collections.Generic;
    using UnityEngine;
    using Sirenix.OdinInspector;

    namespace OkusInfo
    {
    public enum PetTransition
    {
    FadeIn,
    FadeOut,
    Minimize,
    Maximize
    }

    public class InfoSequence : SerializedMonoBehaviour
    {
    [HideReferenceObjectPicker]
    public List<Info> sequence;
    }

    public class Info
    {
    [PropertyOrder(2)]
    public bool pause;
    }

    public class Dialogue : Info
    {
    [TextArea]
    public string dialogue;
    }

    public class AnimationStep : Info
    {
    public Animator animator;
    }

    public class PetAction : Info
    {
    public PetTransition action;
    }
    }


    I want this:
    InfoSequenceWhatIWant.png

    I want add buttons on every element of the list. They should add a new instance of the class (should let me pick the class type) directly below the element I clicked. Also the add button on top should add a new element at the very top of the list instead of at the bottom.

    Is this possible?

    Also, can I hide the base class from the add new class instance class type picker?

    Edit:
    I know editor scripting. So I guess my question is: How do I combine editor scripting with Odin's serialization behavior for polymorphic lists?
     
    Last edited: Mar 24, 2018
  3. dantonel

    dantonel

    Joined:
    Dec 7, 2015
    Posts:
    4
    Is there an easy way to customize what happen when the "delete" button is clicked on a List item? There doesn't seem to be a straightforward way like there is for the CustomAddFunction.

    ( edit: )
    I could also see using OnEndListElementGUI in the ListDrawerSettingsAttribute, but I would still need to get rid of the existing "x" button, right?
     
    Last edited: Mar 23, 2018
  4. zornor90

    zornor90

    Joined:
    Sep 16, 2015
    Posts:
    43
    Hey just purchased your asset, I've been able to remove a lot of my custom code I wrote for dealing with lists of scriptable objects! I'm really liking the list, but I have a question - say I have a ScriptableObject that has a list of other ScriptableObjects (a PickupDatabase with a list of pickups). I need a way to add a new ScriptableObject when clicking the plus button, is there a way to override the default behavior so that it calls my own function instead - to open up an add new window?
    upload_2018-3-24_15-39-16.png

    Thanks so much!
     
    bjarkeck likes this.
  5. fidelsoto

    fidelsoto

    Joined:
    Aug 7, 2012
    Posts:
    51
    I believe this case is covered in the documentation here:
    http://sirenix.net/odininspector/documentation/sirenix/odininspector/listdrawersettingsattribute
     
    bjarkeck likes this.
  6. fidelsoto

    fidelsoto

    Joined:
    Aug 7, 2012
    Posts:
    51
    I think I found my answer here:
    Next time I buy an asset I will read the documentation AND the forum before asking a question.

    Looks like its in the FAQ as well:
    http://www.sirenix.net/odininspector/faq/13/can-i-use-odin-inspector-to-create-custom-editor-windows

    Edit:
    I did exactly whats in the FAQ (see code below) for my polymorphic list and the editor slows down to a crawl when I inspect the object.

    Code (csharp):
    1.  
    2. [CustomEditor(typeof(MyMonoBehaviour))]
    3. public class CustomOdinEditor : OdinEditor
    4. {
    5.    public override void OnInspectorGUI()
    6.    {
    7.        var tree = this.Tree;                                      // Like this.serializedObject.
    8.        var obj = this.target as MyMonoBehaviour;
    9.  
    10.        InspectorUtilities.BeginDrawPropertyTree(tree, true);      // This and EndDrawPropertyTree automatically handles a lot of stuff like prefab instance modifications and undo
    11.  
    12.        var someProp1 = tree.GetPropertyAtPath("someProp1");   // Like serializedObject.FindProperty("path")
    13.        someProp1.Draw();                                      // Like EditorGUILayout.PropertyField(property);
    14.  
    15.        InspectorUtilities.EndDrawPropertyTree(tree);
    16.  
    17.        // You can also call base.OnInspectorGUI(); instead if you simply want to prepend or append GUI to the editor.
    18.    }
    19. }
    20.  
     
    Last edited: Mar 26, 2018
  7. SorenCoder

    SorenCoder

    Joined:
    Mar 27, 2017
    Posts:
    16
    Really great asset!
    I have two questions though, First, is it possible to automatically serialize all auto-properties in classes without placing OdinSerialize attribute on each one of properties?
    Second, Is it possible to use Odin serialization to serialize and deserialize entire scene in runtime?
     
    bjarkeck likes this.
  8. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    166
    It's possible to add your own custom serialization policies using the ISerializationPolicy, but we don't have any guide on doing that, so you would need to dig through the code, starting at SerializedMonoBehaviour and see how it could be achieved.

    However, I would advise against serializing properties, for a number of reasons:

    You can only safely serialize auto-properties, as full property implementations don't guarantee that there is a backing field to serialize. And full property implementations can't be called directly as they can easily execute code that is not allowed are meant to be called during serialization and deserialization. Virtual properties, (this includes all properties declared by interfaces), might be an auto-property in one class. But nothing is to say, that another class can't override that implementation, and ruin the serialization. Should you ever convert an auto-property to a full property implementation, you would have to use the [FormalySerializedAs] on the backing field etc, which one might forget resulting in loss of data.

    Having a full property implementation with a serialized backing field is much more robust, and more clear in terms of data. And it also allows you to rename the property without worrying about a thing :)

    You can use Odin's serialization during runtime to both serialize and deserialize custom data. But you can't serialize any Unity objects down directly as assets during runtime out of the box. That requires Unity to serialize it, which is only possible in the editor. Only Unity can serialize Unity objects. In fact, whenever Odin encounter a UnityObject, it gets stored in a separate list, which we then let Unity handle for us.
     
    SorenCoder likes this.
  9. fidelsoto

    fidelsoto

    Joined:
    Aug 7, 2012
    Posts:
    51
    So why is this so slow?

    Code (csharp):
    1.  
    2. using UnityEditor;
    3. using Sirenix.OdinInspector.Editor;
    4.  
    5. [CustomEditor(typeof(DerivedList))]
    6. public class CustomOdinEditor : OdinEditor
    7. {
    8.     public override void OnInspectorGUI()
    9.     {
    10.         var tree = this.Tree;                                      // Like this.serializedObject.
    11.         var obj = this.target as DerivedList;
    12.  
    13.         InspectorUtilities.BeginDrawPropertyTree(tree, true);      // This and EndDrawPropertyTree automatically handles a lot of stuff like prefab instance modifications and undo
    14.  
    15.         var someProp1 = tree.GetPropertyAtPath("instance");   // Like serializedObject.FindProperty("path")
    16.         someProp1.Draw();                                      // Like EditorGUILayout.PropertyField(property);
    17.  
    18.         InspectorUtilities.EndDrawPropertyTree(tree);
    19.  
    20.         // You can also call base.OnInspectorGUI(); instead if you simply want to prepend or append GUI to the editor.
    21.     }
    22. }
    Code (csharp):
    1.  
    2. using Sirenix.OdinInspector;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class DerivedList : SerializedMonoBehaviour {
    7.  
    8.     [HideReferenceObjectPicker]
    9.     [ListDrawerSettings(ShowPaging = false)]
    10.     public List<BaseClass> instance;
    11. }
    12.  
    13. public class BaseClass
    14. {
    15.     [PropertyOrder(2)]
    16.     public bool booleanVariable;
    17. }
    18.  
    19. public class DerivedClass1 : BaseClass
    20. {
    21.     public float floatValue;
    22. }
    23.  
    24. public class DerivedClass2 : BaseClass
    25. {
    26.     public string stringValue;
    27. }
    28.  
    29. public class DerivedClass3 : BaseClass
    30. {
    31.     public Animator animatorReference;
    32. }
    33.  
    Edit: Actually seems like whats broken is collapsing the list (animated) only. It goes slow and stops midway.
    Also the vertical top position a bit off.
    derivedlist.png
    Adding EditorGUILayout.Space(); on top fixed this, but I'm still wondering why the folding is so slow. I set the foldout animation time to 0.001 for now.
     
    Last edited: Mar 26, 2018
  10. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    166
    You could also create a custom drawer for that. Here is something to get you started :)

    Code (CSharp):
    1.  
    2. [OdinDrawer]
    3. [DrawerPriority(DrawerPriorityLevel.WrapperPriority)]
    4. public class ListElementDrawer<T> : OdinValueDrawer<T>
    5.     where T : Info
    6. {
    7.     protected override void DrawPropertyLayout(IPropertyValueEntry<T> entry, GUIContent label)
    8.     {
    9.         if (entry.ValueCategory == PropertyValueCategory.StrongListElement)
    10.         {
    11.             var objectPicker = ObjectPicker<Info>.GetObjectPicker(entry);
    12.             if (GUILayout.Button("+"))
    13.             {
    14.                 objectPicker.ShowObjectPicker(false, entry.Property.LastDrawnValueRect, false);
    15.             }
    16.             if (objectPicker.IsReadyToClaim)
    17.             {
    18.                 var value = objectPicker.ClaimObject();
    19.                 object[] values = new object[entry.ValueCount];
    20.                 values[0] = value;
    21.                 for (int j = 1; j < values.Length; j++)
    22.                 {
    23.                     values[j] = SerializationUtility.CreateCopy(value);
    24.                 }
    25.                 var listChanger = entry.Property.FindParent(PropertyValueCategory.Member, false)
    26.                     .ValueEntry.GetListValueEntryChanger();
    27.                 listChanger.InsertListElementAt(entry.Property.Index, values, "List element inserted");
    28.             }
    29.             this.CallNextDrawer(entry, label);
    30.         }
    31.         else
    32.         {
    33.             this.CallNextDrawer(entry, label);
    34.         }
    35.     }
    36. }
    37.  
     
    fidelsoto likes this.
  11. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    166
    It seems slow because it's not repainting. Just add this.RepaintIfRequested(); at the bottom of the OnInspectorGUI
     
    fidelsoto likes this.
  12. DMeville

    DMeville

    Joined:
    May 5, 2013
    Posts:
    360
    Are there any tips for performance anywhere?

    I'm new to Odin, and really only want to use it to be able to show dictionaries in the inspector for now. The nicer lists are an added bonus, but I can deal with the default drawing of them. The performance I'm getting isn't great though.

    I created a simple test to try and narrow down if it was a specific type of collection that was causing issues. I have one SerializedMonoBehaviour with an int[4096]. When clicking the object to view it in the inspector while the game is running framerate drops from 60fps to 20fps.

    Any tips?

    Edit: Further testing shows that the default unity drawer slows down a ton in the same situation. Guess I can just be more careful of what I'm showing in the inspector, and just hide lists unless I really need to see them.

    Surprisingly, marking my int[4096] array with [HideInPlayMode] removes it from the inspector in play mode, but doesn't change the framerate. Using the built-in [HideInInspector] does, but means I can't edit the values during edit time without editing the script file >.<
     
    Last edited: Mar 26, 2018
  13. arlevi09

    arlevi09

    Joined:
    Dec 31, 2014
    Posts:
    89
    Just wanted to mention that this is no longer an issue for me with 1.0.6.1!
     
    bjarkeck likes this.
  14. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    166
    Performance issues will be adressed in our next major patch 1.1 which we'll start beta testing of very soon! From our patch-notes: http://sirenix.net/odininspector/releasenotes/1-0-6-1

    The best thing you can do until then, is to disable Odin for those types that contain a lot of data.
     
    DMeville likes this.
  15. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,007
    Is there an ETA on 1.1 :) ?
     
  16. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    166
    Soon :p

    Send us an email from sirenix.net/contact with your Odin invoice Id if you want in on an early beta :)
     
    BTStone likes this.
  17. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    121
    EDIT: Silly me, Unity 5.6+ has uint serialization support. So my main issue is a non-issue really.

    But do let me know if Odin can now be used in more modular fashion, loved its inspector upgrade :)

    ----

    Hi All,

    I bought Odin a long time ago and was planning to use it, but then went for some lighter and modular solutions (like a custom serializable dictionary, or a custom reorderable list, etc., instead of depending on a custom monobehaviour).

    Now I am facing another data structure I want to serialize, specifically, uint, which I will use as List<uint> and SerializableDictionary<uint, T>.

    I realize my previous approach isn't very sustainable, as I am just reinventing the wheel here by creating serializable class and custom inspector Odin has already done.

    So I am thinking of switching back to Odin, but I would like to do it in a modular way if it's possible.

    I wonder if I can use Odin's uint32serializer in a low impact way? Like, allow me to declare a custom serializable uint type and define a custom inspector (see the custom dictionary mentioned above).

    I know Odin's binary serialization is wired quite deeply so I am not sure what I can do...
     
    Last edited: Mar 30, 2018
    bjarkeck likes this.
  18. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    166
    Good to hear you found a solution :) If not, Odin would definitely also have alternative options for you. You can easily use Odin Inspector for only the inspector upgrades btw. Odin's inspector upgrades doesn't require you to inherit from any specialized MonoBehaviour. They just work out of the box.

    231befc2-0b39-4e8a-a955-2abd934e55bf_scaled.jpg
     
  19. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,109
    @bjarkeck Do you know if there is a way to use SirenixEditorFields to show UnityEvents and UnityActions?
     
  20. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    166
    Afraid not. As far as I'm aware the only way of drawing it is through Unity's SerializedObject and SerializedProperties.
     
  21. jay-jin

    jay-jin

    Joined:
    Jun 22, 2014
    Posts:
    12
    Hi, I have an idea that I wish to be adopted. I hope to be able to make my own timeline in editorWindows. But my attempt is not ideal, perhaps you can give some advice or provide a timeline in editorWindows?
     
  22. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    150
    Hello, I have a custom drawer that I'm wanting to use [UseInlineEditor] on.

    Basically, I have a value inside the property that I want to draw an inline editor for :)

    Is this possible?
     
  23. Shadowing

    Shadowing

    Joined:
    Jan 29, 2015
    Posts:
    663
    Trying to figure out how to do something can someone type me out a example. My csharp is so so. so the documentation is confusing a bit for me :(

    Code (csharp):
    1.  
    2.     [ValueDropdown("IdleAnimationType")]
    3.     public int m_IdleAnimationType;
    4.  
    5.     private ValueDropdownList<int> IdleAnimationType = new ValueDropdownList<int>(){
    6.         {"Default",0},
    7.         {"Human",5},
    8.         {"Raptor",3},
    9.     };
    10.  

    Lets say Human is selected in the inspector.
    How can I return Human as a string. I can get the int value just by reading the variable m_IdleanimationType.
    Keep in mind int values can be the same.
     
    Last edited: Apr 2, 2018
  24. Froghuto

    Froghuto

    Joined:
    Oct 4, 2012
    Posts:
    41
    Is it possible to get a [ValueDropdown] on the key of a dictionary somehow?
     
  25. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    166
    Froghuto likes this.
  26. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    166
    Not entirely sure I got your question right but is this what you're looking for?

    Code (CSharp):
    1. string name = IdleAnimationType[m_IdleAnimationType].Text
     
  27. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    166
    Sounds like something that is possible :) If you could share the code then it'll be easier for me to help you figure out how. (drawer + the class containing the field you want the inline editor for)
     
    joshcamas likes this.
  28. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    150
    Alright, so I have a class called "ScriptableObjectParameter". It has a variable called "value", which is a scriptable object.

    I want to be able to put an attribute onto the class, but apply it to a value in the class itself... sounds confusing, I know. :/

    So:

    [UseInlineEditor]
    public ScriptableObjectParameter param;

    Would make a specific variable inside the class have inline editor enabled.

    Is there a way to do this? I'd be insanely useful if I could make it so all or specific attributes could basically be pointed to a certain value (For me, it's just a scriptableobject variable named "value").

    In other words, ScriptableObjectParameter is a sort of container for a value, with some special get and set logic and stuff
     
  29. AmRafay1

    AmRafay1

    Joined:
    Oct 22, 2013
    Posts:
    592
    @bjarkeck
    Hi there, i have a generic monobehaviour based class like this
    Code (CSharp):
    1. public MyDataProvider<VOItem> : MonoBehaviour
    2. where VOItem:object{
    3.  
    4. }

    and i use it in control generic class
    Code (CSharp):
    1. public MyControl<VOItem> : MonoBehaviour
    2. where VOItem:object{
    3.  
    4. public MyDataProvider<VOItem> dataProvider;
    5.  
    6.  
    7. dataProvider = GetComponent<MyDataProvider<VOItem>>();
    8.  
    9. }
    10.  
    11.  
    12. }
    and finally a concrete implementation of both control and data provider. Currently i have to attach both concrete dataprovider and concrete control to the gameobject . and it works.


    But now i want to use same dataProvider class to 2 different gameobjects, and i want to do that "visually" dragging and dropping the concret dp class to that generic dataProvider property. Is there any attribute for that in Odin which exposes it to editor?


    Thanks
     
  30. AmRafay1

    AmRafay1

    Joined:
    Oct 22, 2013
    Posts:
    592
    Update 2:
    I'm able to show this field in insepctor using [ShowInInsepctor] and able to drag the shared dataprovider, however when i run the app it loses the references. What should i do?
     
  31. xjjon

    xjjon

    Joined:
    Apr 15, 2016
    Posts:
    145
    Just a note about one of the sample projects (RPG Editor)

    Code (CSharp):
    1.  // If you inspect the Character Overview in the inspector, you will also notice, that
    2. // the list is not directly modifiable. Instead, we've customized it so it contains a
    3. // refresh button, that scans the project and automatically populates the list.
    However - it is mutable, as the elements are mutable.

    Code (CSharp):
    1. [ReadOnly]
    2. [ListDrawerSettings(Expanded = true)]
    3. public Character[] AllCharacters;
     
  32. emrys90

    emrys90

    Joined:
    Oct 14, 2013
    Posts:
    428
    Is there an option to change the background color or put horizontal lines between list elements? When you have a list of a struct, it is currently not easy to see where one element ends and the next begins without looking very closely at it.
     
  33. srivello

    srivello

    Joined:
    Jan 16, 2011
    Posts:
    10
    I downloaded the latest version of Odin 1.0.6.4.

    In 2017.1 and above it works great.

    In 5.6.2p2 the console is spammed with this error. Please fix.

    MissingMethodException: Method not found: 'UnityEngine.Debug.get_unityLogger'.
     
  34. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    166
    Thanks, will look into it. Could you post the full log of that message? Or was that all it said? Were the other messages as well? Did it happen only in a certain scene? Some more information would be useful.
     
  35. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,007
    Finally I have the time to play around with this impressive tool. I downloaded the latest version in a clean new Unity project (using the very latest Unity 2017.4.0f1 on MacOS). I imported all the Demo Scenes and Scripts.

    Looking into the "Odin Attributes Overview", selected the "Default Drawer Changes" object and when I the "Normal Enum" field, which is set to the value "M" a window pop ups which just displays nothing along with a Console Warning, saying:



    Could not get serialized property for type EnumSelector<KeyCode>; this type will not be shown in the inspector.
    UnityEngine.Debug:LogWarning(Object)
    Sirenix.OdinInspector.Editor.InspectorPropertyInfo:populateUnityProperties(Type, List`1) (at D:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Utilities/SerializationDebugger/SerializationInfoMenuItem.cs:45)
    Sirenix.OdinInspector.Editor.InspectorPropertyInfo:CreateInspectorProperties(Type, Boolean) (at D:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Utilities/SerializationDebugger/MemberSerializationInfo.cs:30)
    Sirenix.OdinInspector.Editor.InspectorPropertyInfo:Get(Type, Boolean) (at D:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Utilities/SerializationDebugger/MemberSerializationInfo.cs:21)
    Sirenix.OdinInspector.Editor.PropertyTree`1:.ctor(EnumSelector`1[], SerializedObject)
    System.Activator:CreateInstance(Type, Object[])
    Sirenix.OdinInspector.Editor.PropertyTree:Create(IList, SerializedObject) (at D:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/Attribute Drawers/InlineEditorAttributeDrawer.cs:381)
    Sirenix.OdinInspector.Editor.PropertyTree:Create(IList)
    Sirenix.OdinInspector.Editor.PropertyTree:Create(Object)
    Sirenix.OdinInspector.Editor.OdinEditorWindow:UpdateEditors() (at D:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Children/PropertyValueCollection.cs:146)
    Sirenix.OdinInspector.Editor.OdinEditorWindow:OnGUI() (at D:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Children/PropertyValueCollection.cs:141)
    UnityEngine.GUIUtility:processEvent(Int32, IntPtr)

    EDIT:
    Happens with Flag Enums, too!


    I attached a screenshot and marked the empty Window in the upper left.
     

    Attached Files:

    bjarkeck likes this.
  36. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    166
    Thanks for the report and help on Discord.

    To everyone:
    We've accidentally introduced a bug in the latest 1.0.6.5 patch that got approved yesterday on the Asset Store. The bug affects all Unix based operating systems, and causes a wide range of strange behaviour. If you're on Windows you're good, but if not, best wait for the patch 1.0.6.6 to upgrade. So sorry about this! The hotfix 1.0.6.6 is already on its way to the Asset Store, but for those affected and need it now, just send us a message on discord, mail, or from our website with your Odin invoice number included, and we'll send you the hotfix right away.