Odin Inspector Version 3.2.1

Odin 3.2 includes a slew of new features, capabilities and fixes, but most exciting are our three big ticket items: UI Toolkit support, Units and Smart Fields, and the new Addressables support module.

UI Toolkit Support

Odin Inspector can now render Visual Elements (UI Toolkit) inside ImGUI! This means that Odin now supports rendering of Unity property drawers and inline editors implemented with UI Toolkit. This greatly improves Odin's out-of-the-box support for many newer Unity packages as well as Asset Store assets.

This means whenever Odin stumbles upon something for which it has no specific built-in or user-created drawer, it will try to draw it with UI Toolkit if a UI Toolkit drawer is available, which will be the case for for many newer Unity packages as well as some Asset Store assets.

Note that this feature is only enabled in Unity 2020.2 and above. You can also also disable it manually in the Odin preferences window under the general drawer settings.

This new feature is made possible by our OdinImGuiElement integration, allowing you to draw visual elements inside ImGUI from anywhere, even in non-Odin editors. You can also utilize this API manually in your own ImGUI code to embed arbitrary visual elements anywhere:

using Sirenix.OdinInspector.Editor.Internal.UIToolkitIntegration;

// Your element goes in the constructor.
// You can also give it a serializedProperty.
private OdinImGuiElement SomeElement = new OdinImGuiElement(new ListView());

private void OnGUI()
{
	GUILayout.BeginVertical();
	var rect = ImguiElementUtils.EmbedVisualElementAndDrawItHere(this.SomeElement);
	// Or optionally with a label:
	//var rect = ImguiElementUtils.EmbedVisualElementAndDrawItHere(this.SomeElement, new GUIContent("Custom label"));
	GUILayout.EndVertical();
}

In addition to the manual API above, Odin will now draw any Unity PropertyDrawer, DecoratorDrawer and inlined Editor as an embedded VisualElement if it provides one, with a fallback to normal ImGUI. You can also force any property to be drawn with visual elements by applying the new DrawWithVisualElements attribute to it.

Units and Smart Fields

Introducing enhanced number interaction with Unit and smart fields in Odin Inspector.

The new Unit attribute allows you to define a field's value, such as meters, and easily switch units without changing the underlying code. You can even input values in other units, and the inspector will automatically convert them. With over 200 built-in units, Unit and Smart Fields offer a more flexible way of handling numerical values.

The Unit system also comes with a new Unit Overview window, allowing overview of all units in your system, including custom units you've added. It's accessible from the Odin menu, or by right clicking a unit field in the inspector.

Smart fields enable scripting directly into a field's text box using Odin expressions by starting with an @ character. They also maintain a history of your entries for quick navigation.

How to use

// A meters field. The user can enter other values and convert them to meters, or change the display on the fly.
[Unit(Units.Meter)]
public float Meters;

// Radians field shown in degrees. The user can still enter other values and change the display as they want.
[Unit(Units.Radian, Units.Degree)]
public float RadiansDisplayedAsDegrees;

// You can reference units by name. Useful for using custom units.
[Unit("Meters per Second")]
public float MetersPerSecond;

// Combine with ShowInInspector and properties can be used as a kind of debug field by displaying a value in multiple units at once.
// ForceDisplayUnit prevents users from change the unit in the inspector, and DisplayAsString, well, displays as string.
[ShowInInspector, Unit(Units.MetersPerSecond, Units.KilometersPerHour, ForceDisplayUnit = true, DisplayAsString = true)]
public float KilometersPerHour => MetersPerSecond;

API

As always, you can utilize our API to implement custom behaviors yourself.

All the new unit and smart field behaviors can be found in the SirenixEditorFields (Sirenix.Utilities.Editor) class, alongside all other custom Odin fields. The new methods are UnitField, SmartUnitField, and SmartField, with variations for different primitive data types.

UnitNumberUtility (Sirenix.Utilities.Editor) is the core of the new unit system. The class contains definitions for all implemented units and conversion methods. You can also use the AddCustomUnit methods to add custom units, and they will work with the unit fields. This is best done by creating called by some variant of Unity's InitializeOnLoad that registers your custom units during Unity's initialization.

The UnitInfo (Sirenix.Utilities.Editor) class defines a unit in the Unit system. It contains a unit's name, symbols, category, and conversion instructions.

Limitations

Unit and Smart Fields are currently available only as standalone number fields, and other attributes like Range or Delayed have not yet been implemented to work with them. The size of the field you use with units will affect precision, as conversion logic is implemented as decimal numbers. Finally, this will not work at runtime! If you want to convert units at runtime, though, you can easily go grab the conversion ratios you need from the Unit Overview and convert the values manually in your code.

Addressables Module

Unity's Addressables now has first-class support in Odin Inspector through the Addressables support module, which supports addressables 1.20 and up.

Additions

  • Added the DisallowAddressableSubAssetField attribute, which hides the sub asset object field from addressable fields in the inspector.
  • Added the RegisterAssetReferenceAttributeForwardToChild attribute, which forwards attributes onto the drawing of an addressable field, to add support for custom attributes for asset reference drawing - for example, the InlineEditor attribute has been forwarded in order to correctly draw addressables marked with InlineEditor.
  • Added the CheckResourcesToAddressableDuplicateDependencies validator that identifies dependencies that are duplicated in both addressable groups and the "Resources" folder. Note that this rule requires Odin Validator 3.2+ to be installed in order to function.
  • Added the CheckDuplicateBundleDependencies validator that detects potential asset dependencies in an addressable group. For instance, imagine two prefabs in separate groups, both referencing the same material. Each group would then include the material and all its associated dependencies; this validator will detect this case and tell you. Note that this rule requires Odin Validator 3.2+ to be installed in order to function.
  • Added the MissingAddressableGroupReferenceValidator, which checks that there are no missing asset references in any addressable groups. Note that since this is a GlobalValidator, this feature requires Odin Validator 3.2+ to be installed in order to function.
  • Added several validations for asset references: 1) checks that the provided object is marked as addressable and gives a fix if it is not, 2) checks that you've created addressable asset settings and gives you a button to open the group window if not, 3) checks that the main and sub asset are not missing and that AssetReferenceUILabelRestrictions are enforced; if they are missing, it provides a fix with the option to assign a label or open the labels window to create a new one.

    Example of what happens if you drag a non-addressable asset into an addressable field.


    Example of what happens if [AssetReferenceUILabelRestrictions] requirements aren't met:

Improvements

  • Improved the asset reference dropdown with a custom drawer which has different modes to show the values in a hierarchy, flat, or grouped by addressable group.

  • Improved inspector support for the InlineEditor and PreviewField attributes.
  • Improved validation support for the Required and Optional attributes. There's also two new corresponding rules which have global toggles to make them required by default which can be overwritten using the Optional attribute.

General Patch Notes

Odin Inspector

Additions

  • Added [Searchable] support for TableLists and Dictionaries.
  • Implemented new version of shakeable group (SirenixEditorGUI.BeginShakeableGroup, StartShakeableGroup and EndShakeableGroup) that no longer requires a group key as input.
  • The FilePath attribute now has an option to exclude the file's extension.
  • Added support for Odin displaying member-less SerializedProperty backed inspector values that are of type Vector2Int, Vector3Int, RectInt and BoundsInt.
  • Added support for handling SerializedProperties of types Vector2Int, Vector3Int, RectInt and BoundsInt to the SerializedPropertyUtilities class.
  • Added percentage units.
  • Added Kibibyte, Mebibyte, Gibibyte, Tebibyte and Pebibyte units.

Performance

  • Removed a FindObjectsOfTypeAll call that occurred for each inspected component opened that uses Odin. Originally, the call was trying to find all Inspector windows to request mouse moves. It is replaced with a call that only affects the currently drawing Inspector window instead. This will greatly reduce the performance impact of opening the inspector in very large Unity projects with an enormous amount of assets loaded in memory.

Changes

  • AssemblyTypeFlags and all APIs and features that interact with them have been marked obsolete. These APIs have been replaced by ones that use the new AssemblyCategory enum, which is far more robust, reliable and sensible. This means the "artificial" distinction of User Types vs Plugin Types and which types are editor types or not has been removed - assemblies are now categorized into Scripts, ImportedAssemblies, UnityEngine, DotNetRuntime, DynamicAssemblies, and Unknown.

    You will notice that the sorting categories under Editor Types have changed names, and many types that would formerly have been categorized as plugin or Unity types are now instead categorized as Script types (IE, compiled by Unity as source files from the project or a package) or as imported assemblies (assembly files that are in the project or a package), whereas Unity types is now a category reserved solely for types from the core Unity engine distribution itself, not for types that originate from scripts contained in Unity packages installed via the package manager.

  • Added the ability to override how OdinSelector toolbars are drawn.
  • Custom Odin number fields now uses Unity's internal logic for sliding values. This makes Odin's number sliding identical to Unity's.
  • Marked already obsolete SirenixEditorFields.EnumMaskDropdown to produce compile errors if used.
  • SirenixEditorGUI.ToolbarButton draws SDF icons slightly bigger.
  • Odin's modules will now default to installing and updating automatically when their requirements are present, instead of always asking the user first. Note that this can easily be disabled in the preferences; we have just changed the default to make the overall experience smoother for new users.
  • OdinEditorWindow.OnGUI() has been marked obsolete; you should now override OnImGUI() instead. This change is sadly necessary in order to add UIToolkit support to OdinEditorWindow.

Fixes

  • Fixed an issue where rebuilding the menu tree would prevent it from closing on selection confirmed.
  • Fixed case where Odin would not correctly match and use Unity property drawers targeting generic types, when those drawers have useForChildren set to true on their CustomPropertyDrawer attribute.
  • Fixed a bug where using a Toggle or ToggleGroup attribute would make Odin dropdowns unclickable.
  • Fixed a UI alignment issue with dictionaries.
  • Fixed an issue where ToggleGroups incorrectly removed focus control on mouse down events, causing other controls not to work properly.
  • PropertyValueCollection.ForceSetValue now actually forcibly sets the value under all circumstances. Before, it would not set the value or mark itself dirty if the values were "the same" according to its equality comparator.
  • The expression compiler now always resolves the un-namespaced "Units" identifier as referring to Sirenix.OdinInspector.Units, and "GUIHelper" as referring to "Sirenix.Utilities.Editor.GUIHelper". This resolves short name resolution conflicts for those identifiers.
  • Fixed bitbucket issues #912 (AssetsOnlyAttribute does nothing when marked with TableMatrixAttribute)
  • Fixed an issue where dictionary key slide rects were not proparly indented.
  • Fixed invalid formatting exception on decimal fields in Unity 2022 and above. This especially affected unit fields, as they are handled as decimal internally.
  • Fixed issue with the UI Toolkit support feature where Odin would throw InvalidCastExceptions when trying to draw values with UITK when that value is drawn because of a Unity UITK PropertyDrawer for a value or an attribute, that is non-polymorphically targeted.
  • Improved handling of custom classes inheriting from AssetReference.
  • Fixed an issue where clicking the "Reset To Default" button in the "Editor Types" preferences would throw a "SerializedObject target has been destroyed" exception.
  • Fixed a small aligment issue with dictionary headers.
  • Fixed issue where in some cases Odin would recreate InspectorProperties every frame. This fixes the beta issue where some of Unity's Localization inspectors would be mangled and render badly if drawn by Odin. This issue happened if an OdinPropertyResolver was matched to a type polymorphically using non-generic type matching. This would cause the ResolverForType member to return an incorrect value, prompting the property system to rebuild the entire property every frame. IE, a MyResolver : OdinPropertyResolver<Component> that is resolving for a MyMonoBehaviour, would return a ResolverForType value of Component instead of MyMonoBehaviour. Now it correctly returns MyMonoBehaviour instead, despite its generic argument for the resolved type being Component.
  • Fixed issue where tabs in TabGroups would not always properly respect member ordering when ordering the tabs in the TabGroup.
  • Fixed issue where AssetReferenceDrawer would not always show the sub asset field when it was supposed to.
  • Fixed an issue in which the MaterialValidator would throw an error in newer versions of Unity. This was due to Unity's GetHDUpgraders method becoming public.
  • Fixed an issue where the UnitOverviewWindow would assume that no new categories would be added (excluding custom ones).
  • Removed forgotten Debug.Log from AddressableReferenceDrawer.

Changes to UIToolkit Support (since UIToolkit Preview launched)

  • Made the UI Toolkit support toggleable, and forced it to be disabled in versions prior to 2020.2 (or rather, when the required API is not present)
  • Fixed case where Odin would not draw UIToolkit element implementations of Unity property drawers if those drawers did not define the CreatePropertyGUI method themselves but instead inherited it from a parent class.
  • Fixed case where Unity Decorator drawers might be drawn twice.

Odin Validator

New validator type: Global Validators

In addition to ValueValidators, RootObjectValidator, SceneValidator and AttributeValidator we've now added a GlobalValidator. You can think of it as doing for the entire project what a scene validator does for a scene; it checks overall project settings and can do other more complicated validations that may require looking at more than a single asset at a time, and thus would be complicated to run from asset or value validators.

Here's an example of a global validator that checks if the current build target is supported by the project:

// Like other validators, global validators can be both rules or normal validators.
[assembly: RegisterValidationRule(typeof(GlobalvalidatorExample))]
// [assembly: RegisterValidator(typeof(GlobalvalidatorExample))]

public class GlobalvalidatorExample : GlobalValidator
{
	public BuildTarget[] ValidBuildTargets = new BuildTarget[] { BuildTarget.Android, BuildTarget.iOS };

	public override IEnumerable RunValidation(ValidationResult result)
	{
		if (ValidBuildTargets.Contains(EditorUserBuildSettings.activeBuildTarget) == false)
		{
			ref var error = ref result.AddError($"Your current build target ({EditorUserBuildSettings.activeBuildTarget}) is not supported by this project.");

			foreach (var item in ValidBuildTargets)
			{
				var buildTarget = item;
				error.WithButton($"Switch to {buildTarget}", () =>
				{
					DemoUtils.SwitchBuildTarget(buildTarget);
				});
			}
		}

		// Similar to coroutines, you can yield return null 
		// for long running validators, similar to coroutines.
		// Each yield will return the control flow back to the 
		// editor, and validation will continue next frame.
		return null;
	}
}

Additions

  • Added new validation rule to the validator called Missing Unity Object References validator. This validators checks if any unity object fields has a unity object assigned to it that has gone missing. A missing value is likely caused by the referenced object being deleted.
  • Added options to create a global validator from the validator window as well as the project browser's context menu.
  • Added tooltips to all configurables options in all built-in rules.

Fixes

  • Creating new validators from the Validator window, now remembers your last location on a per project basis.
  • Fixed an issue where excluding shaders with errors by right clicking shader compiler error issues, did not work.
  • AssetReference Validator now calls AssetReference.ValidateAsset.

Changes

  • Rules are now sorted alphabetically.

Odin Serializer

Fixes

  • Fixed issue where "UnityException: GetAllRegisteredPackages is not allowed to be called during serialization" and possibly other similar exceptions would be logged during an AOT support scan. Processing and filtering of all registered types for AOT support is now delayed to the end of the scan where the Unity API is legal to use, rather than performed immediately as they are registered.