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. We're looking for your feedback on the platforms you use and how you use them. Let us know!
    Dismiss Notice
  4. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  5. Improve your Unity skills with a certified instructor in a private, interactive classroom. Learn more.
    Dismiss Notice
  6. ARCore is out of developer preview! Read about it here.
    Dismiss Notice
  7. 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
  8. 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. Flavelius

    Flavelius

    Joined:
    Jul 8, 2012
    Posts:
    434
    I have a case where a field for an abstract serializable class is not shown in the inspector (not serialized?) if it's nested inside another serializable class in a list. It is shown if i put it at the root level though:
    Code (CSharp):
    1.  
    2. [Serializable]
    3. public abstract class EntityBehaviourAction //has subclasses
    4. {
    5.     public virtual string DescriptiveName { get { return string.Empty;} }
    6. }
    7.  
    8. [Serializable]
    9. public class EntityBehaviourEventListener
    10. {
    11.     public EntityEvent Event; //EntityEvent ist a regular ScriptableObject
    12.     public EntityBehaviourAction Action;
    13. }
    14.  
    15. public class EntityBehaviour : SerializedScriptableObject
    16. {
    17.     [SerializeField] List<EntityBehaviourEventListener> eventListeners; //does not display the Action fields
    18.     [SerializeField] EntityBehaviourAction test; //shows the dropdown/picker as expected
    19. }
    20.  
    Edit: I discovered that when i marked the list with [OdinSerialize], it did work. But that feels strange when i already inherited from SerializedScriptableObject (which i expected to do this implicitly).
     
    Last edited: Dec 6, 2017
  2. Froghuto

    Froghuto

    Joined:
    Oct 4, 2012
    Posts:
    43
    Is it possible to change the title text of a BoxGroup to be bold?
     
  3. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    167
    We did it the way we did in order to optimize performance, and in order to retain backwards compatibility. If you add Odin serialization to a component you've already used for a while, nothing actually changes in the data that Unity is already serializing for you. Odin only supplements with extra stuff that Unity wouldn't touch anyways. In this way, we both get better performance, and more reliability and backwards compatibility. This, however, comes at the cost of being a little confusing.

    We're thinking of how best to deal with this UX issue of people getting confused, as it's happening a lot. We will institute some changes to make it more intuitive or obvious what's going on, in the future, and probably also allow people to annotate their classes in a way such that everything is serialized by Odin by default.

    This is intended behaviour, though I can see why you might find it confusing. See my answer to the above quote, as well as this FAQ answer, for more info as to why things are like this.

    There is currently no "straight-forward" way of doing this, but you could hack it in doing something like this, based on this old suggestion on our issue tracker:

    Code (CSHARP):
    1. public class MyComponent : MonoBehaviour
    2. {
    3.     [BoxGroup]
    4.     [OnInspectorGUI("DrawBoldedHeader", append: false)]
    5.     public int A;
    6.  
    7.     [BoxGroup]
    8.     public int B;
    9.  
    10. #if UNITY_EDITOR
    11.     private void DrawBoldedHeader()
    12.     {
    13.         SirenixEditorGUI.BeginBoxHeader();
    14.         GUIHelper.PushIsBoldLabel(true);
    15.         GUILayout.Label("My Box Header");
    16.         GUIHelper.PopIsBoldLabel();
    17.         SirenixEditorGUI.EndBoxHeader();
    18.     }
    19. #endif
    20. }
     
    tyapichu and Froghuto like this.
  4. Nexuachip

    Nexuachip

    Joined:
    Oct 10, 2016
    Posts:
    1
    Hello, i have problem with drawing custom drawer. When using it in the ScriptableObject inspector is updated and values are updated too, but when closing then opening unity values reset.
    I tried to use it in the scene and it works perfectly fine in the scene. I also tried to use
    entry.ApplyChanges();
    entry.Update();
    I also tried disableing Odin Custom Drawer code completely, and my property serialized and displayed correctly using unity default inspector. After changing values in this state i enabled Odin Custom Drawer code and after reopening Unity values started to reset to this state.
    I am using Odin In Editor only mode
    The problem only occurs after closing then opening Unity

    My classes are all marked [Serializable], and variables that need serializing and are not public are marked [SerializeField]

    Code (CSharp):
    1.  
    2. [OdinDrawer]
    3.     public class RangeFloatModifiableDrawer : OdinValueDrawer<RangeFloatModifiable>
    4.     {
    5.         protected override void DrawPropertyLayout(IPropertyValueEntry<RangeFloatModifiable> entry, GUIContent label)
    6.         {
    7.             var children = entry.Property.Children;
    8.             var target = entry.SmartValue;
    9.             var rect = EditorGUILayout.GetControlRect();
    10.  
    11.             // In Odin, labels are optional and can be null, so we have to account for that.
    12.             if (label != null)
    13.             {
    14.                 rect = EditorGUI.PrefixLabel(rect, label);
    15.             }
    16.  
    17.             var prev = EditorGUIUtility.labelWidth;
    18.             EditorGUIUtility.labelWidth = 20;
    19.             var leftRect = rect.AlignLeft(rect.width * 0.5f);
    20.             {
    21.                 EditorGUI.LabelField(leftRect.AlignLeft(leftRect.width * 0.5f), "Min");
    22.                 target._value.min = EditorGUI.FloatField(leftRect.AlignRight(leftRect.width * 0.5f),target._value.min);
    23.             }
    24.             var rightRect = rect.AlignRight(rect.width * 0.5f);
    25.             {
    26.                 EditorGUI.LabelField(rightRect.AlignLeft(rightRect.width * 0.5f), "Max");
    27.  
    28.                 target._value.max = EditorGUI.FloatField(rightRect.AlignRight(rightRect.width * 0.5f),target._value.max);
    29.  
    30.             }
    31.             EditorGUIUtility.labelWidth = prev;
    32.             entry.SmartValue = target;
    33.         }
    34.     }
    By the way, Odin is the my most favorite and best asset i have ever purchased, thank you very much for this great tool.
     
  5. Saucyminator

    Saucyminator

    Joined:
    Nov 23, 2015
    Posts:
    12
    Hi, I'm trying to make ToggleGroup appear inside of a TabGroup, but it's not working and the properties ends up below the TabGroup.

    Here's my code I have trouble with:

    Code (CSharp):
    1.   [TabGroup("Testing")] [ToggleGroup("useKickback")] public bool useKickback;
    2.   [TabGroup("Testing")] [ToggleGroup("useKickback")] public float kickback = 0f;
    I've looked at your example scenes... The Toggle attribute would probably work for my case but it seems to only work when referencing another script's member.
     
  6. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    167
    Your code would only work in the case that RangeFloatModifiable is a struct. If it's a reference type, you're repeatedly setting the same reference to entry.SmartValue, and it can't detect any changes, because you've only changed the values within the reference. What you should do in this sort of case is, if you change anything in your reference type object, you should call entry.Values.ForceMarkDirty() - that way, the fact that something has changed will be registered, and the ScriptableObject will be marked dirty by Odin, and Unity will know to save any changes made to it.

    Hope that helps!
     
    Nexuachip likes this.
  7. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    167
    What you should do is use group paths, like so:

    Code (CSHARP):
    1. [TabGroup("MyTabGroup", "Testing")] [ToggleGroup("MyTabGroup/Testing/useKickback")] public bool useKickback;[TabGroup("MyTabGroup", "Testing")] [ToggleGroup("MyTabGroup/Testing/useKickback")] public float kickback = 0f;
    Note that tab groups have a special path behaviour, that of "TabGroupName/TabName". If you only pass one parameter (the tab parameter) to the TabGroup attribute, it will use a default tab group name of "_DefaultTabGroup", so in your case the path to place something in your tab would then be "_DefaultTabGroup/Testing".
     
  8. Saucyminator

    Saucyminator

    Joined:
    Nov 23, 2015
    Posts:
    12
    Aha I see, awesome! Thanks! There's so much to learn about Odin, money well spent! :)

    Another question: Is it possible to Show/Hide field based on an enum value? I have a workaround (it's not pretty). Might as well ask if there is functionality for this.

    Workaround:
    Code (CSharp):
    1.   public AmmunitionType ammoType;
    2.   [ShowIf("guiAmmoTypeArrow")] public ArrowType arrowType;
    3.   [ShowIf("guiAmmoTypeBullet")] public BulletType bulletType;
    4.  
    5.   private bool guiAmmoTypeArrow;
    6.   private bool guiAmmoTypeBullet;
    7.  
    8.   void OnValidate () {
    9.     switch (ammoType) {
    10.       case AmmunitionType.Arrow:
    11.         guiAmmoTypeArrow = true;
    12.         guiAmmoTypeBullet = false;
    13.         break;
    14.       case AmmunitionType.Bullet:
    15.         guiAmmoTypeArrow = false;
    16.         guiAmmoTypeBullet = true;
    17.         break;
    18.       default:
    19.         guiAmmoTypeArrow = false;
    20.         guiAmmoTypeBullet = false;
    21.         break;
    22.     }
    23.   }
     
  9. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    167
    Simply write this:

    Code (CSHARP):
    1. public AmmunitionType ammoType;
    2. [ShowIf("ammoType", AmmunitionType.Arrow)] public ArrowType arrowType;
    3. [ShowIf("ammoType", AmmunitionType.Bullet)] public BulletType bulletType;
     
  10. dearamy

    dearamy

    Joined:
    Mar 17, 2015
    Posts:
    67
    I'm having trouble using [ValueDropdown]
    Code (CSharp):
    1.     [System.Serializable] public class Config {
    2.             [ValueDropdown("friendlyTextureSizes")]
    3.             public int[] FriendlyTextureSize;
    4.             public GameObject[] AvailablePrefabs;
    5.             static ValueDropdownList<int[]> friendlyTextureSizes = new ValueDropdownList<int[]>() {
    6.                 { "Small",new int[]{ 256, 2 } },
    7.                 { "Medium", new int[]{ 252, 2 } },
    8.                 { "Large",new int[]{ 1024, 2 } },
    9.             };
    10.         }
    11.  
    12.         public Config[] configs;
    13.  
    And the inspector looks weird and there's an error.
    What's more, the drop-down value can't be saved.
    OdinError.png
     
  11. Saucyminator

    Saucyminator

    Joined:
    Nov 23, 2015
    Posts:
    12
    Amazing. Thank you for all your hard work on this great plugin!
     
  12. Tracecat

    Tracecat

    Joined:
    Mar 20, 2014
    Posts:
    3
    upload_2017-12-12_12-53-52.png

    Is there a way to activate inline editors for multi object editing?
     
  13. tyapichu

    tyapichu

    Joined:
    Aug 11, 2013
    Posts:
    8
    Can I somhow hide TableLists Add button? As i understood [ListDrawerSettings(HideAddButton = true)] wirks only with basic list view.
     
  14. Jodwig

    Jodwig

    Joined:
    Feb 23, 2014
    Posts:
    4
    Hiya, really loving the asset so far.

    Got a question/suggestion - is it possible to "sort" all components in the inspector in a specific order? For example, I have hundreds of objects and they have like 20 components each, and I want to have rigidbodies always on the very top, then colliders, then script with creature stats and so on. Doing it all manually would take me ages, so I wonder if it is possible (or would it be possible to add it in the future) with this asset to create such a list and put some components in desired order in there to force inspector to sort them this way?

    Best Regards.
     
  15. lanrosta

    lanrosta

    Joined:
    Oct 11, 2014
    Posts:
    23
    I can't find any information in this forum or any of the documents. Maybe it's a simple and dumb question, but how do I retrieve a value from a specific row and column (by id or name) field using the Table List Example so I can display this in the Scene UI (using a Canvas and UI Text field)? I know how to do this with native strings and such, but how do I do it with an Odin Table List? I do not see any questions regarding using Odin inspector data inside actual Scene UI's?
     
  16. lanrosta

    lanrosta

    Joined:
    Oct 11, 2014
    Posts:
    23
    EDIT- I answered this one myself. Turns out I just needed to learn more about how Lists and Dictionaries work in Unity...
    https://unity3d.com/learn/tutorials/modules/intermediate/scripting/lists-and-dictionaries
     
    Tor-Vestergaard likes this.
  17. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    167
    There are a few issues with value dropdowns and reference types - upon deserialization, the references in the dropdown will become different than the references, and we have no way of knowing which reference the value corresponds to. For now, we advise only using dropdowns of value types, and reference types that implement the IEquatable interface with themselves. We have improvements upcoming in the next patch, which improve how it's handled, and give error messages if issues like this would happen.

    I'm afraid this isn't a thing you can do for now.

    Right now customization options for the TableList drawer are very limited. We're going to be improving this in the future, but for now, it's not nearly as flexible as the basic list drawer.

    This is probably possible somehow, but isn't really in the scope of Odin. I'd advise you to research Unity's editor API yourself or search Unity answers, and try to figure out how it might be done that way.
     
  18. djfrail

    djfrail

    Joined:
    Jan 16, 2014
    Posts:
    111
    Got a question - the TableMatrix attribute draws a 2d array with row 0 drawn at the top and then draw rows 1,2, ... under that.

    Say you've got a 2d array like gameObjects[5,20]. Is there a way to have it draw row 19 on top, then draw row 18,17, ... under each other? Put another way, can you draw the 2d array flipped vertically?

    Thanks.
     
  19. Brogan89

    Brogan89

    Joined:
    Jul 10, 2014
    Posts:
    64
    Hi, I'm getting some really bad performance in editor with a script I'm using in editor. I didn't think it was an Odin issue because I'm only using the `ReadOnly` attribute and removing all of them didn't help my performance. However, after doing some deep profiling I have noticed that `OdinEditor.OnInspectorGUI()` is within the pipeline. I don't know anything passed this point. It was really hard to get even to this point, having Unity crash because of too much memory use (~13-14GB). I really don't know how I can get any further with this issue.

    Here's my profiler snapshot. Editor Profiler (Deep-2).PNG

    Any help would be much appreciated.


    EDIT: ok, strange situation, it wasn't Odin at all as I expected, It had something to do with the Nested Prefab asset we're using. Reassign the prefab fixed the issue.
     
    Last edited: Dec 18, 2017
  20. CaptainRedmuff

    CaptainRedmuff

    Joined:
    Nov 17, 2015
    Posts:
    1
    Hi,

    Odin is truly fantastic. It has completely changed my workflow and reinvigorated my interest in making editor tools. Many thanks for that! :]

    I have been porting over my UnityEditor inspectors to OdinEditor and wanted to leverage some of the swish drawers like those for Mesh-es and Materials.

    Is it possible to draw these inline, when overriding OnInspectorGUI? I have managed so far by muddling through the documentation (which appears to be broken as the drop down menus do not expand/contract).

    Code (CSharp):
    1.  
    2. public override void OnInspectorGUI() {
    3.  
    4.             DrawNodeGUI();
    5.  
    6.             DrawMeshGUI();
    7.  
    8.            //other stuff
    9. }
    10.  
    11. void DrawMeshGUI() {
    12.  
    13.             SirenixEditorGUI.BeginBox();
    14.  
    15.             SirenixEditorGUI.BeginBoxHeader();
    16.  
    17.             foldouts.mesh = SirenixEditorGUI.Foldout(foldouts.mesh, "Mesh");
    18.  
    19.             SirenixEditorGUI.EndBoxHeader();
    20.  
    21.             if(foldouts.mesh && node != null) {
    22.  
    23.                 Mesh mesh = grid.chunkRenderer.nodeRenderer.Render(node);
    24.  
    25.                 //which control do I use to draw the mesh?
    26.             }
    27.  
    28.             SirenixEditorGUI.EndBox();
    29.         }
    30.  
    I do not want to use the attributes/decorators for properties as I want to draw some fairly specific custom GUI. Are there specific Sirenix methods available to do this programmatically?
     
    Last edited: Dec 18, 2017
  21. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    167
    I'm afraid you can't do this right now, but it's on our todo list to add options for rearranging the axes and doing things like transposing the visuals of drawn 2D arrays.

    Ah, that makes sense. When looking at it, the location of the lost performance seemed rather absurd, to be frank - it's a string.EndsWith comparison that is run once per prefab modification on the object in question, on the path of the modification. For it to take so long and be an actual performance hog, is rather unusual to say the least, as that indicates that there would be an utterly stupendous number of prefab modifications on the object in question.

    An issue with Nested Prefabs might very well cause that, though, for all I know - so that makes sense. I'm happy to hear the issue was resolved!

    If you wish to use Odin's more advanced drawing capabilities to draw things, you must use Odin's own property system, easily accessible through deriving from the OdinEditor rather than Editor class when making your custom editor.

    However, I should note that inline editors (IE drawing a mesh preview, for example) are handled by the InlineEditorAttribute drawer and require quite a lot of wrapping code - so you'll need to put an InlineEditor attribute on the field in question to get that particular thing drawn. It's not the kind of thing you can just make a static "DrawInlineEditorFor(UnityEngine.Object object)" method for.

    Another option you have is opening the provided Odin source code, finding the InlineEditorAttributeDrawer.cs file, and copying all that it does in order to draw an inline editor correctly into your own custom editor code.
     
    Brogan89 and CaptainRedmuff like this.
  22. tyapichu

    tyapichu

    Joined:
    Aug 11, 2013
    Posts:
    8
    Not sure if i should ask for such help... you wrote about Odin's own property system. I'm using QuickSheet plugin to import config data form google sheets. it's free, it works, but it has one problem (for me). QuickSheet allows to import array of enum values as flags enum. but it uses SerializedProperty to draw data in ScriptableObjects custom editor and SerializedProperty doesn't know how to handle whith multivalue flags enum. it trys to use enumValueIndex to show values and mask, but enumValueIndex returns the sequence number of the value. and in case of multivalue enum enumValueIndex returns out of range -1. may be i can change unity SerializedProperty to Odin property system and Odin will draw enum correctly? But I don't know where to start...
     
  23. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    167
    This certainly sounds possible - you can use PropertyTree.Create() to create an Odin PropertyTree for a given set of target objects. You can then use the PropertyTree to query and draw your data, using for example tree.Draw(), or by doing it more manually as in this FAQ example.
     
    tyapichu likes this.
  24. tyapichu

    tyapichu

    Joined:
    Aug 11, 2013
    Posts:
    8
    thats awesome! original plugin had 190 lines of code which parsed property to draw in inspector and i've changed it by 10 lines from manual and it works and looks even better. thank you.
     
    bjarkeck likes this.
  25. DanW

    DanW

    Joined:
    Nov 4, 2013
    Posts:
    7
    Apologies if this has been asked and answered but, I didn't see it yet.
    In Editor Only Mode ( UPW app) if I have a MonoBehavior with a field that is an inherited type from a interface or abstract class, can I visualize it?
    Example:
    public interface IMyInterface
    {
    public string A {get; set;}
    }

    public class MyDerivedClass : IMyInterface
    {
    public string A {get; set;}
    public string NotInInterface {get; set;}
    }

    public class MyBehavior : MonoBehavior
    {
    public IMyInterface C; (assume this is set to a new instance of MyDerivedClass)
    }

    When inspecting MyBehavior, will I see the A and NotInInterface values? What attributes would be needed?

    Same question but change the interface to an abstract class.

    Thanks!
    Dan
     
    Last edited: Dec 19, 2017
  26. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    167
    You can use [ShowInInspector] to force anything to be shown in the inspector by Odin. Just note that it won't be serialized by Odin, and thus the shown values will be reset whenever there is a reload.
     
    DanW likes this.
  27. DanW

    DanW

    Joined:
    Nov 4, 2013
    Posts:
    7
    Awesome! Since I'd be in Editor Only Mode I would not expect serialization to occur. I just want to see the damn things :) Thanks for the response.
     
    bjarkeck likes this.
  28. doq

    doq

    Joined:
    Aug 17, 2015
    Posts:
    113
    I want to use SuffixLabel to display a dynamic value, but it only takes strings. Is there an easy way to display non-string values (int, bool, Vector3, etc). I was trying to use the dynamic $ operator on a function, but is there a way to pass a value to the function?

    For example:
    Code (CSharp):
    1. [SuffixLabel("$FromInt('EntitiesUsed')"]
    2. public int EntitiesSize = 1;
    3. private int EntitiesUsed = 0;
    4.  
    5. string FromInt(int value) { return value.ToString(); }
    Ideally I could just pass "$EntitiesUsed" into SuffixLabel.
     
    Last edited: Dec 22, 2017
  29. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    167
    I'm afraid there's no way to do that, no. The closest you can get is just reading the field value directly in your method, and treat it as an argument - or call another method with that value as an argument.

    And you should just be able to use $EntitiesUsed - if you can't, that should be a bug,
     
  30. doq

    doq

    Joined:
    Aug 17, 2015
    Posts:
    113
    At first, I tried $EntitiesUsed and ERROR was displayed in place of the value. That's why I was trying out a function instead. So I guess that's a bug.

    Edit: FYI, I ended up creating a custom OdinEditor to get around this issue. It's kind of over-engineering, but it's an elegant workaround.
     
    Last edited: Dec 25, 2017
  31. Harekelas

    Harekelas

    Joined:
    Feb 3, 2015
    Posts:
    562
    Hi there,
    I'm using odin in my project and it can create fantastic interface.
    But I also have some problems with it:
    1. it can be very laggy if the content is many. I used odin to draw all my main player's data and status into the inspector, and every time I click on the main player, unity editor will freeze 1~2 seconds to draw all the contents for me, any optimization options or plans?
    2. This one is related to the one up there, odin converts all component's public variables into odin's drawing. But this sometimes can be very tedious: like the morph character system(MCS) model, on it's hit bone there is a list of blend shape bones and it has over a thousand elements inside it, and odin tries to draw it.
    Every time I click on the hip bone by mistake, the editor will freeze for 10 minutes to show it in inspector, then the delta time of unity editor becomes tens of seconds, all I can do is to force quit unity and try not to click on anything that contains long lists.
    Any suggestions?
    Thanks!
     
  32. zaidikhlas

    zaidikhlas

    Joined:
    Jan 4, 2017
    Posts:
    3
    Hey is there anyway I could reverse the order of the list view? For example, if a list has 10 items; I would like to draw the 10th item first instead of the 1st item. Any leads?
    Thanks!
     
  33. benzsuankularb

    benzsuankularb

    Joined:
    Apr 10, 2013
    Posts:
    120
    @Tor-Vestergaard
    I'm doing CI.
    How can I scan an generate AOT programatically.
     
  34. Laicasaane

    Laicasaane

    Joined:
    Apr 15, 2015
    Posts:
    21
    Hi,
    I want to use Odin's "Editor Only" mode and GameObject's "EditorOnly" tag together without showing the error notification. Is there anyway to do that in the current version?

    upload_2018-1-6_19-14-13.png
     
  35. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    211
    Not in the current version sadly, but I've added it to our todo. It's a good option to have. We didn't add an option to disable the message, as we would fear that people would just disable it, and make mistakes. But an option to disable it on editor only objects makes a lot of sense.

    For now, you could easily make your own SerializedEditorMonoBehaviour that doesn't have this error message:

    Code (CSharp):
    1.  
    2.     [ShowOdinSerializedPropertiesInInspector]
    3.     public abstract class SerializedEditorMonoBehaviour : MonoBehaviour, ISerializationCallbackReceiver, ISupportsPrefabSerialization
    4.     {
    5.         [SerializeField, HideInInspector]
    6.         private SerializationData serializationData;
    7.  
    8.         SerializationData ISupportsPrefabSerialization.SerializationData { get { return this.serializationData; } set { this.serializationData = value; } }
    9.  
    10.         void ISerializationCallbackReceiver.OnAfterDeserialize()
    11.         {
    12.             UnitySerializationUtility.DeserializeUnityObject(this, ref this.serializationData);
    13.             this.OnAfterDeserialize();
    14.         }
    15.  
    16.         void ISerializationCallbackReceiver.OnBeforeSerialize()
    17.         {
    18.             UnitySerializationUtility.SerializeUnityObject(this, ref this.serializationData);
    19.             this.OnBeforeSerialize();
    20.         }
    21.  
    22.         protected virtual void OnAfterDeserialize()
    23.         {
    24.         }
    25.  
    26.         protected virtual void OnBeforeSerialize()
    27.         {
    28.         }
    29.     }
    Not sure it would need to support prefab modifications, but you can just remove that interface. There is more info on this in our manual :)
     
    Laicasaane likes this.
  36. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    211
    Yeah, we are aware of the performance problems with Odin inspecting objects with a lot of data. But we are working on it! In our property-rework branch, we are inspecting objects that contain lists with 500.000 elements and it runs buttery smooth, the only thing slowing it down is Unity that really wants really to serialize everything each frame in the inspector.

    For now, your best bet is to disable Odin for those types that give your trouble. More information on that here: http://www.sirenix.net/odininspector/faq/38/how-will-odin-affect-performance-in-the-inspector
     
    Harekelas likes this.
  37. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    211
    You could sort the list with a button :) You could even put that button the list itself like so:
    http://sirenix.net/odininspector/documentation/sirenix/odininspector/listdrawersettingsattribute
    Or maybe with a custom context menu: http://sirenix.net/odininspector/documentation/sirenix/odininspector/customcontextmenuattribute
     
  38. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    211
    Code (CSharp):
    1. AOTGenerationConfig.Instance.ScanProject();
    2. AOTGenerationConfig.Instance.GenerateDLL();
     
    benzsuankularb likes this.
  39. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    211
    It's probably because what you referenced was not a string. In the next patch, you can reference anything and it will just ToString that.
     
    doq likes this.
  40. Dennin-Dalke

    Dennin-Dalke

    Joined:
    Aug 10, 2014
    Posts:
    22
    Hi,

    I had a plugin were I display the inspector window inside a Custom Editor Window, everything works fine using the default `Editor.CreateEditor(...)` method without Odin, but when I have an editor that uses any Odin Inspector features I end with this error:

    Code (CSharp):
    1. ArgumentException: GUILayout: Mismatched LayoutGroup.MouseEnterWindow
    2. UnityEngine.GUILayoutUtility.BeginLayoutGroup (UnityEngine.GUIStyle style, UnityEngine.GUILayoutOption[] options, System.Type layoutType) (at C:/buildslave/unity/build/Runtime/IMGUI/Managed/GUILayoutUtility.cs:301)
    3. UnityEngine.GUILayout.BeginHorizontal (UnityEngine.GUIContent content, UnityEngine.GUIStyle style, UnityEngine.GUILayoutOption[] options) (at C:/buildslave/unity/build/Runtime/IMGUI/Managed/GUILayout.cs:306)
    4. UnityEngine.GUILayout.BeginHorizontal (UnityEngine.GUIStyle style, UnityEngine.GUILayoutOption[] options) (at C:/buildslave/unity/build/Runtime/IMGUI/Managed/GUILayout.cs:296)
    5. Sirenix.Utilities.Editor.SirenixEditorGUI.BeginIndentedVertical (UnityEngine.GUIStyle style, UnityEngine.GUILayoutOption[] options) (at C:/Sirenix/Sirenix Solution/Sirenix.Utilities.Editor/GUI/SirenixEditorGUI.cs:1302)
    6. Sirenix.OdinInspector.Editor.Drawers.DictionaryDrawer`3[TDictionary,TKey,TValue].DrawPropertyLayout (Sirenix.OdinInspector.Editor.IPropertyValueEntry`1[TValue] entry, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    7. Sirenix.OdinInspector.Editor.OdinValueDrawer`1[T].DrawProperty (Sirenix.OdinInspector.Editor.IPropertyValueEntry`1[TValue] entry, UnityEngine.GUIContent label) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:1065)
    8. Sirenix.OdinInspector.Editor.OdinValueDrawer`1[T].DrawPropertyImplementation (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    9. Sirenix.OdinInspector.Editor.OdinDrawer.DrawProperty (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:283)
    10. Sirenix.OdinInspector.Editor.OdinDrawer.CallNextDrawer (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    11. Sirenix.OdinInspector.Editor.Drawers.NullableReferenceDrawer`1[T].DrawPropertyLayout (Sirenix.OdinInspector.Editor.IPropertyValueEntry`1[TValue] entry, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    12. Sirenix.OdinInspector.Editor.OdinValueDrawer`1[T].DrawProperty (Sirenix.OdinInspector.Editor.IPropertyValueEntry`1[TValue] entry, UnityEngine.GUIContent label) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:1065)
    13. Sirenix.OdinInspector.Editor.OdinValueDrawer`1[T].DrawPropertyImplementation (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    14. Sirenix.OdinInspector.Editor.OdinDrawer.DrawProperty (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:283)
    15. Sirenix.OdinInspector.Editor.OdinDrawer.CallNextDrawer (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    16. Sirenix.OdinInspector.Editor.Drawers.ReferenceValueConflictDrawer`1[T].DrawPropertyLayout (Sirenix.OdinInspector.Editor.IPropertyValueEntry`1[TValue] entry, UnityEngine.GUIContent label) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/Misc Drawers/PropertyContextMenuDrawer.cs:302)
    17. Sirenix.OdinInspector.Editor.OdinValueDrawer`1[T].DrawProperty (Sirenix.OdinInspector.Editor.IPropertyValueEntry`1[TValue] entry, UnityEngine.GUIContent label) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:1065)
    18. Sirenix.OdinInspector.Editor.OdinValueDrawer`1[T].DrawPropertyImplementation (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    19. Sirenix.OdinInspector.Editor.OdinDrawer.DrawProperty (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:283)
    20. Sirenix.OdinInspector.Editor.OdinDrawer.CallNextDrawer (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    21. Sirenix.OdinInspector.Editor.Drawers.ReferencePathConflictDrawer`1[T].DrawPropertyLayout (Sirenix.OdinInspector.Editor.IPropertyValueEntry`1[TValue] entry, UnityEngine.GUIContent label) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/Misc Drawers/PropertyContextMenuDrawer.cs:249)
    22. Sirenix.OdinInspector.Editor.OdinValueDrawer`1[T].DrawProperty (Sirenix.OdinInspector.Editor.IPropertyValueEntry`1[TValue] entry, UnityEngine.GUIContent label) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:1065)
    23. Sirenix.OdinInspector.Editor.OdinValueDrawer`1[T].DrawPropertyImplementation (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    24. Sirenix.OdinInspector.Editor.OdinDrawer.DrawProperty (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:283)
    25. Sirenix.OdinInspector.Editor.OdinDrawer.CallNextDrawer (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    26. Sirenix.OdinInspector.Editor.OdinDrawer.CallNextDrawer (Sirenix.OdinInspector.Editor.IPropertyValueEntry entry, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    27. Sirenix.OdinInspector.Editor.Drawers.FixUnityNullDrawer`1[T].DrawPropertyLayout (Sirenix.OdinInspector.Editor.IPropertyValueEntry`1[TValue] entry, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    28. Sirenix.OdinInspector.Editor.OdinValueDrawer`1[T].DrawProperty (Sirenix.OdinInspector.Editor.IPropertyValueEntry`1[TValue] entry, UnityEngine.GUIContent label) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:1065)
    29. Sirenix.OdinInspector.Editor.OdinValueDrawer`1[T].DrawPropertyImplementation (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    30. Sirenix.OdinInspector.Editor.OdinDrawer.DrawProperty (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:283)
    31. Sirenix.OdinInspector.Editor.OdinDrawer.CallNextDrawer (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    32. Sirenix.OdinInspector.Editor.Drawers.ReferenceDrawer`1[T].DrawPropertyLayout (Sirenix.OdinInspector.Editor.IPropertyValueEntry`1[TValue] entry, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    33. Sirenix.OdinInspector.Editor.OdinValueDrawer`1[T].DrawProperty (Sirenix.OdinInspector.Editor.IPropertyValueEntry`1[TValue] entry, UnityEngine.GUIContent label) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:1065)
    34. Sirenix.OdinInspector.Editor.OdinValueDrawer`1[T].DrawPropertyImplementation (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    35. Sirenix.OdinInspector.Editor.OdinDrawer.DrawProperty (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:283)
    36. Sirenix.OdinInspector.Editor.OdinDrawer.CallNextDrawer (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    37. Sirenix.OdinInspector.Editor.OdinDrawer.CallNextDrawer (Sirenix.OdinInspector.Editor.IPropertyValueEntry entry, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    38. Sirenix.OdinInspector.Editor.Drawers.PropertyContextMenuDrawer`1[T].DrawPropertyLayout (Sirenix.OdinInspector.Editor.IPropertyValueEntry`1[TValue] entry, UnityEngine.GUIContent label) <0x17e87af0 + 0x000d7> in <dc3c6ee119b9421cb4cd3cb0032203ee>:0
    39. Sirenix.OdinInspector.Editor.OdinValueDrawer`1[T].DrawProperty (Sirenix.OdinInspector.Editor.IPropertyValueEntry`1[TValue] entry, UnityEngine.GUIContent label) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:1065)
    40. Sirenix.OdinInspector.Editor.OdinValueDrawer`1[T].DrawPropertyImplementation (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at <dc3c6ee119b9421cb4cd3cb0032203ee>:0)
    41. Sirenix.OdinInspector.Editor.OdinDrawer.DrawProperty (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:283)
    42. Sirenix.OdinInspector.Editor.InspectorUtilities.DrawProperty (Sirenix.OdinInspector.Editor.InspectorProperty property, UnityEngine.GUIContent label) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:601)
    43. Rethrow as OdinPropertyException: This error occurred while being drawn by Odin.
    44. Odin Property Path: _testDictionary
    45. Odin Drawer Chain: PropertyContextMenuDrawer<Dictionary<string, float>>, ReferenceDrawer<Dictionary<string, float>>, FixUnityNullDrawer<Dictionary<string, float>>, ReferencePathConflictDrawer<Dictionary<string, float>>, ReferenceValueConflictDrawer<Dictionary<string, float>>, NullableReferenceDrawer<Dictionary<string, float>>, DictionaryDrawer<Dictionary<string, float>, string, float>.
    46. UnityEngine.Debug:LogException(Exception)
    47. Sirenix.OdinInspector.Editor.InspectorUtilities:DrawProperty(InspectorProperty, GUIContent) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:601)
    48. Sirenix.OdinInspector.Editor.InspectorUtilities:DrawProperty(InspectorProperty) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:527)
    49. Sirenix.OdinInspector.Editor.InspectorUtilities:DrawPropertiesInTree(PropertyTree) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/Infos/InspectorPropertyInfo.cs:520)
    50. Sirenix.OdinInspector.Editor.PropertyTree:Draw(Boolean) (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Utilities/Persistent/PersistentContextCache.cs:182)
    51. Sirenix.OdinInspector.Editor.OdinEditor:OnInspectorGUI() (at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Misc/DrawerPriority.cs:380)
    52. CustomEditorWindow:OnGUI() (at Assets/CustomEditorWindow.cs:22)
    53. UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
    A really basic snippet that can reproduce the error:
    Code (CSharp):
    1.  
    2. using System.Linq;
    3. using UnityEngine;
    4. using UnityEditor;
    5. public class CustomEditorWindow : EditorWindow
    6. {
    7.     [MenuItem("Window/Custom Editor Window")]
    8.     public static void CreateWindow()
    9.     {
    10.         GetWindow<CustomEditorWindow>();
    11.     }
    12.     private void OnGUI()
    13.     {
    14.         var selected = Selection.activeGameObject;
    15.  
    16.         if (selected == null) return;
    17.  
    18.         var targetComp = selected.GetComponents<MonoBehaviour>().FirstOrDefault();
    19.  
    20.         if (targetComp == null) return;
    21.  
    22.         var editor = Editor.CreateEditor(targetComp);
    23.         editor.OnInspectorGUI();
    24.     }
    25. }
    26.  
    Any thoughts on how to solve this problem?
     
    Last edited: Jan 10, 2018
  41. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    211
    Code (CSharp):
    1. var editor = Editor.CreateEditor(targetComp);
    That is not supposed to be called each frame

    You need to cache the created editor instance, and then call OnInspectorGUI on that instance, otherwise, things will go crazy.

    Code (CSharp):
    1.  
    2.         if (this.someEditorInstane == null)  this.someEditorInstane = Editor.CreateEditor(targetComp);
    3.         this.someEditorInstane.OnInspectorGUI();
    4. }
    It's also a good practice to destroy it when you're done with it as well.

    In the next patch stuff like this will become super easy as you can just inherit from OdinEditorWindow and override what target or targets it should draw. If you want in on the beta, just say the word and I'll send it you, it has a lot of EditorWindow examples.

    Code (CSharp):
    1.  
    2.     public class OverrideGetTargetsExampleWindow : OdinEditorWindow
    3.     {
    4.         [MenuItem("Window/Custom Editor Window")]
    5.         private static void OpenWindow()
    6.         {
    7.             GetWindow<OverrideGetTargetsExampleWindow>();
    8.         }
    9.  
    10.         protected override object GetTarget()
    11.         {
    12.             if (Selection.activeGameObject)
    13.             {
    14.                 return Selection.activeGameObject.GetComponent<MonoBehaviour>();
    15.             }
    16.  
    17.             return null;
    18.         }
    19.     }
     
  42. Dennin-Dalke

    Dennin-Dalke

    Joined:
    Aug 10, 2014
    Posts:
    22
    Regarding the cache, definitely, this isn't the real code, it's just a snippet to reproduce the exception.

    I would love to test the beta and probably will be really useful for what I'm trying to achieve.

    Thanks!
     
    bjarkeck likes this.
  43. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    211
    Right, but that code works fine if the editor instance is cashed. So if that was not the issue, then it doesn't reproduce the actual problem. At least on my end.
     
  44. Dennin-Dalke

    Dennin-Dalke

    Joined:
    Aug 10, 2014
    Posts:
    22
    Actually extending from OdinEditorWindow did the job! Thanks!
     
    bjarkeck likes this.
  45. Skendar

    Skendar

    Joined:
    Apr 4, 2016
    Posts:
    2
    It is possible to use a method that return a variable as a read-only field? (And not as a button) for something like this:

    Code (CSharp):
    1. public float myFloat()
    2. { return floatA+floatB;}
     
  46. Dennin-Dalke

    Dennin-Dalke

    Joined:
    Aug 10, 2014
    Posts:
    22
    Hi @bjarkeck another question, I'm trying to customize the header of a list item, as you can see in the following image, where there's an "InteractionDefinition" field.

    I've accomplished that, where you can see the "Is Active", by using a 'ListDrawerSettings(OnEndListElementGUI(...))' attribute and drawing the elements over the previous header. This isn't elegant and doesn't work exactly the way I'd like because it still allows you to open the Object Picker and I'm willing to have a TextArea in the header, which I can't because the Object Field hijacks the mouse events...
    Custom Polymorphic Header.png

    So, the question is: is there a proper way of doing this?

    I've tried to create a NullableReferenceDrawerOverride since it's the NullableReferenceDrawer from OdinInspector that creates the ObjectField, but when I do this, I end with double drawers:
    Custom Polymorphic Header - Override.png
    I'm missing something, not sure if I shouldn't call the next drawer or whether there's no built-in way to support this currently.

    Any thoughts on this would be great! Thanks!
     
  47. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    211
    It sounds like you're looking for HideReferenceObjectPicker attribute, try that on the list. You can still modify the polymorphic type by right-clicking.
     
  48. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    211
    Would this do?

    Code (CSharp):
    1. [ShowInInspector]
    2. public float myFloat { get { return floatA+floatB;} }
     
  49. Skendar

    Skendar

    Joined:
    Apr 4, 2016
    Posts:
    2
    It does, damn, sometimes I feel stupid. Well, I will one day become decent in coding...probably.
     
  50. Shadowing

    Shadowing

    Joined:
    Jan 29, 2015
    Posts:
    721
    I'm really having a hard time learning using the online documentation. Cause its just a huge list of stuff to look though.
    Really needs another organization idea.
    The new editor tools are awesome. Really happy about it.

    I was able to create a window and add button and inputfield by looking at your example scripts.
    I ran into a snag though.

    I use BestHTTP to do web requests and was wanting to use it with Odin.
    https://assetstore.unity.com/packages/tools/network/best-http-pro-edition-10872

    My csharp knowledge is intermediate.
    how do I add BestHTTP Directive so I can use it.
    Or do I need to create a mono class on this script and if so how do I use a function from inside OdinEditorWindow class.

    Also another question is that. is OnValueChanged the only way to add a Inputfield? I'm not needing a on value changed event.

    Code (csharp):
    1.  
    2. namespace Sirenix.OdinInspector.Demos
    3. {
    4.     using UnityEditor;
    5.     using Sirenix.OdinInspector.Editor;
    6.     using Sirenix.OdinInspector;
    7.     using UnityEngine;
    8.     using Sirenix.Utilities.Editor;
    9.     using Sirenix.Utilities;
    10.     using SimpleJSON;
    11.     using BestHTTP;
    12.     using System;
    13.     public class QuestCreator : OdinEditorWindow
    14.     {
    15.         [MenuItem("Game Tools/Quest Creator")]
    16.         private static void OpenWindow(){
    17.             var window = GetWindow<QuestCreator>();
    18.             window.position = GUIHelper.GetEditorWindowRect().AlignCenter(500, 500);
    19.         }
    20.         [OnValueChanged("QuestNameCallBack")]
    21.         public string QuestName;
    22.         private void QuestNameCallBack(){
    23.         }
    24.         [Button(ButtonSizes.Large), GUIColor(0, 1, 0)]
    25.         public void CreateQuest(){
    26.         }
    27.     }
    28. }
    29.  
    30.  
    31.