Note that this is a beta release. We've chosen to give 3.2 a few weeks in beta before we classify it as a stable release, given how many new features and systems we've included.
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.
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.
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.
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.
// 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;
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.
Unity's Addressables now has first-class support in Odin Inspector through the Addressables support module, which supports addressables 1.20 and up.
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.
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.
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.
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;
}
}