We're proud to announce that Odin now has official support for Unity 7.0 and its new CoreCLR runtime.
The same build of Odin - both in pre-compiled assembly and source mode - now functions in both the
old Mono and the new CoreCLR runtimes.
This involved hundreds of changes and fixes across the codebase, both small and large. These have been
condensed into the few dozen CoreCLR-related patch notes listed below.
This is a big change for Odin, and Unity 7.0's alpha is also a quickly moving target with regular changes,
so please let us know if you experience any Odin-related issues in Unity 7.0.
Odin Inspector
Additions
Added CoreCLR (Unity 7.0) support to Odin Inspector.
Added the public extension method TypeExtensions.SubstituteGenericParameters, which replaces generic parameters with given arguments anywhere within a type. This was added as a replacement for the Mono runtime's ability to
create partially constructed generic types; something which CoreCLR does not allow. Everywhere this was used, Odin now keeps its own separate set of partially defined generic arguments, and uses this method to fill
them out as necessary.
Improvements
Odin can now be compiled against the .NET Standard 2.1 API Compatibility Level while in source mode. .NET Standard 2.0 is still not supported.
Added a "Scripting Defines" page to Tools > Odin > Inspector > Preferences, which controls where Odin puts its scripting define symbols: Player Settings (default), shared with everyone who uses the project; Local Response File, which writes them to Assets/csc.rsp so you can exclude it from source control when only some team members have Odin; or Manual, where Odin doesn't add or remove them.
Range and MinMaxSlider errors now show the allowed range and the current value.
Fixes
Visual Designer files are now culture-independent, and files saved in the old culture-dependent format still load. Values that can't be read are now skipped instead of failing to load the file.
Fixed Visual Designer files failing to load when an attribute had a flags enum with more than one value set.
Fixed AssetSelectorAttribute.Paths getter separating the paths with ',' while its setter splits them by '|'.
Fixed setting AssetSelectorAttribute.Paths to null throwing an exception; it now clears the paths, so the whole project is searched.
Fixed the Visual Designer not saving changes to AssetSelector.Paths.
Fixed the Visual Designer dropping a property's attribute changes on save when its first attribute had no changes.
Fixed a NullReferenceException when clicking a static button on a member whose value is null.
Fixed the RequiredListLength code example breaking the API documentation.
Fixed the Serialization Debugger giving wrong reasons for generic collections and dictionaries that Unity can't serialize.
Fixed Odin not recognizing [SerializeReference] fields on Unity 7.0: they were treated as though they were not serialized by Unity, so Odin's inspector didn't show them and Odin Validator didn't validate them.
Removed FixUnityAssemblyVersionResolution, an old workaround for resolving Unity's script assemblies (Assembly-CSharp and similar) when referenced with another version, which every supported Unity version now does by itself. This also resolves a crash it was causing on the new CoreCLR runtime (Unity 7.0).
Future-proofed for the new CoreCLR runtime (Unity 7.0): Odin no longer assumes that an assembly without an Assembly.Location wasn't loaded from a file, which Unity warns may become the case for all assemblies it loads. Odin also checks the path Unity reports for the assembly before treating it as dynamic.
The Getting Started window now imports its demo packages with AssetPackage.Package.Import (Unity 7.0) and finds scene objects with Object.FindObjectsByType(Type) (Unity 6.4+), where they exist, instead of AssetDatabase.ImportPackage (obsolete in Unity 7.0) and Object.FindObjectsOfType (obsolete since Unity 6). Older Unity versions keep using the APIs they have.
Odin now sets its scripting define symbols in Player Settings through Unity's current NamedBuildTarget API where it exists (Unity 2021.2+), instead of an API that is now obsolete.
Fixed static expressions without a result and without parameters (for example "@Debug.Log(1)" in a number field in a static context) failing to compile. Expression errors that are not syntax errors are now reported like syntax errors instead of being lost, and number field expressions that throw, or produce something that isn't a number, now log an error naming the expression; an expression without a result simply runs.
Fixed expressions failing with an unreported error when they call a generic method whose type parameters are constrained by each other (e.g. where T : U) with arguments that don't satisfy the constraint. Overload resolution now moves on to the next matching overload, and if the generic method is the only candidate, the error message names the inferred types.
Fixed the Static Inspector failing to show a type at all on the new CoreCLR runtime (Unity 7.0) when the type has static members using Span<T>, ReadOnlySpan<T> or other byref-like types (for example "static ReadOnlySpan<byte> Table => ..."). The specific members that cannot be shown are now passed over.
Fixed the persistent inspector state cache file keeping stale data at its end when it shrank, as it was written without truncating the old file.
Fixed foldouts, tabs, table pages and other persistent inspector state being forgotten every time the editor restarted on the new CoreCLR runtime (Unity 7.0), where string hash codes differ between processes. Persistent state keys now use StringSlice's hash, which now gives the same values in every process, and the same values as string.GetHashCode() did on older Unity versions, so existing saved state is kept.
The Serialization Debugger now correctly explains that Unity does not serialize .NET class library types from the System namespaces, on every runtime.
Fixed persistent inspector state, such as foldouts, not being saved when scripts reload on the new CoreCLR runtime (Unity 7.0). It is now saved before scripts reload and when the editor quits, instead of when the AppDomain unloads, which no longer happens on script reloads.
Fixed Odin keeping the previous script reload's code alive and running after every script reload on the new CoreCLR runtime (Unity 7.0), a memory leak that grew with each recompile. The expression cache cleanup thread and the Visual Designer's file watcher are now stopped before scripts reload.
Fixed Odin using types from the previous script reload on the new CoreCLR runtime (Unity 7.0), causing errors such as "cannot cast GeneralDrawerConfig to GeneralDrawerConfig" or generic constraint violations. On CoreCLR, AppDomain.GetAssemblies() also returns the previous reload's assemblies while they are being unloaded; Odin now only uses current assemblies everywhere it scans them. Added AssemblyUtilities.GetLoadedAssemblies() and AssemblyUtilities.IsCurrentAssembly().
Fixed Odin not being used as the inspector for your own types on the new CoreCLR runtime (Unity 7.0), and assemblies being classified wrongly (for example user scripts as Unity engine assemblies) in type pickers, the expression engine and everywhere else Odin filters by assembly category.
Assembly file paths now come from Unity where possible, as Assembly.CodeBase doesn't necessarily give the right path on CoreCLR.
Fixed "Could not find the field 'm_CachedPtr'" errors on Unity 7.0, which broke drawing values in the inspector. UnityExtensions.SafeIsUnityNull now uses Unity's own native object check where m_CachedPtr no longer exists.
Fixed the Visual Designer's file watcher throwing an exception when stopping on the new CoreCLR runtime (Unity 7.0), where Thread.Abort() doesn't exist any more.
Fixed "Show in explorer" on file path fields, and the folder buttons of file and folder path fields, throwing an exception instead of opening the folder on the new CoreCLR runtime (Unity 7.0).
Fixed Odin's inspector failing to initialize on the new CoreCLR runtime (Unity 7.0) with a TypeLoadException in DrawerUtilities, caused by how Odin wraps Unity's own PropertyDrawers and DecoratorDrawers. Such partially constructed drawer types are now described as data through the new TypeSearchInfo.MatchTypeArguments, instead of being created as types. Users who have created their own custom type search index matchers are encouraged to account for the MatchTypeArguments field as well, either not applying their matcher when it is non-null, or using it instead of partially constructed generic types for matchers using generic inference features.
Odin's generic constraint validation now follows the .NET runtime's rules exactly, on both the Mono and new CoreCLR runtimes (Unity 7.0). This fixes errors on CoreCLR when Odin would construct invalid generic types (for example for drawers, resolvers and formatters), and a possible stack overflow (editor crash) with some generic constraint setups.
Odin Inspector can now create runtime-emitted assemblies on both the Mono and new CoreCLR runtimes (Unity 7.0).
Fixed $value in attribute expressions having the member's declared type instead of the value's actual type, which made expressions like "@$value.UpdateVersion()" fail on interface-typed members.
Fixed errors when inspecting types with pointer or ref-returning members, e.g. in the Static Inspector.
Fixed the Getting Started window trying to open when Unity runs in batch mode.
Sirenix.Reflection.Editor.dll now loads and functions properly on the CoreCLR runtime in Unity 7.0 instead of throwing invalid access exceptions.
Fixed the default import settings of Odin's serialization assemblies, so every platform now defaults to exactly one version (the AOT one). The import settings automation will still by default configure the JIT assemblies to be used on target platforms with a JIT.
Fixed Odin editors drawing blank when created and drawn in the same GUI event, e.g. in an IMGUI SettingsProvider.
Fixed the Odin Personal EULA popping up every time Unity started for users whose EditorPrefs weren't being saved. Accepting the EULA is now also saved in the project's EditorUserSettings, and is remembered per project, so new users accept it once in each project. Anyone who has already accepted the EULA isn't asked again.
Fixed the selected tab of a TabGroup being hard to tell apart from the other tabs in play mode. Tab backgrounds and borders now respect GUI.color, including Unity's play mode tint.
Fixed SdfIcons.CreateTransparentIconTexture sometimes creating icons with the wrong color or thickness right after an assembly reload, and the textures it creates being destroyed when a scene is loaded, which made icons such as LabelText icons disappear after entering play mode. The returned textures now have HideFlags.DontSaveInEditor set, so set hideFlags to HideFlags.None before saving one in an asset or scene.
Fixed an issue where double-clicking the Script field at the top of a component, or an Odin object field, to open the asset would leave the scene view unable to receive navigation input such as right mouse fly mode (seen in Unity 6000.7). Odin now opens the asset after the GUI event has finished processing, instead of from inside the mouse event.
Fixed dictionary Add adding the old key instead of a key just picked from a popup.
Fixed Paste being greyed out in the right-click menu when copying between a prefab override and another field, such as a changed field in a prefab variant. In Unity 6, Unity's own Copy and Paste items replaced Odin's on overridden fields, and the two don't share a clipboard.
GenericMenuExtensions.RemoveMenuItems and ReplaceOrAdd now work in Unity 2022.3 and newer, instead of failing with an error. Also added GenericMenuExtensions.RemoveRedundantSeparators.
Fixed an issue where fields inside groups gave PropertyDrawers a null fieldInfo and attribute, skipped custom drawers, and hid prefab override bars.
Fixed an issue where the Addressables selector would throw "ArgumentException: Invalid path" and become unusable when viewing assets by path, if an Addressable folder contained sub-assets such as sprites.
SirenixEditorFields.Vector2Field now correctly divides its rect into 2 sections instead of 3.
Odin Validator
Additions
Added CoreCLR (Unity 7.0) support to Odin Validator.
Fixes
When installing itself, Odin Validator should no longer cause console warnings about meta files with missing assets.
Fixed a possible NullReferenceException when finding the validator for a result in the Validator window.
Fixed the precompiled Odin Validator assemblies throwing MethodAccessException in the Scene view on the new CoreCLR runtime (Unity 7.0).
Fixed the validation result cache's background saving thread being left running after every script reload on the new CoreCLR runtime (Unity 7.0).
Fixed DetectComponentsNotAttachedToGameobject throwing when its component is null.
Fixed a typo in the 'Component is not attached to gameobject' error message.
Fixed scene validators made by validation rules not being initialized with their scene when running their fixes.
Fixed a result with both errors and warnings being reported as a warning, so automation did not stop on the error.
Odin Serializer
Regression Notice
Unfortunately, patch 4.0.2.4 of Odin was accidentally built with a slightly older version of the serializer due to an issue in our repository setup.
Therefore, Tuanjie scene AOT scan support and Unity dictionary serialization support were not present in this patch. We have corrected the issue so
it cannot reoccur, and reinstated these fixes in this version of Odin.
Additions
Added CoreCLR (Unity 7.0) support to Odin Serializer.
Improvements
Odin Serializer can now be compiled against the .NET Standard 2.1 API Compatibility Level while in source mode. .NET Standard 2.0 is still not supported.
Fixes
Fixed regression from patch 4.0.2.4 where the AOT scan would no longer correctly scan Tuanjie engine scene files, which can have the ".scene" extension instead of the ".unity" extension.
Fixed regression from patch 4.0.2.4 where OdinSerializer would fail to understand that as of 6000.6, Unity can now serialize dictionaries under certain specific circumstances. NOTE: this means that serialization of dictionaries in public fields marked [SerializeField] will now switch from Odin- to Unity-serialized on all Odin-serialization-enabled Unity objects (IE, objects deriving from SerializedMonoBehaviour, etc). A warning will be logged when this switch happens, prompting the user to specifically request Odin serialization via [NonSerialized, OdinSerialize] if they want to keep using Odin serialization for that dictionary.
Fixed AOT support dll generation potentially including private types of the .NET class library, such as HashSet<T>.Entry, which made the generated dll larger and depend on implementation details that can differ between the editor and the player.
Fixed Odin Serializer not recognizing [SerializeReference] fields on Unity 7.0, which treated them as not serialized by Unity.
Fixed float and double values of negative zero (-0) being saved as positive zero in Odin Serializer's text formats (the editor's Nodes format, JSON, and dictionary keys in prefab modifications) on Mono.
Fixed SerializationUtility.SerializeValue with DataFormat.JSON sometimes producing compact JSON without type optimization after a prefab instance had been saved, instead of the default readable JSON. Saving prefab modifications no longer leaves its JSON writer settings on the shared cached writer.
Fixed Odin-serialized objects being saved in the editor as if a player were being built on the new CoreCLR runtime (Unity 7.0), when the Scriptable Build Pipeline package isn't installed. Prefab instances lost their Odin prefab modifications (an instance whose Odin-serialized values were changed could load with no data and an "Invalid binary data stream" error), and the editor serialization format setting was ignored in favour of the build format.
Removed uses of long-obsolete Unity APIs, namely the PS3, Xbox 360 and Wii U runtime platforms.
Fixed Odin Serializer turning a script reload leak caused by another package into a much larger one on the new CoreCLR runtime (Unity 7.0): if anything kept one old script context alive, Odin Serializer kept every later one alive too, so the editor's memory use grew with every recompile.
Fixed Odin Serializer saving several .NET types without their contents: dictionaries using StringComparer.InvariantCultureIgnoreCase (or another culture-aware comparer) threw a NullReferenceException after loading, and non-generic Stack, Queue and SortedList, BigInteger, Complex and CompareInfo values (and BitArray on Mono) came back empty. The Unity serialization policy now serializes all non-[NonSerialized] fields of .NET's own [Serializable] types, as .NET's serialization contract does.
Dictionaries using their key type's default comparer no longer save the comparer. Their data is smaller and the same on every Unity version; previously, a dictionary with string keys saved on the new CoreCLR runtime (Unity 7.0) caused a warning when loaded in older Unity versions. Existing data loads as before.
Fixed prefab modifications of dictionaries with Vector2, Vector3 or Vector4 keys reading the keys back wrong in English locales (e.g. (1.5, -2.25) as (15, -225)), and of dictionaries with float, double or decimal keys reading the keys back wrong in locales such as Danish or German (e.g. 1.5 as 15). Key strings are now always parsed with the invariant culture they are written in.
On the new CoreCLR runtime (Unity 7.0), Odin Serializer's text formats (JSON, and the nodes format used for prefab modifications) now write float and double values exactly as older Unity versions do, instead of writing about half of all values as a different but equivalent text.
On the new CoreCLR runtime (Unity 7.0), Odin Serializer now writes .NET type names the way older Unity versions do, for example "System.Int32, mscorlib" instead of "System.Int32, System.Private.CoreLib". The same data no longer changes depending on the Unity version that saved it, and older Unity versions read it directly instead of searching every loaded assembly.
Fixed Odin Serializer not serializing fields of some .NET class library types, such as Uri, ObservableCollection<T>, BindingList<T>, StringCollection and StringDictionary on the new CoreCLR runtime (Unity 7.0), and BigInteger and Complex on all Unity versions. Odin assumed Unity serializes these types, but Unity never serializes types from the System namespaces, so their values were silently lost.
Fixed Odin Serializer keeping the previous script reload's code alive after every script reload on the new CoreCLR runtime (Unity 7.0), by unsubscribing its AppDomain.AssemblyLoad handler when its code is unloaded.
Fixed Odin Serializer binding types from the previous script reload on the new CoreCLR runtime (Unity 7.0). On CoreCLR, AppDomain.GetAssemblies() also returns the previous reload's assemblies while they are being unloaded; Odin Serializer now only uses and registers current assemblies.
Fixed "FieldInfo must be a runtime FieldInfo object" errors when serializing on the new CoreCLR runtime (Unity 7.0). Odin Serializer's fast emitted formatters are used again, instead of falling back to slower reflection formatters with an error logged per type. This also fixes AnimationCurve data being written corrupt, and Odin Validator's ReflectionOrEmittedBaseFormatter reading and writing nothing on CoreCLR.
Fixed "Could not find the field 'm_CachedPtr'" errors on Unity 7.0, which broke serialization of SerializedMonoBehaviour, SerializedScriptableObject and other Odin-serialized Unity objects. UnityExtensions.SafeIsUnityNull now uses Unity's own native object check where m_CachedPtr no longer exists.
Generating AOT support dlls (Tools > Odin > Serializer > AOT Generation) now works on the new CoreCLR runtime (Unity 7.0), as well as on Mono. Saving the generated assembly uses PersistedAssemblyBuilder where the old AppDomain-based API doesn't exist.
Odin's generic constraint validation now follows the .NET runtime's rules exactly, on both the Mono and new CoreCLR runtimes (Unity 7.0). This fixes errors on CoreCLR when Odin would construct invalid generic types (for example for drawers, resolvers and formatters), and a possible stack overflow (editor crash) with some generic constraint setups.
Odin Serializer can now create runtime-emitted assemblies on both the Mono and new CoreCLR runtimes (Unity 7.0).