Thanks so much!
We just submitted version 1.0.0.3 Odin yesterday - awaiting Unity approval right now.
Here’s what has changed. Keep the feedback coming, as we continue improving Odin
Highlights
- HorizontalGroup attribute has been added. Checkout it out in the updated demo scene.
- Odin now works in the latest Unity 2017 beta version.
- Assembly documentation xml files are now included in the package. This means the api documentation now will show up in the IntelliSense.
- Odin now works much better with external plugins. It now handles duplicate type name conflicts during editor generation far more gracefully, giving detailed warning messages (which can be disabled), and automatically disabling editor generation for the types in question to fix the error.
Fixes
- Fixed an error where private members in base-classes would by be found by attributes such as ShowIf and HideIf.
- Fixed various errors that broke everything in the 2017.1 beta. NOTE: To fix errors in the 2017.1 beta, a feature has been disabled since an error was introduced by Unity that prevents it from working. The feature in question is drawing custom Unity Property Drawers for data which is not serialized by Unity. If an attribute seems to have no effect in 2017.1, it is likely because it was implemented by a custom Unity Property Drawer and the data is not being serialized by Unity.
- Fixed a bug where you couldn’t put several [CustomContextMenu] on a property and have them all show up in the context menu.
- The Header and Title attributes are now part of the super drawer queue, which means they no will longer be indented by the attribute as originally intended.
- Fixed a lot of spacing inconsistencies between GUI Elements.
- Fixed a bug where the ValidateInput attribute would break if the type was changed.
- Fixed a bug where set-to-null did not work on Nullable types.
- The Space attribute will no longer be applied to List elements.
- Fixed a bug where GUILayoutOptions.MaxWidth() specified the width instead of the MaxWidth.
- Fixed TabGroup GUI popping issues.
- Fixed an issue where EnumDrawer would not apply changes to the property.
Changes
- Build serialization format can now only be set to data formats valid in builds.
- Whether or not a property tree should draw the mono-script object field at the top, can now be specified via the new myPropertyTree.DrawMonoScriptObjectField property.
Upgrade Notes
- Delete Sirenix/Odin Inspector/Demo folder
- Import new package.
- Delete Sirenix/Assemblies/Editor/GeneratedOdinEditors.dll after upgrading, which will cause it to regenerate an updated version of itself if you have this behaviour enabled. The old .dll may cause a multitude of Mono.Cecil type lookup errors to be generated in the console. (These messages are harmless, but annoying.)
I may have found a slight bug? Or maybe it’s WAD or I’m doing something wrong, I dunno.
[ShowOdinSerializedPropertiesInInspector]
public abstract class MyMonoBehaviour : SerializedMonoBehaviour { }
public class SomethingStrange : MyMonoBehaviour { }
I have an empty scene, nothing but the Main Camera and the GameObject containing the SomethingStrange component. It seems that if the scene is playing and I hit stop while having SomethingStrange selected and visible in the inspector, it sets the scene to dirty, as if it needs saving. It does this even if I save right before hitting play.
That is something strange indeed! And it seems that:
public class SomethingStrange : SerializedMonoBehaviour
{
}
Actually is enough to trigger it. I’m looking in to it.
As a side note [ShowOdinSerializedPropertiesInInspector] is actually only needed if you are not inheriting SerializedMonoBehaviour but you want Odin to act as if you where. And remember, you only need to inherit from SerializedMonoBehaviour if you want to serialize stuff that otherwise would not be serialized by Unity
If I make a custom editor on top of an object that has Odin attributes such as [Readonly] and then in the editor I use
DrawDefaultInspector() then any Odin attributes will not render at all the way they are supposed to, for instance the readonly attributes will not be read only.
Is there a way to retain them while still having a custom editor?
I need the custom editor because I need to call some editor windows that aren’t available in non-editor scripts, so I’m forced to make buttons for them in custom editors.
A quick heads up for anybody who installed the latest patch (1.0.0.3).
A bug was accidentally introduced in this patch, which causes public members marked with [NonSerialized] to show up in the inspector. This is particularly visible on asset lists, which show a lot of properties which were previously hidden. A patch with a fix for this has already been submitted and is undergoing approval.
Meanwhile, while the bug may be annoying, it is entirely harmless. Remember, if any of your members show up despite being marked as [NonSerialized], you can make sure it is hidden by decorating it with the [HideInInspector] attribute.
Note that this only affects what is shown in the inspector, not what is actually serialized.
You can derive your custom editor from the OdinEditor class, override OnInspectorGUI, and then to draw the “default” Odin editor, call base.OnInspectorGUI().
Thank you, That did the trick!
I hope the documentation gets completed soon, there’s so much that can be done but I have no idea that can be done yet.
Hello. I submitted an email but figured I would post here as well for extra viability. I have found 2 issues myself.
I am currently running unity 5.6.0f3 and this can be replicated by just importing Odin into a new, blank project.
Issue 1: Trying to open the About Unity page under the help menu cause a lot of errors and the screen is just black. Image below.
Issue 2: Several of the list manipulation button icons stop drawing when you change scenes. I was viewing your own demo scenes that come with the project. When I open Unity, it appears there is no issue when looking at a list in one of your scenes. All icons are present on the buttons. But if you switch scenes, and look at an inspector list, you will notice icons are missing. And if you switch scenes again, more icons go missing. Only way to get them to show again is restart unity. Image below.
Other than those issues things are looking great.
We’ve just committed fixes to both of these issues to our repository - they will make it into the patch after 1.0.0.3a.
No problem! And yes, we definitely do need to finish that documentation. However, for now we’ve chosen to prioritize bug-fixing, until we have a proper handle on all that. Luckily, it seems we’re getting there, so hopefully we can continue work on the documentation very soon.
We just bought Odin and it’s really great! But I think we found a bug.
We generate assets (Meshes etc) and put them into SerializableObject’s with AssetDatabase.AddObjectToAsset(). We then put references to those assets into “[SerializeField] private” fields inside that SerializableObject. When viewing those SerializableObjects in the Inspector with Odin enabled the references to those local assets get lost. When disabling Odin editor for that specific type (so using native Unity Inspector) the references are saved and preserved.
Thanks for the report - we’re looking into it!
So I’ve been trying to replicate this in 5.3.0 and 5.6.1, and so far I haven’t been able to make it break.
This is my testing code:
using Sirenix.OdinInspector;
using System.Linq;
using UnityEditor;
using UnityEngine;
[CreateAssetMenu(fileName = "Test", menuName = "Test/Create", order = -10000)]
public class NewScriptableObject : SerializedScriptableObject // Also tried with just deriving from ScriptableObject, it made no difference
{
[SerializeField]
private Mesh testMesh;
[SerializeField]
private Mesh[] allMeshes;
[Button]
private void CreateSubAsset()
{
this.allMeshes = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(this)).OfType<Mesh>().ToArray();
Mesh mesh = new Mesh();
mesh.name = "TestMesh_" + this.allMeshes.Length;
mesh.vertices = new Vector3[]
{
Vector3.up,
Vector3.left + Vector3.up,
Vector3.left,
Vector3.zero,
};
mesh.triangles = new int[]
{
0, 1, 3,
1, 2, 3,
};
mesh.RecalculateNormals();
mesh.UploadMeshData(false);
AssetDatabase.AddObjectToAsset(mesh, this);
this.testMesh = mesh;
}
}
And this is the result:
I’ve tried reloading the project, moving the asset around, messing with the values. So far, nothing I’ve done has broken any of the mesh references. Can you perchance post (or PM) me the code that has the issue, or tell me whether my test code above is insufficient?
Now that I looked at it it seems that it works for meshes, but other assets (I tried Materials and Texture2Ds) don’t.
Sorry for my bad reporting skills
That did it! I managed to replicate this issue, and a fix is making it into the next patch, 1.0.1. I’ll PM you a link to a temporary build with a lot of the latest fixes, since asset store approval takes a while to come through.
Thanks for the super fast support!
I’ll just leave my wishlist for future features here…
- More / any types for Dictionary keys
- Copy&Paste values in Inspector windows using a hotkey and drag&drop
anyone know it ?
Serialization happens when a prefab is instantiated, and deserialization happens when an object is loaded (IE, when a scene or resource asset is loaded) or a prefab is instantiated. So it is at these times that reflection is used by Odin on mobile, for objects that are derived from SerializedMonoBehaviour, SerializedScriptableObject, etc.
Nothing happens in Awake, Start, or other such methods - Odin uses the ISerializationCallbackReceiver interface to determine when data should be serialized and deserialized. As a rule, deserialization happens before Awake or any other Unity event methods are ever called on your object.
Generally speaking, loading scenes and instantiating prefabs are already very expensive operations on mobile that people tend to avoid, so in truth Odin shouldn’t make that much of a difference. It will generally only make a difference if you are making Odin serialize very large amounts of data.
Feature Request.
I often have an enum and a matching list eg:
enum Things
{cat,dog,cow,max};
public List m_Things[Things.max];
so I’d like to be able to create a list with each item in the list labeled with the enum type
So the user can see they need a cat like object dragged into element 0 a dog like object in element 1 etc.
I didnt see anything obvious in the demos to show this might be all ready possible.
so an annotaion like
[ListLabels(“Things”)]
We haven’t written the drawers 101 section yet, so it would be unclear how to do this, but it is quite easy to create your own attribute that does exactly this. Here’s how.
Say you declare an attribute like this:
using System;
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class EnumListLabelAttribute : Attribute
{
public Type EnumType;
public float LabelWidth;
public EnumListLabelAttribute(Type enumType, float labelWidth)
{
this.EnumType = enumType;
this.LabelWidth = labelWidth;
}
}
And then, in an editor script (located in an editor folder), declare this drawer:
using System;
using UnityEngine;
using System.Collections;
using Sirenix.OdinInspector.Editor;
using Sirenix.Utilities.Editor;
[OdinDrawer]
[DrawerPriority(0, 1000, 0)] // Set a high wrapper priority, so the drawer is part of the wrapping queue
public class EnumListLabelDrawer : OdinAttributeDrawer<EnumListLabelAttribute>
{
public override bool CanDrawTypeFilter(Type type)
{
return !typeof(IList).IsAssignableFrom(type); // Don't draw for the list itself, only the list elements
}
protected override void DrawPropertyLayout(InspectorProperty property, EnumListLabelAttribute attribute, GUIContent label)
{
// Get label for enum index
int index = property.Index;
string indexName = Enum.GetNames(attribute.EnumType)[index];
// Set label width
GUIHelper.PushLabelWidth(attribute.LabelWidth);
{
// Call next drawer with enum entry
this.CallNextDrawer(property, new GUIContent(indexName));
}
GUIHelper.PopLabelWidth();
}
}
Now, you can easily decorate your list with this attribute, like so:
[EnumListLabel(typeof(Things), 50)]
public GameObject[] m_Things = new GameObject[(int)Things.max];
And this will be the result: