Search Unity

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

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

  1. adamzl

    adamzl

    Joined:
    Feb 24, 2018
    Posts:
    19
    I was able to make a little progress on the above question using [OnValueChanged] but couldn't get it to automatically trigger when the AssetList is populated. I would get OnValueChanged callbacks at the start with an empty list of assets and then when I clicked on the asset list it would finally trigger the callback with actual values.
     
  2. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    704
    Hi, I just became a Odin user. Thank you very much for the wonderful product.
    To give you a background for the question, I would like use Unity to build a game management tool.
    I thought Odin is really nice since it has extensive editor extension and serialization support.

    Here is what I'm trying to do. I would like to use MongoDB for the backend server. Before became an Odin user, I already got succesfully got it working. It serialize/deserializes simple non-unity object just fine. But I can't seem to find a way to serialize/deserialize Unity object. That's why I turned to Odin and I was hoping Odin would help here but my limited knowledge with Odin, I can't figure it out yet.

    For an example, I tried to work with Vector3, strangely, it writes to MongoDB find but when I tried to read it back in, I get this error.


    Code (CSharp):
    1.  
    2. public class test : SerializedScriptableObject
    3. {
    4. [OdinSerialize]
    5.  public Vector3 vec3;
    6. ...
    7. }
    8.  
    BsonSerializationException: Value class UnityEngine.Vector3 cannot be deserialized.
    MongoDB.Bson.Serialization.BsonClassMapSerializer`1[TClass].Deserialize (MongoDB.Bson.Serialization.BsonDeserializationContext context, MongoDB.Bson.Serialization.BsonDeserializationArgs args) (at <6fcd046544f84fe7b17baa39d24ba979>:0)​

    If possible, could you please show me how this can be done?

    Thank you very much for your help.

    BTW, I use MongoRepository wrapper to make it things easier. https://github.com/esendir/MongoRepository
     
    Last edited: May 1, 2018
  3. Mlackey

    Mlackey

    Joined:
    Dec 5, 2014
    Posts:
    41
    Getting this error with Unity 2017.3.1p4

    Code (CSharp):
    1. ArgumentException: Invalid path
    2. System.IO.Path.GetDirectoryName (System.String path) (at <c95265f74fdf4905bfb0d5a4b652216c>:0)
    3. Sirenix.Utilities.AssemblyUtilities.GetAssemblyDirectory (System.Reflection.Assembly assembly) (at D:/Sirenix/Sirenix Solution/Sirenix.Utilities/Misc/AssemblyUtilities.cs:418)
    4. Sirenix.Utilities.AssemblyUtilities.GetAssemblyTypeFlagNoLookup (System.Reflection.Assembly assembly) (at D:/Sirenix/Sirenix Solution/Sirenix.Utilities/Misc/AssemblyUtilities.cs:232)
    5. Sirenix.Utilities.AssemblyUtilities.GetAssemblyTypeFlag (System.Reflection.Assembly assembly) (at D:/Sirenix/Sirenix Solution/Sirenix.Utilities/Misc/AssemblyUtilities.cs:221)
    6. Sirenix.Utilities.AssemblyUtilities.RegisterAssembly (System.Reflection.Assembly assembly) (at D:/Sirenix/Sirenix Solution/Sirenix.Utilities/Misc/AssemblyUtilities.cs:117)
    7. Sirenix.Utilities.AssemblyUtilities.Reload () (at D:/Sirenix/Sirenix Solution/Sirenix.Utilities/Misc/AssemblyUtilities.cs:109)
    8. Sirenix.Utilities.AssemblyUtilities..cctor () (at D:/Sirenix/Sirenix Solution/Sirenix.Utilities/Misc/AssemblyUtilities.cs:186)
    9. Rethrow as TypeInitializationException: The type initializer for 'Sirenix.Utilities.AssemblyUtilities' threw an exception.
    10. Sirenix.OdinInspector.Editor.InspectorTypeDrawingConfigDrawer..cctor () (at D:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Value Entries/PropertyValueEntryAlias.cs:334)
    11. Rethrow as TypeInitializationException: The type initializer for 'Sirenix.OdinInspector.Editor.InspectorTypeDrawingConfigDrawer' threw an exception.
    12. Sirenix.OdinInspector.Editor.InspectorConfig.UpdateOdinEditors () (at <428e9f1bdbd84f4da186445d347c5a34>:0)
    13. Sirenix.OdinInspector.Editor.OdinEditorWindow.OnGUI () (at D:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Children/PropertyValueCollection.cs:141)
    14. Sirenix.OdinInspector.Editor.OdinMenuEditorWindow.OnGUI () (at D:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/OdinEditorWindow/OdinMenuItem.cs:128)
    15. System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <c95265f74fdf4905bfb0d5a4b652216c>:0)
    16. Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
    17. System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <c95265f74fdf4905bfb0d5a4b652216c>:0)
    18. System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) (at <c95265f74fdf4905bfb0d5a4b652216c>:0)
    19. UnityEditor.HostView.Invoke (System.String methodName, System.Object obj) (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:295)
    20. UnityEditor.HostView.Invoke (System.String methodName) (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:288)
    21. UnityEditor.HostView.InvokeOnGUI (UnityEngine.Rect onGUIPosition) (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:261)
    22. UnityEditor.DockArea.OldOnGUI () (at C:/buildslave/unity/build/Editor/Mono/GUI/DockArea.cs:398)
    23. UnityEngine.Experimental.UIElements.IMGUIContainer.DoOnGUI (UnityEngine.Event evt) (at C:/buildslave/unity/build/Runtime/UIElements/Managed/IMGUIContainer.cs:182)
    24. UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
    Nothing appears for any of the other options under Tool for this plugin. Tons of looping errors that go away once I delete the plugin. Didn't have an issue with this plugin until I updated. Tried with a new build and still not working.

    Any fix for this?

    ------------------------------------

    EDIT: 5/1/2018

    The issue seems to have resolved itself, I reinstalled my version of Unity, it still threw the same error so I then rebuilt the project libraries for the fresh project with just Odin in it and it resolved, I then rebuilt the library for my actual project overnight and it resolved.

    It appears to have been an error with Unity referencing the asset properly.

    The error appears to have revolved around Unity itself and an error in referencing the asset, I don't know whether rebuilding the library fixed it or if it was just unity itself however, it resolved.

    I've been using this asset since summer of 2017 and this is the first error I've had with it. Absolutely wonderful asset.
     
    Last edited: May 1, 2018
  4. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Hey there, thanks for reporting, and sorry about the issue.

    Could PM me your Odin invoice ID, along with the path to your Unity project, and maybe some information about which plugins you also have present? Then I can also send you ASAP.
     
  5. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Hey, Odin can definitely help you display data that you may store in databases, and isn't necessarily serialized by Unity.

    But, I can really help you with how you would go about storing Unity types with MongoDB. I think you would have to give the ORM a Unity's serialization policy so it knows exactly what data from the Vector3 should be included in the database.

    I would reach out to a MonogDB veteran and ask him how to add support for types such as those from Unity.
     
  6. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Yeah those attributes are likely never to really work well together :/

    Isn't that how it would be rendered in the Inspector by default already? https://jumpshare.com/v/HLZs8qw7x1gpVaXzUYC8 Could you explain a bit more visually what you're after perhaps?
     
  7. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    If I understand you correctly, you can simply do this by "right-clicking -> Copy Special -> Copy Reference", and then paste reference directly in the dictionary
     
  8. adamzl

    adamzl

    Joined:
    Feb 24, 2018
    Posts:
    19
    Attaching explanation image: https://drive.google.com/open?id=1xT3j7lPxeFmaFHqkzD4cUM1OwmJD0gMA

    Ships are defined by a 2D grid of blocks, the bottom array allow me to easily build a ship by drag and dropping prefab blocks into the grid (many thanks for control-click-drag). Currently I drag in blocks from a folder in the project hierarchy but am hoping to simplify that by using the top list of prefabs and dragging them into the bottom array. As I work on this more I see I'll likely have an issue dragging between the two lists but mostly I want the top AssetList to render previews.

    I hear you on "they probably won't work together", but since this is a ScriptableObject I couldn't find a callback to let me execute code to fix this problem (Copy the prefab list[] into a prefab array[,] via OnValuChanged script). OnValueChanged did not trigger when the AssetList was populated, only a callback at the start with no values and a callback when I clicked on it.
     
  9. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    Hello,

    1. Before coming to Odin I was using Google Spreadsheet and sync the data to ScriptableObject. One thing I missed having when using [TableList] is that is there any way to style the cell based on some criteria? Like with enums I would like the cell to be yellow if it is at some value, for example. (Or color the whole row based on some criteria that that row met) If a cell coloring is not possible an approach to make the enum dropdown itself change color based on its value would be nice.

    2. Also, can I have HorizontalGroup in a BoxGroup? It seems that BoxGroup can be horizontally next to each other, but contents inside the BoxGroup must be listed vertically. (I have tried to put HorizontalGroup inside BoxGroup using "/" syntax but they still appear sequentially from top to bottom)

    3. I am amazed by `OdinMenuEditorWindow`! I have my own similar solution before and I am planning to switch to Odin, however the side bar is a bit too large to have it at the usual "inspector width". My previous solution have the index at top, it would be great if you could consider an OdinMenuStyle which put the navigation on top, or is there any way to custom OdinMenuEditorWindow's navigation to be like that? Here's a picture of what I have had. I could tab it at the together with Inspector because it does not require too much horizontal space.

    Screenshot 2018-05-02 09.22.07.png

    4. Odin forcibly draw something that I already have PropertyDrawer for. Is this an intended behaviour? For a class which I have custom `: Editor` and `OnInspectorGUI` it uses my own drawing correctly but not the one with `: PropertyDrawer`. How to prevent Odin from doing this?
     
    Last edited: May 2, 2018
    bjarkeck likes this.
  10. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    704
    Hi, Isn't Odin supposed to help serialize Unity Objects? I'm not sure how Odin can help here. I tried to look for more info in Odin documentation but there aren't much useful information how serialization works. How am I suppose to serialize Vector3? It is pretty much the simpliest Unity object. Thanks for any help.
     
  11. Aggressor

    Aggressor

    Joined:
    Aug 10, 2012
    Posts:
    62
    Sorry if I wasn't clear. The issue is if I create a variable on a class like so:

    Code (CSharp):
    1.     public IResolver test; // DOES NOT APPEAR IN INSPECTOR
    I am unable to create an instance of it and assign it to that variable in the inspector. However, the default dictionary behaviour allows this.

    Do you know how I can reproduce this:



    With a variable that is just sitting in a class?

    The value field for an IResolver in the dictionary defaults to this *Null (IResolver) field that lets me instantiate an instance.

    But when I delcare just a regular variable on a class as an IResolver, it doesn't even appear in the inspector, nor allow me to create an instance of it.

    Hopefully that is more clear?
     
  12. bumbummen99

    bumbummen99

    Joined:
    May 19, 2013
    Posts:
    10
    Edit: Ok it is working as intendet.
     
    Last edited: May 4, 2018
  13. tcmeric

    tcmeric

    Joined:
    Dec 21, 2016
    Posts:
    190
    Hi, is there any plan to add an attribute of [Tag] or [Tags] ? Thanks.
     
  14. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Thanks for reporting, I've reached out to the developer of TerrainComposer, in hopes to get a copy so I can investigate the problem further. Will keep you updated :)
     
  15. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    tcmeric likes this.
  16. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Ahh, I see. I like the idéa of being able to quickly provide a selection to populate the matrix with. Can't think of anything Odin has that will help with that out of the box though, will think about this one :) Perhaps, just adding a button that opens up a new Project Window, with the correct folder selected, could be useful?
     
  17. Dan2013

    Dan2013

    Joined:
    May 24, 2013
    Posts:
    200
    Thanks for your answering.
    I am considering the most convenient way to represent the JSON data in Odin.
    Since JSON can be easily represented as dictionaries and arrays, I proposed to use SerializedMonoBehaviour to represent the dictionaries on Odin inspector.
     
  18. Dimlos

    Dimlos

    Joined:
    Aug 13, 2014
    Posts:
    51
    Hello,
    I never wrote any shader by hand, allways used ShaderForge and now Amplify Shader since ShaderForge developpement is stoped.
    I was wondering if it was possible to use Sirenix attributes in shaders? I can't use the "using" keyword.
    Is there a way of doing that or is it not possible in .shader files?
     
  19. Osteel

    Osteel

    Joined:
    Jan 17, 2014
    Posts:
    59
    Hi! Thanks for a great plugin. :)

    Quick question. Is it possible to show Interfaces (specifically a list of them) inside a Scriptable Object?
     
  20. bullardo

    bullardo

    Joined:
    Jan 5, 2013
    Posts:
    46
    On Unity 2017.3.1p4 (64-bit) Any clue why this would happen on Android builds?
    Error removing component when merging prefab changes: Can't remove AudioSource because FirstPersonController (Script) depends on it
    UnityEditor.SceneManagement.EditorSceneManager:OpenScene(String, OpenSceneMode)
    Sirenix.Serialization.AOTGenerationConfig:processScenes()
    Sirenix.Serialization.AOTGenerationConfig:processProject(List`1&)
    Sirenix.Serialization.AOTGenerationConfig:ScanProject()
    Sirenix.Serialization.Internal.PreBuildAOTAutomation:OnPreprocessBuild(BuildTarget, String) (at Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/BuildAOTAutomation.cs:37)
    UnityEngine.GUIUtility:processEvent(Int32, IntPtr)
     
  21. RafaelKalleen

    RafaelKalleen

    Joined:
    Mar 5, 2013
    Posts:
    2
    Nevermind, I couldn't understand how Vertical/Horizontal groups worked but a cup of coffee later everything made sense. I think I need some sleep haha.
     
    Last edited: May 6, 2018
    bjarkeck likes this.
  22. candycat

    candycat

    Joined:
    Jun 5, 2014
    Posts:
    29
    Great plugin!

    Is there any callback of delete event for List properties? There does exist such a CustomAddFunction, but no "CustomDeleteFunction".
     
  23. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    Code (CSharp):
    1.             SirenixEditorGUI.BeginBox(attribute.ShowLabel ? labelGetter.Value.GetString(property) : null, attribute.CenterLabel);
    2.  
    3.             for (int i = 0; i < property.Children.Count; i++)
    4.             {
    5.                 InspectorUtilities.DrawProperty(property.Children[i]);
    6.             }
    7.  
    8.             SirenixEditorGUI.EndBox();
    When using `OdinGroupDrawer` 's `DrawPropertyGroupLayout` there is an `attribute` parameter, however it seems to be a group attribute the first item only. How can I get a group `attribute` of each children in the group while drawing?

    I have a custom group drawer which maps to the same Box Group, but accepts an additional string that I would like to use to draw each item. I could only get that string of the first item in the group.

    Previously :
    [BoxGroup("Test")] public int a;
    [BoxGroup("Test")] public int b;
    [BoxGroup("Test")] public int c;

    Currently :
    [TestGroup("aaa")] public int a;
    [TestGroup("bbb")] public int b;
    [TestGroup("ccc")] public int c;

    EDIT : Never mind I got it. I need to use `CombineValuesWith(PropertyGroupAttribute other)` to get those value across to the main ones. Works great now.
     
    Last edited: May 7, 2018
    bjarkeck likes this.
  24. candycat

    candycat

    Joined:
    Jun 5, 2014
    Posts:
    29
    I want to add some alerts when deleting elements. How can i do?
     
  25. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Making Odin's attributes available in shader code is not something we've looked into, but it's defiantly not something that works out of the box. Would have to investigate it a bit to see what is possible. Would like to look into this at some point. If you find out anything interesting I would be very curious :)
     
  26. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Yup, :) Either, if you just want to show it, you can just put [ShowInInspector] on the list of interfaces, and if you want to serialize them and show them, then just inherit form SerializedScriptableObject, and then it will be shown and serialized without the [ShowInInspector].
     
  27. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Hey, this has been a very popular request. And it's coming in 1.1 (The next big patch)! - It's currently in beta, so if you want in, shoot me a message with your Odin invoice Id :)

    This applies to everyone with Odin btw!

    odin1_1preview.png
     
    candycat likes this.
  28. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    1. We'll keep that in mind when we revisit the TableList attribute, which is bound to happen at some point! But you can color the enum-field. In 1.1 we've added a cosntructer to the [GUIColor] attribute, that lets you reference a member that returns a color. Bun untill then you can do something like this:

    Code (CSharp):
    1. [OnInspectorGUI("BeginChangeColor", "EndChangeColor")]
    2. public KeyCode keyCode;
    3.  
    4. private void BeginChangeColor()
    5. {
    6.     GUI.color = this.keyCode == KeyCode.Space ? Color.red : Color.white;
    7. }
    8.  
    9. private void EndChangeColor()
    10. {
    11.     GUI.color = Color.white;
    12. }
    2. Yeah you can group groups together. If you open up the Attributes Demo example, there is a Groups in Groups example. But here is one of the examples:

    Code (CSharp):
    1. [HorizontalGroup("Split", width: 0.4f, LabelWidth = 20)]
    2. [BoxGroup("Split/Left")]
    3. public int[] A;
    4.  
    5. [BoxGroup("Split/Left")]
    6. public int[] C;
    7.  
    8. [BoxGroup("Split/Center")]
    9. public int[] B;
    10.  
    11. [BoxGroup("Split/Center")]
    12. public int[] D;
    13.  
    14. [HorizontalGroup("Split", width: 0.4f)]
    15. [BoxGroup("Split/Right")]
    16. public int[] E;
    17.  
    18. [BoxGroup("Split/Right")]
    19. public int[] F;
    3) Cool we have something very similar, we do this with TabGroups:

    dashboard.png

    This is the idea:

    Code (CSharp):
    1. public class ControlPanel : ScriptableObject
    2. {
    3.     [MenuItem("MyGame/Control Panel")]
    4.     private static void OpenControlPanel()
    5.     {
    6.         var cp = AssetDatabase.FindAssets("t:ControlPanel")
    7.             .Select(x => AssetDatabase.GUIDToAssetPath(x))
    8.             .Select(x => AssetDatabase.LoadAssetAtPath<ControlPanel>(x))
    9.             .FirstOrDefault();
    10.  
    11.         OdinEditorWindow.InspectObject(cp);
    12.     }
    13.  
    14.     [TabGroup("Default Palette")]
    15.     public int a;
    16.  
    17.     [TabGroup("Game Settings")]
    18.     public int b;
    19.  
    20.     [TabGroup("Operation")]
    21.     public ScriptableObject SimfileDatabase;
    22.  
    23.     [TabGroup("Operation")]
    24.     public ScriptableObject LanguageSource;
    25.  
    26.     [TabGroup("SceneSelector"), HideLabel, ShowInInspector, HideReferenceObjectPicker]
    27.     public SceneSelector sceneSelector;
    28. }
    29.  
    30. public class SceneSelector
    31. {
    32.     [OnInspectorGUI]
    33.     public void OnGUI()
    34.     {
    35.         // stuff?
    36.     }
    37. }
    4) I'm not sure I follow. Do you have a PropertyDrawer that Odin doesn't draw? And yeah, if you have a custom Editor for a type, then Odin won't be applied at all for that type. That way we don't break existing editors.
     
    5argon likes this.
  29. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    Sorry, for this question actually that class is a button that I derived from Unity's Button. I am trying to remove something I don't use and rearranging Unity's Button interface to suit my game more. Like, I am making a mobile game and I don't want to see any highlighted property or navigations. And also I have added on Down event in addition to on Click, etc.

    It was drawn by UnityEditor.UI.ButtonEditor and not Odin. I understand that Odin avoids drawing things if it is already drawn by something else. My additional fields of my subclass of Button are added properly to the base class by the way, because the Button drawing code of Unity explicitly search for any subclass component.

    The only way around this seems to be using Unity's `: Editor` then the good old `OnInspectorGUI`. My question is, from this empty `OnInspectorGUI` function which makes everything disappear do I have any way to explicitly tells Odin to draw my class? (Preferrably with logic I have written in `OdinValueDrawer<MyButton>`) Thanks.
     
  30. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Would inheriting the Editor from OdinEditor instead of Editor do the trick in your case?
     
    5argon likes this.
  31. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    Thanks, works like a charm! Didn't know such a class exist!

    Currently I managed to filter something out when enumerating the property tree. With the new AttributeResolver I hope I could modify Unity's things before it arrives at PropertyTree > InspectorProperty > DrawerLocator.GetDrawersForProperty so that InspectorUtilities.DrawProperty(property); draws differently. It would be really cool if can change Unity's default presentation for everything. Will try once I get the beta.
     
  32. MarcopoloR

    MarcopoloR

    Joined:
    Feb 4, 2015
    Posts:
    114
    Hi, I am currently teaching myself C# and am just starting to get into some of the more advanced stuff. This seems to be a popular asset but I am trying to figure out exactly how it would help me. I am currently learning about scriptable objects, and how to use system serializable and serialize field to do stuff like expose variables in the inspector. There is a lot I still don't understand about the whole thing. I am also struggling to try and make a save/load system and an inventory system. So when you say full serialization are you talking about a system to replace inheriting from serialization? or a new way to scriptable objects? Can you more easily make a runtime save/load system with this? Or is it just for more advanced programmers who mainly want to do editor scripting stuff to write their own unity editor extensions? Forgive me if I sound ignorant but am curious if this system would at all help me (in newbie programmer terms) and why it is so much better than the existing serialization and editor extension tools?
     
  33. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Cool, let me know how all of that turns out :)
     
  34. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Hey there :)

    Well to begin with, I would suggest that you familiarized yourself with Unity's way of doing things first in terms of serialization. If you just want a ton of more editor capabilities, then definitely pick up Odin, it's quite beginner friendly in many areas I would say. ;)

    But I would advice you to stick around with Unity's serialization for a while, until you're more familiar with all the concepts that are involved - check out Unitys Json serialization Utility, I think that can get you a long way to start off with. If you then later want to have better performance, serialize more data-types etc, then Odin's serialization can defiantly help you out.

    In terms of ScriptableObjects, Odin has a SerialziedScriptableObject which utilizes Odins serialization system behind the scenes, to serialize data that Unity can't serialize, and Odin of course also makes sure to show that data in the editor. But again, in the beginning I advise you to stick with Unity's serialization and keep things simple.
     
  35. MarcopoloR

    MarcopoloR

    Joined:
    Feb 4, 2015
    Posts:
    114
    Okay, thanks for your frankness, that is what I was thinking too. This is on sale and a very popular asset so I thought I would consider it.
     
    bjarkeck likes this.
  36. adamzl

    adamzl

    Joined:
    Feb 24, 2018
    Posts:
    19
    Spent some time trying to follow your advice, couldn't figure out how one pops a project window. While looking into this stuff though I did find EditorGuiUtility.ShowObjectPicker(), seems like the best solution here is if I could override the "select" button that shows when you mouse over one of the matrix squares. This already has some functionality for filtering, dreams of future features I suppose.
     
  37. dantonel

    dantonel

    Joined:
    Dec 7, 2015
    Posts:
    8
    Hi, I see that CustomDeleteFunction for ListDrawerSetterings is planned for Odin 1.1, but I was wondering if there was more customization coming to Lists. Here's a list of some of the things I'm struggling with:

    The default dialog that comes up with the Add button does not support MonoBehaviours on Prefabs - I can only get prefabs from the dialog if the type is List<GameObject>, not List<MyScript> (where I would want all prefabs that have that script on them to appear)

    Also with the dialog, it would be great if we could add custom choices in there such as "Create New". I want my level designers to chose from a list of items that already exist in the scene (and maybe prefabs), but also be able to create a new one easily if it's not there yet. I was able to do something similar using a custom add function along with UnityEditor.GenericMenu (and calling .ShowAsContext() after manually creating a "Create New" entry and an entry for each item in the scene), but it's really ugly, and hard to navigate if there are a lot of items in the scene especially since this menu doesn't support scrolling with the mouse wheel.

    Finally, is there a way to add context menu entries to the items in the list, not just to the list itself?
     
  38. Artaani

    Artaani

    Joined:
    Aug 5, 2012
    Posts:
    423
    Hello.
    Is there a way to somehow write a description of variable \ function \ class - so as result, this description will be visible in both situations:

    1. When I hover cursor over this variable in the IDE
    2. When I hover cursor over this variable in the Unity Inspector

    Currently in order to achieve such result I should write:

    2018-05-14 16_10_26-Assembly-CSharp - TooltipTester.cs - MonoDevelop-Unity.png

    But this is a lot of code per each variable. 4 lines and description text duplicated twice.
    Maybe Odin may provide something which will allows to achieve such result using single line of code?
     
    Romenics and bjarkeck like this.
  39. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Cool idea! But there is unfortunately no easy way to pull it of that I know of. The hard part is getting the documentation of any given MemberInfo. I'm not actually sure whether those mdb files is a mono or unity thing. I know there is a tool in the MonoBleedingEdge that lets you convert pdb files to mdb files which we actually use as part of our building pipeline, but beyond that I'm blank.

    If you manage to somehow pull it of and get the comments out of the mdb files then Odin can defiantly help you display that data in the inspector as a tooltip :)
     
    Artaani likes this.
  40. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    I think the 1.1 patch will have everything you would need to make that easily. The ValueDropdown takes over the list add button in 1.1 so you'll be able to easily populate a list of things to choose from, and it handles lists of assets and unity objects really well with search etc... So I would say give the beta a try :D (pm me your Odin Invoice number and I'll send it to you)

    Not sure how you would do the CreateNew, if you have any think you think Odin could add to make that part easy let me know.
     
  41. tspk91

    tspk91

    Joined:
    Nov 19, 2014
    Posts:
    131
    Hi, I'm using Unity 2017.4.3f1 and Odin (I am using the latest AssetStore version) fails to work at all. I reproduced the bug in an empty project. Custom inspectors are shown with unity's default style or not at all. I cannot even enter the odin preferences window.

    Code (CSharp):
    1. InvalidCastException: Cannot cast from source type to destination type.
    2. Sirenix.OdinInspector.Editor.CustomEditorUtility.ResetCustomEditors () (at D:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Children/PropertyValueCollectionAlias.cs:256)
    3. Sirenix.OdinInspector.Editor.InspectorConfig.UpdateOdinEditors ()
    4. Sirenix.OdinInspector.Editor.OdinEditorWindow.OnGUI () (at D:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Children/PropertyValueCollection.cs:141)
    5. Sirenix.OdinInspector.Editor.OdinMenuEditorWindow.OnGUI () (at D:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/OdinEditorWindow/OdinMenuItem.cs:128)
    6. System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222)
    7. Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
    8. System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:232)
    9. System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MethodBase.cs:115)
    10. UnityEditor.HostView.Invoke (System.String methodName, System.Object obj) (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:295)
    11. UnityEditor.HostView.Invoke (System.String methodName) (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:288)
    12. UnityEditor.HostView.InvokeOnGUI (Rect onGUIPosition) (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:255)
     
    Last edited: May 14, 2018
  42. jsizemore

    jsizemore

    Joined:
    May 14, 2018
    Posts:
    3
    Hello everyone. I'm having trouble using the Serialization utility. The class I am trying to serialize is an item class with member fields that are all primitive data types, guids, and some enums. I was able to serialize this file but I could not deserialize it. I tried again to serialize, this time with the simplest class I could think of:

    Code (CSharp):
    1. public class SerializeTest : SerializedMonoBehaviour
    2. {
    3.     public int x = 1;
    4. }
    and this is the code I'm using to actually serialize and deserialize:

    Code (CSharp):
    1.             GameObject obj = GameObject.Find("SerializeTest");
    2.             SerializeTest st = obj.GetComponent<SerializeTest>();
    3.  
    4.             FileStream file = File.Create(Path.Combine(Application.streamingAssetsPath, "test.gd"));
    5.             SerializationContext sc = new SerializationContext(new StreamingContext(StreamingContextStates.File));
    6.             BinaryDataWriter writer = new BinaryDataWriter(file, sc);
    7.             SerializationUtility.SerializeValue<SerializeTest>(st, writer);
    8.             file.Close();
    9.  
    10.             file = File.OpenRead(Path.Combine(Application.streamingAssetsPath, "test.gd"));
    11.             DeserializationContext dc = new DeserializationContext(new StreamingContext(StreamingContextStates.File));
    12.             BinaryDataReader reader = new BinaryDataReader(file, dc);
    13.             SerializeTest st2 = SerializationUtility.DeserializeValue<SerializeTest>(reader);
    14.             file.Close();
    As can be seen above, I just stick my script on an empty GameObject in my scene, find it and get the script component off of it, and then attempt to serialize. The serialization works just fine, but upon de-serialization I get the following error every single time:

    Code (CSharp):
    1. ArgumentNullException: Argument cannot be null.
    2. Parameter name: unityObject
    3.  
    4. Sirenix.Serialization.UnitySerializationUtility.DeserializeUnityObject (UnityEngine.Object unityObject, Sirenix.Serialization.SerializationData& data, Sirenix.Serialization.DeserializationContext context, Boolean isPrefabData, System.Collections.Generic.List`1 prefabInstanceUnityObjects) (at F:/Sirenix/Sirenix Solution/Sirenix.Serialization/Utilities/UnitySerializationUtility.cs:1005)
    5. Sirenix.Serialization.UnitySerializationUtility.DeserializeUnityObject (UnityEngine.Object unityObject, Sirenix.Serialization.SerializationData& data, Sirenix.Serialization.DeserializationContext context) (at F:/Sirenix/Sirenix Solution/Sirenix.Serialization/Utilities/UnitySerializationUtility.cs:994)
    6. Sirenix.OdinInspector.SerializedMonoBehaviour.UnityEngine.ISerializationCallbackReceiver.OnAfterDeserialize () (at F:/Sirenix/Sirenix Solution/Sirenix.Serialization/Unity Integration/SerializedMonoBehaviour.cs:25)
    7. Sirenix.Serialization.BaseFormatter`1[SerializeTest].Deserialize (IDataReader reader) (at F:/Sirenix/Sirenix Solution/Sirenix.Serialization/Formatters/BaseFormatter.cs:207)
    8. UnityEngine.Debug:LogException(Exception)
    9. Sirenix.Serialization.CustomLogger:LogException(Exception) (at F:/Sirenix/Sirenix Solution/Sirenix.Serialization.Config/CustomLogger.cs:61)
    10. Sirenix.Serialization.DebugContext:LogException(Exception) (at F:/Sirenix/Sirenix Solution/Sirenix.Serialization/Misc/SerializationConfig.cs:222)
    11. Sirenix.Serialization.BaseFormatter`1:Deserialize(IDataReader) (at F:/Sirenix/Sirenix Solution/Sirenix.Serialization/Formatters/BaseFormatter.cs:211)
    12. Sirenix.Serialization.ComplexTypeSerializer`1:ReadValue(IDataReader) (at F:/Sirenix/Sirenix Solution/Sirenix.Serialization/Serializers/ComplexTypeSerializer.cs:332)
    13. Sirenix.Serialization.SerializationUtility:DeserializeValue(IDataReader) (at F:/Sirenix/Sirenix Solution/Sirenix.Serialization/Utilities/SerializationUtility.cs:330)
    I get the same error no matter what I try - I've also attempted the following versions of SerializeValue/DeserializeValue:

    Code (CSharp):
    1.      SerializeValue<T>(T, Stream, DataFormat, SerializationContext)
    2.      DeserializeValue<T>(Stream, DataFormat, DeserializationContext)
    .........but I still get the same error. I'm not really sure what I'm doing wrong. I can get it to serialize, but I can't deserialize it. What am I doing wrong and how can I get this to work? I'm really pulling my hair out with this one.
     
  43. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    The fix for the latest Unity 2017.4 is on it's way to the Asset Store, send me a pm, with your Odin invoice id, then I'll send it to you right away :)
     
  44. bac9-flcl

    bac9-flcl

    Joined:
    Dec 5, 2012
    Posts:
    829
    I'm not sure if this is by design or a bug - any non-inline (popup) selection widgets, like enum value selectors or custom texture fields, seem to fail to trigger calls to OnValueChanged functions when you change selections in them. Only exiting those popups triggers an update. This is not consistent with behaviour of the default object field drawer and old Unity drawers, where, for example, clicking a Texture field brought out a popup where every click immediately triggers an update.

    Though I might be mistaken - maybe they just take over editor drawing and OnValueChanged functions are correctly called immediately, except scene view, console view and other parts of the main window I use to debug the behaviour are simply not redrawn immediately on clicks to Odin popups, like they are when clicks land on the main window. This is more likely.

    Another thing I'm unsure about - is clicking an X button in the top right corner the only way to exit custom PreviewField popups without clearing the value? With old object popups, clicking anywhere outside of them or hitting Esc closed the popup and maintained an old value, but PreviewField-triggered popup with a list of Textures (or any other objects) seems to set the field to null when you do the same (click outside of the list or hit Esc).

    Otherwise, this is an incredible asset, keep up the great work!

    P.S.: Forgot another minor issue: Odin arguments like OnValueChanged seem to be unable to use methods where every argument has a default value (so, methods which can be used in C# code as argument-less actions), like these:

    Code (csharp):
    1. private void RefreshMaterial (bool skipChecks = false)
    2. {
    3.     if (!skipChecks)
    4.     {
    5.         CheckSetup ();
    6.         if (!setupComplete)
    7.             return;
    8.     }
    9.  
    10.     // Do stuff
    11. }
    A quick workaround is to refactor those methods into two, I suppose:

    Code (csharp):
    1. private void RefreshMaterial ()
    2. {
    3.     RefreshMaterial (false);
    4. }
    5.  
    6. private void RefreshMaterial (bool skipChecks)
    7. {
    8.     if (!skipChecks)
    9.     {
    10.         CheckSetup ();
    11.         if (!setupComplete)
    12.             return;
    13.     }
    14.  
    15.     // Do stuff
    16. }
    This makes Odin arguments work correctly, without errors. I'm not familiar enough with reflection, so I'm not sure if it's really a fault of the arguments - maybe C# makes it impossible to treat the first example as an argument-less method for the purposes of an attribute. :)
     
    Last edited: May 14, 2018
    bjarkeck likes this.
  45. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Thanks a lot for the feedback. Will take a look at your reportings tomorrow and see what's up. And yeah, we could actually easily just invoke the method if all parameters has default values, I've added it to our todo :)
     
  46. jsizemore

    jsizemore

    Joined:
    May 14, 2018
    Posts:
    3
    Hello there,

    Just checking back in to follow up with the question I posted the other day (post #592). Thank you!
     
  47. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Was just trying out the 2018.2 beta and this error shows up occasionally. I can't see anything bad it's doing to data at first glance.

    AmbiguousMatchException: Ambiguous match found.
    System.RuntimeType.GetMethodImpl (System.String name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Reflection.CallingConventions callConv, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) (at <e1a80661d61443feb3dbdaac88eeb776>:0)
    System.Type.GetMethod (System.String name, System.Reflection.BindingFlags bindingAttr) (at <e1a80661d61443feb3dbdaac88eeb776>:0)
    Sirenix.OdinInspector.Editor.UnityPropertyHandlerUtility..cctor () (at F:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Context/PropertyContext.cs:60)
    Rethrow as TypeInitializationException: The type initializer for 'Sirenix.OdinInspector.Editor.UnityPropertyHandlerUtility' threw an exception.
    Sirenix.OdinInspector.Editor.UnityPropertyDrawer`2[TDrawer,TDrawnType]..ctor () (at <318f40a3260646299b4357350c53962c>:0)
    System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters) (at <e1a80661d61443feb3dbdaac88eeb776>:0)
    Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
    System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters) (at <e1a80661d61443feb3dbdaac88eeb776>:0)
    System.RuntimeType.CreateInstanceMono (System.Boolean nonPublic) (at <e1a80661d61443feb3dbdaac88eeb776>:0)
    System.RuntimeType.CreateInstanceSlow (System.Boolean publicOnly, System.Boolean skipCheckThis, System.Boolean fillCache, System.Threading.StackCrawlMark& stackMark) (at <e1a80661d61443feb3dbdaac88eeb776>:0)
    System.RuntimeType.CreateInstanceDefaultCtor (System.Boolean publicOnly, System.Boolean skipCheckThis, System.Boolean fillCache, System.Threading.StackCrawlMark& stackMark) (at <e1a80661d61443feb3dbdaac88eeb776>:0)
    System.Activator.CreateInstance (System.Type type, System.Boolean nonPublic) (at <e1a80661d61443feb3dbdaac88eeb776>:0)
    System.Activator.CreateInstance (System.Type type) (at <e1a80661d61443feb3dbdaac88eeb776>:0)
    Sirenix.OdinInspector.Editor.DrawerLocator.GetDrawer (System.Type drawerType, System.Boolean forceUniqueDrawerInstance) (at <318f40a3260646299b4357350c53962c>:0)
    Sirenix.OdinInspector.Editor.DrawerLocator+<>c__DisplayClass35_0.<GetAllDrawers>b__2 (Sirenix.OdinInspector.Editor.DrawerInfo info) <0x584b7e40 + 0x00072> in <318f40a3260646299b4357350c53962c>:0
    UnityEngine.Debug:LogException(Exception)
    Sirenix.OdinInspector.Editor.<>c__DisplayClass35_0:<GetAllDrawers>b__2(DrawerInfo)
    System.Linq.WhereEnumerableIterator`1:MoveNext()
    Sirenix.Utilities.<Append>d__19`1:MoveNext() (at F:/Sirenix/Sirenix Solution/Sirenix.Utilities/Extensions/LinqExtensions.cs:343)
    System.Linq.Enumerable:ToArray(IEnumerable`1)
    Sirenix.OdinInspector.Editor.DrawerLocator:GetAllDrawers(Type, Type, List`1, Boolean)
    Sirenix.OdinInspector.Editor.DrawerLocator:GetValueDrawers(Type) (at F:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:710)
    Sirenix.OdinInspector.Editor.DrawerLocator:GetDrawersForMemberInfo(MemberInfo, Type, Boolean) (at F:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:524)
    Sirenix.OdinInspector.Editor.DrawerLocator:GetDrawersForProperty(InspectorProperty) (at F:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:535)
    Sirenix.OdinInspector.Editor.InspectorUtilities:DrawProperty(InspectorProperty, GUIContent)
    Sirenix.OdinInspector.Editor.InspectorUtilities:DrawProperty(InspectorProperty)
    Sirenix.OdinInspector.Editor.InspectorUtilities:DrawPropertiesInTree(PropertyTree)
    Sirenix.OdinInspector.Editor.PropertyTree:Draw(Boolean)
    Sirenix.OdinInspector.Editor.OdinEditor:DrawTree() (at F:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Children/PropertyValueCollection.cs:541)
    Sirenix.OdinInspector.Editor.OdinEditor:DrawOdinInspector() (at F:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Children/PropertyValueCollection.cs:533)
    Sirenix.OdinInspector.Editor.OdinEditor:OnInspectorGUI() (at F:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Children/PropertyValueCollection.cs:516)
    UnityEngine.GUIUtility:processEvent(Int32, IntPtr)
     
  48. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    I'm also wondering if the above might be related to the api updater always triggering and then failing on what looks like the odin inspector editor dll. Error messages aren't really helpful they mention the editor csproj though, and I can't think of any other editor dll's I have so just a guess.
     
  49. tspk91

    tspk91

    Joined:
    Nov 19, 2014
    Posts:
    131
    Welp, the asset store fix works fine!
     
  50. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Try this approach:

    Code (CSharp):
    1.    public void SaveData()
    2.    {
    3.        byte[] bytes = SerializationUtility.SerializeValue(data, format);
    4.        using (var fs = new FileStream(FilePath, FileMode.Create, FileAccess.Write, FileShare.Write))
    5.        using (var writer = new BinaryWriter(fs))
    6.        {
    7.            writer.Write(bytes);
    8.        }
    9.    }
    10.  
    11.    public void LoadData()
    12.    {
    13.        using (var fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
    14.        using (var reader = new BinaryReader(fs))
    15.        {
    16.            this.data = SerializationUtility.DeserializeValue<Data>(reader.BaseStream, format);
    17.        }
    18.    }