diff --git a/Aspid.FastTools.Analyzers/Aspid.FastTools.Analyzers/Aspid.FastTools.Analyzers/AnalyzerReleases.Shipped.md b/Aspid.FastTools.Analyzers/Aspid.FastTools.Analyzers/Aspid.FastTools.Analyzers/AnalyzerReleases.Shipped.md index f50bb1fe2..01ff8d6f4 100644 --- a/Aspid.FastTools.Analyzers/Aspid.FastTools.Analyzers/Aspid.FastTools.Analyzers/AnalyzerReleases.Shipped.md +++ b/Aspid.FastTools.Analyzers/Aspid.FastTools.Analyzers/Aspid.FastTools.Analyzers/AnalyzerReleases.Shipped.md @@ -1,2 +1,23 @@ ; Shipped analyzer releases ; https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md + +## Release 1.0.0 + +### New Rules + +Rule ID | Category | Severity | Notes +--------|----------|----------|------- +AFT0001 | Usage | Error | [TypeSelector] applied to an unsupported field +AFT0002 | Usage | Warning | [TypeSelector] Allow has no effect on a managed reference +AFT0003 | Usage | Warning | [TypeSelector] base type shares no concrete type with the field +AFT0004 | Usage | Error | [TypeSelector] managed reference targets a UnityEngine.Object-derived type +AFT0005 | Usage | Warning | [TypeSelector] base type has no visible concrete implementation +AFT0006 | Usage | Error | [TypeSelector] string argument resolves to nothing +AFT0007 | Usage | Error | [TypeSelector] member reference cannot supply base types +AFT0008 | Usage | Warning | [TypeSelector] string argument is not a valid type name +AFT0009 | Usage | Warning | [TypeSelector] base types have no type in common +AFT0010 | Usage | Warning | this.Marker() call the profiler-marker generator cannot support +AFT0011 | Usage | Warning | this.Marker() scope is never disposed +AFT0012 | Usage | Warning | [TypeSelector] on a field Unity does not serialize +AFT0013 | Usage | Warning | this.Marker() scope stays open across yield return or await +AFT0014 | Usage | Warning | WithName() name is not a compile-time constant diff --git a/Aspid.FastTools.Analyzers/Aspid.FastTools.Analyzers/Aspid.FastTools.Analyzers/AnalyzerReleases.Unshipped.md b/Aspid.FastTools.Analyzers/Aspid.FastTools.Analyzers/Aspid.FastTools.Analyzers/AnalyzerReleases.Unshipped.md index 76786cb17..f2b7fad65 100644 --- a/Aspid.FastTools.Analyzers/Aspid.FastTools.Analyzers/Aspid.FastTools.Analyzers/AnalyzerReleases.Unshipped.md +++ b/Aspid.FastTools.Analyzers/Aspid.FastTools.Analyzers/Aspid.FastTools.Analyzers/AnalyzerReleases.Unshipped.md @@ -1,24 +1,2 @@ ; Unshipped analyzer release ; https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md - -### New Rules - -Rule ID | Category | Severity | Notes ---------|----------|----------|------- -AFT0001 | Usage | Error | [TypeSelector] applied to an unsupported field -AFT0002 | Usage | Warning | [TypeSelector] Allow has no effect on a managed reference -AFT0003 | Usage | Warning | [TypeSelector] base type shares no concrete type with the field -AFT0004 | Usage | Error | [TypeSelector] managed reference targets a UnityEngine.Object-derived type -AFT0005 | Usage | Warning | [TypeSelector] base type has no visible concrete implementation -AFT0006 | Usage | Error | [TypeSelector] string argument resolves to nothing -AFT0007 | Usage | Error | [TypeSelector] member reference cannot supply base types -AFT0008 | Usage | Warning | [TypeSelector] string argument is not a valid type name -AFT0009 | Usage | Warning | [TypeSelector] base types have no type in common -AFT0010 | Usage | Warning | this.Marker() call the profiler-marker generator cannot support -AFT0011 | Usage | Warning | this.Marker() scope is never disposed -AFT0012 | Usage | Warning | [TypeSelector] on a field Unity does not serialize -AFT0013 | Usage | Warning | this.Marker() scope stays open across yield return or await -AFT0014 | Usage | Warning | WithName() name is not a compile-time constant - - - diff --git a/Aspid.FastTools/Packages/tech.aspid.fasttools/package.json b/Aspid.FastTools/Packages/tech.aspid.fasttools/package.json index 990f81f91..0817895f0 100644 --- a/Aspid.FastTools/Packages/tech.aspid.fasttools/package.json +++ b/Aspid.FastTools/Packages/tech.aspid.fasttools/package.json @@ -1,6 +1,6 @@ { "name": "tech.aspid.fasttools", - "version": "1.0.0-rc.9", + "version": "1.0.0", "displayName": "Aspid.FastTools", "description": "Unity tools to cut boilerplate — source-generated ProfilerMarkers, serializable type/enum systems, SerializeReference tooling and a fluent UIToolkit API.", "unity": "6000.0", @@ -30,7 +30,7 @@ "fluent" ], "author": { - "name": "Vladislav Panin", + "name": "Aspid", "url": "https://github.com/VPDPersonal", "email": "vpd.aspid@gmail.com" }, diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e965a790..7dfce0096 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,444 +9,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [1.0.0-rc.9] — 2026-10-24 +## [1.0.0] — 2026-11-05 -The last prerelease before 1.0.0. The notes below list what changed since `1.0.0-rc.8`. +First stable release. Unity **6000.0.53f1** or newer; every Inspector feature works in both IMGUI and UI Toolkit. The `1.0.0-rc.*` prereleases and their notes are on [GitHub Releases](https://github.com/VPDPersonal/Aspid.FastTools/releases). ### Added -- Type dropdowns show the type's icon left of its name: the `[TypeSelectorDisplay]` icon, else Unity's icon for the type. **Type icons** under Appearance in the Settings tab turns them off. -- **Field stripes** under Appearance in the Settings tab hides the status stripe left of `[SerializeReference]`, `[TypeSelector]`, `SerializableType` and `SerializableMonoScript` fields in the Inspector, and the gutter a shared reference leaves for it. The notices under the fields stay. -- In the Settings tab the Right arrow turns a focused switch on and the Left arrow turns it off; Enter still flips it. -- Alt+Shift+R (Option+Shift+R on macOS) opens Asset References on the selected asset from any Editor window. Rebind it as Aspid FastTools/Open Asset References in the Shortcuts window. -- The FastTools window switches tabs with Alt+Left and Alt+Right (Option on macOS), next to Ctrl+Tab. Rebind them under Aspid FastTools/Window in the Shortcuts window. -- `RemoveChildren` and `RemoveChildrenIf` remove several children in one call and take the same `params`, `IEnumerable`, `List` and `ReadOnlySpan` overloads as `AddChildren`. -- `AddClasses`, `RemoveClasses`, `ToggleClasses` and `EnableClasses` change several USS classes in one call and take the same `params`, `IEnumerable`, `List` and `ReadOnlySpan` overloads as `AddChildren`. An `IEnumerable` may read `GetClasses()` of the same element. `EnableClasses` takes the flag first: `EnableClasses(isFree, "selected", "free")`. -- `AddAspidWindowTheme()` gives an element of your own editor window the colours of the FastTools windows: the palette of the editor skin and the theme picked under **Appearance**, a theme of the project included. The element follows a new pick at once, and the style sheets you add after it read the `--aspid-colors-*` tokens. -- `TypeSelectorWindow.Show` takes a style sheet. The picker then takes the FastTools palette and theme, light on the light skin, in place of the colours of Unity's popups, and the sheet comes on top, so the picker can match the window that opens it. -- `InsertStyleSheet` inserts a style sheet at an index, `EnableStyleSheet(sheet, enable)` adds or removes it, and `ClearStyleSheets` removes every style sheet. -- `AddStyleSheets`, `InsertStyleSheets`, `RemoveStyleSheets` and `EnableStyleSheets` take several style sheets, with the same overloads as `AddClasses`. -- Every style sheet method has a `…FromResources` variant; the plural ones take several paths: `AddStyleSheetsFromResources("UI/Base", "UI/Dark")`. -- Every class and style sheet method has an `…If` variant, for example `AddClassIf`, `EnableClassIf` and `AddStyleSheetFromResourcesIf`. -- `ToggleButtonGroup` gets typed `SetValue`, `AddValueChanged`, `RemoveValueChanged` and `SetLabel` overloads for `ToggleButtonGroupState`, so calls such as `AddValueChanged(evt => …)` need no type arguments. -- `GUIDField` (Unity 6000.4+) gets the same chainable setters as `Hash128Field`: `SetLabel`, `SetReadOnly`, `SetMaxLength` and the other text-input and text-selection setters, so `SetLabel("Id")` needs no type arguments. -- `RectIntField` gets a typed `SetLabel`, so `SetLabel("Area")` needs no type arguments, as on `RectField`. -- `DropdownField`, `PopupField`, `RadioButtonGroup` and `MinMaxSlider` get chainable setters: `SetChoices` for the first three, `SetIndex`, `SetFormatListItemCallback` and `SetFormatSelectedValueCallback` for the popup fields, and `SetLowLimit`, `SetHighLimit`, `SetMinValue` and `SetMaxValue` for `MinMaxSlider`. `SetChoices` needs no type arguments; `DropdownField.SetChoices` also takes any `IEnumerable`, such as an array, and copies it. The other setters of `PopupField` need them (`SetIndex, int>(1)`); `DropdownField` has overloads without them. -- `SetBackgroundImage` takes a `Sprite` or a `VectorImage` as well as a `StyleBackground`: `icon.SetBackgroundImage(sprite)`. -- From Unity 6000.6, `SetTextSelf` also takes an `int`, a `long`, a `ulong`, a `float` with a format, a `ReadOnlySpan`, a `StringBuilder` or a `char[]` slice and sets the text through Unity's allocation-free `TextElement.SetText`, so text that changes every frame needs no `ToString()`. An element that is not attached to a panel yet gets the string instead, without Unity's warning. -- `SetRootItemsSelf` fills a `TreeView` or `MultiColumnTreeView` in a chain: `tree.SetAutoExpand(true).SetRootItemsSelf(items)`. -- `ScrollView`, `TabView`, `Tab` and `TwoPaneSplitView` get chainable setters. `ScrollView`: `SetMode`, `SetHorizontalScrollerVisibility`, `SetVerticalScrollerVisibility`, `SetScrollOffset`, `SetHorizontalPageSize`, `SetVerticalPageSize`, `SetMouseWheelScrollSize`, `SetScrollDecelerationRate`, `SetElasticity`, `SetElasticAnimationIntervalMs`, `SetTouchScrollBehavior`, `SetNestedInteractionKind`. `TabView`: `SetActiveTab`, `SetSelectedTabIndex`, `SetReorderable`, `AddActiveTabChanged`, `AddTabReordered`, `AddTabClosed` and their `Remove…` pairs. `Tab`: `SetLabel`, `SetIconImage`, `SetCloseable`, `AddSelected`, `AddClosing`, `AddClosed` and their `Remove…` pairs. `TwoPaneSplitView`: `SetFixedPaneIndex`, `SetFixedPaneInitialDimension`, `SetOrientation`. -- `ListView`, `TreeView` and the other collection views get `SetShowBorder`. -- `RegisterCallbackSelf`, `RegisterCallbackOnceSelf` (the callback runs for one event) and `UnregisterCallbackSelf` add and remove an event callback in a chain, with the `userArgs` and `TrickleDown` parameters of Unity's `RegisterCallback`: `button.RegisterCallbackSelf((PointerEnterEvent evt) => Hover()).SetTooltip("Apply")`. -- `TextField`, `IntegerField`, `LongField`, `UnsignedIntegerField`, `UnsignedLongField`, `FloatField`, `DoubleField` and `Hash128Field` get chainable setters: `SetMaxLength`, `SetMaskChar`, `SetDelayed`, `SetReadOnly`, `SetPassword`, `SetPlaceholder`, `SetHidePlaceholderOnFocus`, `SetKeyboardType`, `SetAutoCorrection`, `SetHideMobileInput`, `SetHideSoftKeyboard`, and for text selection `SetSelectable`, `SetSelectAllOnFocus`, `SetSelectAllOnMouseUp`, `SetDoubleClickSelectsWord`, `SetTripleClickSelectsLine`, `SetCursorIndex`, `SetSelectIndex`, `AddOnCursorIndexChange` / `RemoveOnCursorIndexChange`, `AddOnSelectIndexChange` / `RemoveOnSelectIndexChange`. The `ITextEdition` and `ITextSelection` setters do not reach these fields. Other value types use `TextInputBaseFieldExtensions` and `TextInputBaseFieldTextSelectionExtensions`. -- `TextField` gets `SetMultiline` and `SetVerticalScrollerVisibilitySelf`; the name has `Self` because Unity's own obsolete `SetVerticalScrollerVisibility` hides an extension of that name. `IntegerField`, `LongField`, `UnsignedIntegerField`, `UnsignedLongField`, `FloatField` and `DoubleField` get `SetFormatString`; other `TextValueField` types use `SetFormatString` of `TextInputBaseFieldExtensions`. -- Added `AndApplyWithoutUndo` counterparts for every `SerializedProperty` setter with immediate application, including `SetValue` overloads, object references, enums, and array size helpers. -- `SetEnum`, `SetEnumAndApply` and `SetEnumAndApplyWithoutUndo` write an enum value to a `SerializedProperty`, and `SetValue(Rarity.Rare)` calls them. `SetEnumIndex` takes an index into the enum entries, not a value: for `Rare = 20` the call `SetEnumIndex((int)Rarity.Rare)` picks the wrong entry. -- On Unity 6000.4 and later, `SetGuid`, `SetGuidAndApply`, `SetGuidAndApplyWithoutUndo` and the `SetValue` overloads write a `GUID` field; it needed `SetBoxed` before. -- **Settings** and **Preferences → Aspid.FastTools** get an **Appearance** section. Its **Theme** dropdown recolors the FastTools windows and the type picker: **Default** (near-black cards, green accent), **Venom** (the blue-black palette of the documentation site with its blue accent) or **Unity** (the greys of Unity's editor skin, so the windows read as editor panels), each with a light variant for the light editor skin. The success status stays green in all of them. The accent of links, focus and hover borders, the active tab, buttons, switches, and the Welcome title and logo moved into its own `--aspid-colors-accent-*` and `--aspid-icons-accent` tokens, so a theme can change it apart from the success status; `--aspid-colors-surface-control` and `--aspid-colors-surface-field` set the fills of the buttons and drop-downs, and of the value boxes, in the settings; `--aspid-radius-card` and `--aspid-radius-control` set their corners, `--aspid-colors-slider-track` the slider track, `--aspid-colors-dots-1` to `-3` colour the dots behind the windows, and `--aspid-dots-radius: 0` hides them. Below the built-in themes the dropdown lists the themes of the project, the `.uss` sheets in `Assets` with the `AspidFastToolsTheme` label, and **Create theme…** at its end copies the current theme into a new sheet, labels it and picks it. A theme of the project is picked for that project, a built-in one for every project on the machine. Picking a theme recolors the windows that are already open, and a sheet picked earlier as the theme override becomes the theme of the project. In the Settings tab, Enter opens the dropdown and the Left and Right arrows step through the themes. -- Analyzer `AFT0009` (warning) — two `[TypeSelector]` base types have no type in common, so the selector is empty. -- Analyzer `AFT0012` (warning) — `[TypeSelector]` on a field Unity does not serialize, so the Inspector never shows it: a non-public field without `[SerializeField]` or `[SerializeReference]`, an auto-property without `[field: SerializeField]`, or a `static`, `const`, `readonly` or `[NonSerialized]` field. -- Analyzer `AFT0010` (warning) — a `this.Marker()` call opens no profiler marker because the generator cannot support it: it is written in a `private` or `protected` type (or a type nested in one), in an interface (a default interface method) or in a type that reuses a type parameter name of a containing type; its receiver is of another type (`other.Marker()`, calls in static classes); it has an explicit argument (`this.Marker(5)`) or a type argument; or it is `this?.Marker()`, the static call form, a method group or a call inside an expression tree. The generator emits no marker for such calls. -- Analyzer `AFT0011` (warning) — the scope of `this.Marker()` is discarded (`this.Marker();` as a statement, `_ = this.Marker();`, a local nothing reads), so the sample it begins never ends. -- `SerializeReferenceIMGUIList.Draw(listProperty, label, baseTypes)` takes the element type from the list field, like `SerializeReferenceEditorGUI.CreateList`; the overload with `elementType` stays. -- `EnumValues` and `EnumValues` get `TryGetValue`, which tells a matching row from the **Default Value** fallback, and `Count`, the number of rows that `foreach` yields. `EnumValues` also gets `GetValue` and `TryGetValue`, which take the key without boxing it; a call such as `table.GetValue(damageType)` binds to them after a recompile. -- Analyzer `AFT0013` (warning) — a `this.Marker()` scope stays open across `yield return` or `await`: the coroutine or `async` method resumes in a later frame or on another thread, so the Profiler gets unbalanced samples. -- Analyzer `AFT0014` (warning) — a `WithName` name the generator cannot read at compile time, such as a variable, so the marker keeps the member name. -- Every analyzer diagnostic has a description of the fix and a help link to its documentation page; Rider and Visual Studio used to open a web search for the ID. -- Missing `[SerializeReference]` types set by prefab instance overrides (prefab variants, nested prefabs, prefab instances in scenes) are now found: the build / CI gate counts them as missing types, Project References lists them in a **Prefab instance overrides** card, and the delete guard and breakage detection count them. They are not rewritten; fix them on the instance or revert the override. An old name that `[MovedFrom]` maps is listed there as a pending migration, since **Migrate all** does not rewrite overrides. The CI report gains a trailing `origin` column, `override` for these rows. -- **Assets → Aspid 🐍 → FastTools → Asset References**, in the main menu and the right-click menu of the Project window, opens Asset References on the selected prefab, ScriptableObject, scene or prefab instance; the item is disabled for any other selection. -- `-srGateStrict` makes the CI check count the files it could not check (unfetched Git LFS files, binary assets that can hold references) as violations, so under `Fail` a run without `git lfs pull` no longer passes with exit code `0`. -- The CI report gains trailing `ns` and `asm` columns with the stored namespace and assembly of a `MissingType` row. The build and CI logs name a missing type with its namespace (`Game.Pistol`, not `Pistol`), so same-named classes can be told apart. -- A `[SerializeReference]` field whose class or own data is overridden on a prefab instance has a bold label, and its header menu offers **Revert** and **Apply to Prefab 'Name'**, as Unity's own fields do. A change inside a nested reference marks only the changed field, and **Apply** is not offered on a prefab variant selected in **Project**. The blue override bar is not drawn, and a selection of several objects shows neither. -- A `SerializableType` or `SerializableMonoScript` field or a `[TypeSelector]` string whose stored type no longer resolves shows a **Missing type** notice under the field. **Fix** opens the type picker to choose a replacement. When the class only moved to another namespace or assembly and exactly one compatible type has its name, a **→ TypeName** button replaces the stored name in one click. The caption shows the type name without its assembly, ``, and the tooltip shows the whole stored name. -- `TypeField.AssemblyQualifiedName` returns the stored name of a missing type, for which `value` is `null`, so a custom editor can save the name back unchanged. `TypeField.ExcludeEditorOnlyTypes` is now public: an unbound field can leave out types from editor-only assemblies, as a bound field on a runtime object does. -- `SerializableType`, `SerializableMonoScript` and their generic variants get `IsEmpty` (no type is stored) and `IsMissing` (a name is stored but no longer resolves); `Type` is `null` in both cases. Unity fills a serialized field with an empty wrapper when it loads an asset, a scene or a prefab, so `field == null` alone misses an unset one: test `field is null || field.IsEmpty`. -- Missing `SerializableType` and `SerializableMonoScript` names are found across the project. **Project References → Scan Project** lists them in **type name** groups with **Fix all**, **Smart Fix** and **Undo**; prefab instance overrides and fields in managed references are rewritten too. The build / CI gate reports them as `MissingTypeName` rows, with the stored name in the `className` column and the wrapper field in `fieldPath`, and breakage detection reports a name that stops resolving. `[TypeSelector]` strings are still checked only in the Inspector. -- The folder button next to a `SerializableType`, `SerializableMonoScript`, `[TypeSelector]` or `[SerializeReference]` field, and `OpenInScriptEditor`, open the API reference of a type that ships with Unity and has no script in the project: a `UnityEngine`, `UnityEditor` or `Unity` type such as `CharacterController` opens its Scripting API page on docs.unity3d.com for your Editor version, a `System` type its page on learn.microsoft.com. The button used to only log a warning for such a type. - -### Changed - -- The IMGUI drawer of `EnumValues` looks like the UI Toolkit one: the field name sits above the type field, which spans the full width, a line separates the header, **Default Value** is no longer indented, and the **Values** header is plain text instead of bold on a band. -- **Excluded scan folders** in the Settings tab reads as one of Unity's lists: its caption and the folders share one framed block, each folder has a **−** at the end of its row, and the last row (or the **List is empty** row) has the **+**. A click selects a folder and a double click picks another one for it. With the keyboard, Enter or Delete on a focused folder removes it, and its **−** lights up while it has the focus. -- The minimum Unity version is now 6000.0.53f1 instead of 6000.0.0f1. The package uses UI Toolkit APIs that later 6000.0 patches added (`IStyle.unityEditorTextRenderingMode`, `IStyle.unitySliceType`, `UxmlElement.libraryPath`), so it did not compile on earlier patches. -- The package no longer ships the `Documentation` folder with its pages and images, so they are not imported into your project; the documentation lives on the site: https://vpdpersonal.github.io/Aspid.FastTools/. The samples ship no README either: a sample description in the Package Manager ends with a link to its tutorial on the site, and the sample card on the Welcome tab shows it as a **Tutorial** link. -- The package `README.md` no longer gives the git URL, so an Asset Store buyer does not add a second copy of the package; the git URL install stays on the site. -- The Agent Skills for this package moved from the `aspid-fasttools` Claude Code plugin in [Aspid.Claude.Plugins](https://github.com/VPDPersonal/Aspid.Claude.Plugins) into this repository (`skills/`). Install them into Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI or another agent with `npx skills add VPDPersonal/Aspid.FastTools#skills`, or `#skills-preview` for a preview version: `npx skills update` then follows the releases of that channel, never `main`; the plugin is no longer published. A plugin you installed stays on your machine and teaches the agent API that no longer exists: remove it in Claude Code with `/plugin uninstall aspid-fasttools@aspid-claude-plugins`. -- The samples have a new look. Every sample ships a `Fonts` folder with IBM Plex Serif and iA Writer Quattro S, and EnumValues and EditorTools also with IBM Plex Mono, under the SIL Open Font License 1.1 (the license texts lie next to the fonts, and `Third-Party Notices.txt` in the package root lists the fonts with their licenses and paths). The scene samples (EnumValues, Types, SerializeReferences, ProfilerMarkers) also ship a `Materials` folder with colour materials and a `Shaders` folder with a small `Studio` shader. The Ability Catalog of the EditorTools sample uses the fonts through `SampleFonts.uss` and takes the FastTools theme through `AddAspidWindowTheme()`; its **Effect** field opens the type picker in place of the **Change…** button and shows the `[TypeSelectorDisplay]` name and icon of the effect, **+** replaces **Create**, **Reset to defaults**, shown while the cost or the cooldown differs from its default, replaces **Halve cooldown, +5 MP**, and the buttons of a row select its asset or move it to the trash. The sample no longer has a custom inspector: an `AbilityConfig` asset shows in Unity's default Inspector. The samples grow from about 0.2 MB to about 3 MB, most of it font copies: a sample is imported on its own, so each one carries its own. -- The five samples are simplified and listed in the order Types, SerializeReferences, EnumValues, ProfilerMarkers, EditorTools. They keep the scenes and the look above, while their C# shrinks from about 2,660 lines to about 1,560: no comments, tooltips or `Debug.Log`, one type per file, the scripts in a `Scripts` folder beside their assembly definition with related types in subfolders, and fewer classes that only filled out the demos. No sample needs the Physics module any more, and the scenes have no lights or colliders. SerializeReferences ships no broken assets: its presets, the broken prefab and the IMGUI preset inspector are gone, and its tutorial breaks a reference by renaming a class instead. -- Renamed `GetScriptName()` to `GetDisplayName()` and `GetScriptNameWithIndex()` to `GetDisplayNameWithIndex()`; update existing calls to the new names. Both methods now return `string.Empty` for null or destroyed objects. Component indexing uses a pooled list instead of temporary arrays and LINQ. -- Renamed VisualElement extensions; update existing calls: - - `SetIsDelayed` / `SetIsPassword` / `SetIsReadOnly` / `SetIsSelectable` → `SetDelayed` / `SetPassword` / `SetReadOnly` / `SetSelectable`; - - `IsFocus` → `IsFocused`, `SetFocus` / `SetBlur` → `FocusSelf` / `BlurSelf`; - - `EnableInClass` / `ToggleInClass` → `EnableClass` / `ToggleClass`; - - `AddStyleSheetsFromResource` / `RemoveStyleSheetsFromResource` → `AddStyleSheetFromResources` / `RemoveStyleSheetFromResources`; `AddStyleSheets(sheet)` and `RemoveStyleSheets(sheet)` still compile, as the plural names now take several style sheets; - - `SetImageFromResource`, `SetSpriteFromResource`, `SetVectorImageFromResource`, `SetBackgroundImageFromResource` → `…FromResources`; - - `MarkDirtyLayout` → `MarkDirtyLayoutSelf`: `IMGUIContainer.MarkDirtyLayout()` hid the old extension, so the call returned `void`; the new name chains. - - `SetText` of `TextElement` (`Label`, `Button` and others) → `SetTextSelf`: from Unity 6000.6 a string argument binds to Unity's own `TextElement.SetText(ReadOnlySpan)`, which returns `void`, so chains such as `label.SetText(x).SetTooltip(y)` failed to compile; the new name chains on every Unity version. `SetText` of `Foldout`, `HelpBox` and `Toggle` keeps its name. -- A bare `null` argument to `SetBackgroundImage` and, from Unity 6000.6, to `SetTextSelf` no longer compiles, because the new overloads fit it as well. Cast it, for example `(string)null`, or pass `StyleKeyword.None` to clear a background. -- Renamed the extension classes `BaseFieldExtensionsSetLabel` to `BaseFieldExtensions` (`BaseFieldExtensionsSetLabelInt` → `BaseFieldIntExtensions`) and `ProgressBarExtensions` to `AbstractProgressBarExtensions`. Extension-method calls are unaffected; only calls through the class name change. -- Renamed the extension class `SerializePropertyExtensions` to `SerializedPropertyExtensions`. Extension-method calls are unaffected; only calls through the class name change, such as `SerializePropertyExtensions.GetFieldInfo(property)`. -- `SetShowMixedValue` no longer defaults its argument to `true`; pass the value explicitly. -- `SetDirection`, `SetFill`, `SetInverted`, `SetPageSize` and `SetShowInputField` now return the slider's own type (`Slider`, `SliderInt`) instead of `BaseSlider`, so a chain keeps the slider's members. They accept `BaseSlider` and `BaseSlider`; the open `BaseSlider` overloads are gone. The `BaseSlider` overloads live in the new `SliderIntExtensions` class: extension-method calls are unaffected, but a call through `SliderExtensions.` on a `SliderInt` must switch to `SliderIntExtensions.`. -- The parameterless constructors of `SerializableType` / `SerializableType` are no longer public: create a wrapper with `new SerializableType(type)` or `new SerializableType(type)` (`null` gives an empty one). `SerializableMonoScript` / `SerializableMonoScript` have no public constructors: declare them as serialized fields and pick the script in the Inspector. -- `SerializableType`, `SerializableMonoScript` and their generic variants now compare by value; `Equals` and `GetHashCode` used to compare references. Wrappers that store the same type name are equal and share a hash code, so they work as `Dictionary` and `HashSet` keys, and `List.Contains` and `IndexOf` find an equal wrapper. `==` still compares references. -- `[TypeSelector]` on a `[SerializeReference]` field now offers only types assignable to every attribute type — the rule `string` and `SerializableType` fields already follow; it used to offer types matching any one of them. The same applies to `baseTypes` of `SerializeReferenceEditorGUI.CreateField`, `CreateList` and `DrawFieldLayout`. A list of alternatives such as `typeof(Pistol), typeof(Rifle)` now leaves the selector empty and triggers `AFT0009`: give the allowed classes a common interface or base class and pass that instead. `AFT0005` now checks all attribute types together. -- The `[TypeSelector]` analyzer no longer resolves the attributes of fields without `[TypeSelector]` and skips assemblies that do not reference the package; it used to slow down every compilation of a large project. -- An IMGUI inspector no longer runs a full duplicate scan of a `[SerializeReference]` list for every element on every GUI event, only once per list per editor update or when the list size changes; a shared field no longer creates a `SerializedObject` on every repaint. -- Breakage detection keeps its baseline in memory and writes it to the session once, before a script reload, instead of parsing and rewriting all of it on every asset save, which cost milliseconds per thousand assets. Its start-up read decodes only the assets that hold a managed reference or a type name, instead of reading every asset in full. -- Deleting or moving an asset no longer drops the warm usage index of Project References, the delete guard and breakage detection. A delete removes the usages of that asset, a move into or out of an **Excluded scan folder** removes or adds them, and a move between scanned folders changes nothing. An import of more than 64 scanned assets drops the index once instead of patching it asset by asset. -- `GetFieldInfo()` and `GetDeclaringInstance()` cache the field lookup, and the check that decides whether a nested `[SerializeReference]` field has its own drawer is cached per field. An IMGUI inspector no longer creates arrays or attribute instances for every nested reference on every event, and creates fewer strings, so a large tree allocates less while the mouse moves. -- **Fix all**, **Smart Fix**, **Migrate all**, `` and the summary's **Undo** in Project References no longer read a file again for every broken reference in it, and write it once. They check only once per file whether it is open or has unsaved changes, so a file with many broken references is repaired much faster. -- An empty `[SerializeReference]` field no longer parses the asset file on every repaint to check for a missing type: an unchanged file is read once, so empty fields in a large scene or prefab no longer slow the Inspector down. -- In the Inspector of a runtime object, the type picker no longer offers types from editor-only assemblies (`UnityEditor`, Editor asmdefs and `Editor` folders): a player cannot resolve them, so the value silently became `null` or a missing reference in a build. Fields of editor windows and other editor-only objects still offer every type. -- **Paste**, **Paste Template**, *Link to Existing*, a dropped script and **Smart Fix** follow the same rule in the Inspector of a runtime object: they no longer assign a type from an editor-only assembly or a generic type closed over one. The type picker of Asset References no longer offers such types for a runtime object either. **Create New Script…** leaves the field as it is and logs a warning when the new script is saved in an `Editor` folder. -- The unconstrained type picker (`SerializableType` without `T`, `[TypeSelector]` on a string, `TypeField`) reuses its type list between openings instead of rebuilding it from every loaded type each time. -- The type picker checks the field's base type first when it lists the loaded types, so a picker with a narrow base type, such as the **+** of a `[SerializeReference]` list of a specific interface, opens several times faster in a large project. An IMGUI type field resolves a stored type name once instead of on every repaint, which a missing type made slow. -- A type picker with a predicate, such as the picker of a `SerializableMonoScript` field, `TypeField.Predicate` or a `[SerializeReference]` field, no longer checks every loaded type again each time it opens: the types that pass everything but the predicate are listed once per set of base types and reused until an assembly loads, and only the predicate runs on each opening. In a project with about 55,000 loaded types, the picker of a `SerializableMonoScript` field opens in about 6 ms instead of about 85 ms, and the picker of a `[SerializeReference] object` field in about 90 ms instead of about 190 ms. -- `TypeField(string label, Type defaultValue = null)` is split into `TypeField(string label)` and `TypeField(string label, Type defaultValue)`, and `InspectorTypeField` likewise. `new TypeField(null)` used to pick the property constructor and throw `NullReferenceException`; it no longer compiles, so name the argument: `new TypeField(label: null)`. The bound constructors throw `ArgumentNullException` for a `null` property and `ArgumentException` for a property that is not a string. With `binding-path` set in UXML, the field logs a warning that it can be bound only from C#. -- Reading `Type` of `SerializableType` and `SerializableMonoScript` opens a Profiler marker only for the lookup of the type, not for a cached read, so reading it for many objects every frame no longer fills the Profiler with samples. -- `EnumValues` opens a Profiler marker only when it builds its entries on first access, not in `GetValue`, `TryGetValue` and `Equals`, so a lookup for many objects every frame no longer fills the Profiler with samples. -- `SerializeReferenceIMGUIList.Draw` now throws `ArgumentNullException` for a `null` property and `ArgumentException` for a property that is not a list of managed references, like `SerializeReferenceEditorGUI.CreateList`; it used to draw nothing. A `null` label now shows the property's display name; pass `GUIContent.none` to hide it. -- Renamed the `currentAqn` parameter of `TypeSelectorWindow.Show` to `assemblyQualifiedName`, like the other parameters that take an assembly-qualified name. Update calls that pass it by name: `currentAqn: name` becomes `assemblyQualifiedName: name`. Positional calls need no change. -- The generated `this.Marker()` code now declares its marker fields only under `ENABLE_PROFILER`, like the `Marker()` body that reads them: builds without the profiler no longer create every marker in a static constructor. -- `ProfilerMarkerExtensionsForGenerator.Marker(this object)` is now `Marker(this T, [CallerLineNumber] int line = -1)`: a struct call site the generator cannot mark is no longer boxed, so a Burst job still compiles. It takes the same parameters as the generated overload, so a type without a namespace, as in Unity's script template, gets its markers too. A `this.Marker()` call inside an expression tree no longer compiles (CS0854), and a method group now needs `Func`. -- A generic class names nested type arguments the way C# writes them (`Foo>.Run (line)`, `Foo.Inner>.Run (line)` instead of ``Foo``, `Foo`). A generic struct gets one marker per call site for all its closed types, named `Job.Execute (line)`, because Burst cannot run the per-type label. -- The generated `Marker()` dispatches on the line with a `switch`, so its cost no longer grows with the number of call sites in a type. -- The generated `Marker()` takes a struct by `in`, so `this.Marker()` in a struct, such as a large job, no longer copies the whole instance on every call. The copy was made under Mono (the Editor, Mono players) and under IL2CPP when the call and the overload land in different C++ files. -- The scripting symbol that compiles out the package's own profiler markers is now `ASPID_FASTTOOLS_UNITY_PROFILER_DISABLED`, to match the other `ASPID_FASTTOOLS_*` symbols. The old `ASPID_FAST_TOOLS_UNITY_PROFILER_DISABLED` no longer works: rename it in **Scripting Define Symbols**. -- `Aspid.FastTools.VisualElements.Math` is no longer compiled as an empty assembly in projects without `com.unity.mathematics`. -- The animated dot background of the FastTools window and the settings page draws all its dots as one mesh instead of tessellating a path per dot on every frame, and pauses while Unity is in the background, so an idle open window no longer keeps the editor busy. -- The dot background repaints 20 times a second instead of 30. The new **Animated background** switch (FastTools window → Settings → Appearance, and Preferences → Aspid.FastTools → Appearance) hides the dots and stops their repaint timer, and stops the animation of the title and the logo on the Welcome tab. -- The hover gradient of a button in the FastTools windows runs its timer only while the gradient fades, and every gradient button shares one gradient texture instead of creating its own. -- The FastTools window (Welcome, Asset References, Project References and Settings) and its pages in Project Settings and Preferences follow the light editor skin: its canvas, cards, text, status colours and the type picker inside it take a light palette, `Aspid-FastTools-Default-Light.uss`; they used to stay dark on both skins. A theme still layers on top of either palette. -- The FastTools window keeps the view of each tab between visits: its scroll position, expanded rows, repair summaries and keyboard focus survive a switch to another tab and back. Asset References and Project References read the asset and the project again when you return. -- The cards of the FastTools window and of its pages in Project Settings and Preferences are opaque, so the dot background no longer shows through their text. The background and the title of the Welcome tab move only while their window is focused or under the pointer, and the Welcome logo pulses only under the pointer. -- The Settings tab marks where a setting is stored with a violet stripe for a project setting (committed, the same for the whole team) and a gray one for a per-user setting. Its legend and reset button say **Project** instead of **Shared**, the word Asset References uses for a shared managed reference, and Asset References marks such a reference with a coloured dot and a muted **shared** instead of a blue **SHARED** badge. The line above the legend is gone; the legend's tooltip says what the stripes mean. Drop-downs, sliders, object fields and the buttons of a row in Settings line up in one column at the right edge instead of taking half of each row. The description lines under the SerializeReference settings are gone: like every other setting, they are explained in the tooltip of their row. **Excluded scan folders** lists its folders in a framed box, which says **No excluded folders** when it is empty. -- **Rescan** in Asset References and **Scan Project** in Project References carry a refresh icon. Project References lists each file once, with its rid or, for several, their count (the tooltip lists them), dims the folder part of a path and adds **Copy Path** to the context menu of a row. **Smart Fix** and **Migrate** rows in both tabs name their target type with its namespace (`Smart Fix → Game.Weapons.Pistol`), and a missing type whose class name equals its fix's names the part of its namespace that differs (`Legacy.Pistol`). An orphaned reference is cleared from its card header, the way Change and Assign work on the other cards, and the Orphaned section is a plain heading instead of an amber box. **Undo** and **Open Source Prefab** are plain outlined buttons now, like the actions of the Settings tab; gradient bands stay for actions that span a card. The icon of an empty Asset References or Project References tab sits at the middle of the tab and no longer jumps when you switch tabs; its text follows below it. In a narrow window a group card of Project References cuts its type name and count with an ellipsis instead of breaking the name mid-word, **Fix all** keeps its width, and **Smart Fix** and **Migrate** rows in both tabs cut the type name in the middle, so the action and the class name stay readable. -- The shortcut hint of a tab in the window toolbar (`⌥2`) follows the tab title and hides when the tab is too narrow for both. -- The FastTools window takes the colours and corners of the documentation site: the accent green, amber, blue, red and violet are the site's, and cards and bands have 6 px corners instead of 8–10 px. Switches take the site's green everywhere; on the light skin an on switch fills its track with it under a white handle, inside a darker green outline, instead of a pale tint under a dark handle. -- The hint under the Project References header keeps only what needs attention, such as data that may be out of date or files that were not read, and Asset References drops its "N managed references mapped" line; how to act on the results moved to the tooltip of the header. Project References sorts its cards under **Broken**, **Required**, **Prefab instance overrides** and **Renamed** headings instead of a colour legend; a list of only broken or only renamed types has no heading. Required violations and prefab instance overrides get one card per file, headed by its path and entry count. Asset References shows an optional empty field as a one-line row in its place among the fields instead of a full card, and every object gets a folding heading named "GameObject › Component", or only "Component" when the GameObject has the same name, with the object's icon, a size above the sections inside them and neutral; their counts are in the tooltip. Every `[TypeSelector]` string, `SerializableType` and `SerializableMonoScript` field, required or not, is shown among the cards of its object in field order, with a field path written like theirs: a set one as a card with its type and **Change**, an empty required one as its amber card, and an empty optional one as a one-line row with **Assign**, as `[SerializeReference]` fields are. An object with such fields and no managed references gets its own heading too. The card of a known type shows the type's icon from the type picker. The Welcome tab describes the package as the site does and names every feature. -- `[TypeSelector]` on an array or `List` field now applies to the collection itself (`applyToCollection`): its drawer draws the list and a picker for each element. `PropertyField` and `EditorGUILayout.PropertyField` on such a list now get the picker-backed **+** in UI Toolkit and IMGUI, and a `PropertyField` on a single element of it no longer shows the picker. `SerializeReferenceIMGUIList.Draw` and `SerializeReferenceEditorGUI.CreateList` add the constraints of a `[TypeSelector]` on the list field to `baseTypes`. Managed-reference lists drawn by the package now honor `[NonReorderable]`. -- Renamed the `value` parameter of `AddClass`, `RemoveClass`, `ToggleClass`, `AddStyleSheet`, `RemoveStyleSheet` and their `…If` variants to `className` and `styleSheet`; a call that names the `value:` argument needs the new name. -- Style sheet methods such as `AddStyleSheet` and `RemoveStyleSheet` skip a `null` style sheet instead of throwing `ArgumentNullException`. -- `RemoveChild` and `RemoveChildren` skip `null` and elements that are not children of the element instead of throwing, so `RemoveChildren` no longer stops halfway. -- The child, class and style sheet extensions carry nullable annotations, so a project with nullable reference types enabled sees which arguments may be `null`. - -### Removed - -- Removed `SetExposedReferenceAndApply()` from `SerializedProperty` extensions; call `SetExposedReference()` instead. Without an `IExposedPropertyTable` context, Unity's `exposedReferenceValue` setter already applies the write and records Undo, so the extra apply did nothing, and a variant without Undo cannot be built on top of it. -- Removed the editor-only `SerializableMonoScript.Script`, which returned the `MonoScript` asset; no public accessor for the asset remains. The type is still available through `Type` or the implicit conversion to `Type`. -- Removed `AddMakeItem` / `RemoveMakeItem` of `ListView` and `TreeView`, and `AddMakeHeader` / `AddMakeFooter` / `AddMakeNoneElement` of `BaseListView` with their `Remove*` pairs; the view keeps one factory, so call `SetMakeItem`, `SetMakeHeader`, `SetMakeFooter` or `SetMakeNoneElement`. -- Removed the `Span` overloads of `AddChildren`, `InsertChildren` and their `…If` variants. A `Span` argument converts to the `ReadOnlySpan` overload, so existing calls compile unchanged. -- Removed the runtime `Aspid.FastTools.StringExtensions.ToKebabCase` and `Aspid.FastTools.TypeExtensions.GetMembersInfosIncludingBaseClasses` from the public API, without a replacement. - -### Fixed - -- The **Asset Store** link and the logo of the Welcome tab open the package page on the Asset Store; they led to a page that does not exist. -- Unity 6000.6 no longer warns on import that seven of the package's stylesheet `.meta` files are below the supported serialized version. -- `InsertChildren` and `InsertChildrenIf` skip a `null` entry without moving the index: `InsertChildren(0, a, null, b)` puts `b` right after `a`; it used to leave a gap or throw `ArgumentOutOfRangeException` at the end of the parent. -- `SetValue`, `SetValueAndApply` and `SetValueAndApplyWithoutUndo` compile again with a `byte`, `sbyte`, `short`, `ushort` or `char` argument on Unity 6000.2 and later: the `EntityId` overload made the call ambiguous (CS0121). Each of these types now has its own overload that calls `SetInt`. -- The XML documentation of the UI Toolkit extensions now matches the behavior: `SetValue(value, notify: true)` raises the change event only when the element is in a panel and the value differs; `SetPadding(8, 4)`, like `SetMargin`, `SetBorderWidth`, `SetBorderColor` and `SetDistance`, sets the top and the right side; a slider needs its range before `SetValue`; an inline lambda passed to `AddValueChanged` cannot be removed with `RemoveValueChanged`; on a `ListView` or `TreeView`, `AddChild` throws and `InsertChild`, `RemoveChildAt` and `ClearChildren` do nothing. Each method that exists only on newer Unity versions says `Available in Unity 6000.x and newer`. -- The documentation of `SerializableType`, `SerializableMonoScript`, `EnumValues` and `[TypeSelector]` strings now gives the right Managed Stripping Level for a class or enum that a field refers to only by its stored name: Medium and High strip it from a player, Minimal and Low keep it; it used to say Low. The Serializable Types page also lists the ways to keep such a class: `[Preserve]`, `link.xml`, and `[RequireImplementors]` or `[RequireDerived]`. -- The `SHARED` badge in Asset References now fits its text; it used to shrink to the width of its colour dot, so the text ran out of it and the dot covered the letter "H". -- Asset References shows unset required fields (the **Required type is not set** cards and REQUIRED badges) of an asset in an **Excluded scan folder**, as it already showed its missing types; the folder still keeps the asset out of Project References and the build / CI checks. -- Asset References no longer shows two states of an asset with unsaved changes at once, such as a card of a filled reference next to an amber card that says the same field is unset. It maps the saved file, so it now asks you to save the asset first and offers **Save Asset**. -- An unset required field gets the amber stripe on its left edge, as a missing type does, in both Inspectors: a `[SerializeReference]` field in UI Toolkit, and a `[TypeSelector]` string, `SerializableType` or `SerializableMonoScript` field in IMGUI and UI Toolkit. They showed only the notice; the IMGUI `[SerializeReference]` field already had the stripe. -- In both Inspectors, the label of an empty `[SerializeReference]` field, or of one with nothing to expand, and of a type name field with a warning stripe stays where it is when the field holds a value, in line with the labels around it, so it no longer jumps when you assign or clear the field. It sat a foldout arrow's width further left or 5 px further right; the stripe now hangs left of the label, in the spot of the foldout arrow. In UI Toolkit the icon of a notice under a field starts under its label, as in IMGUI; it was 3 px further left. The text of a **Shared reference** notice starts under the field label in both Inspectors; in IMGUI it was 3 px further right. -- In the IMGUI Inspector, a shared `[SerializeReference]` field keeps its type dropdown and the values of its child fields in the column of the fields around, as in UI Toolkit; the gap left for its stripe moved them 5 px right. -- Asset References no longer hangs the Editor on an asset whose `[SerializeReference]` objects point at each other: it drew a card for every path through the graph, and the number of paths grows exponentially. An object now shows its children once, under its first card that is not below a missing type; another field that points at it keeps its own card and field path, with **children on another card** in the footer. The window draws at most 1000 reference cards and says how many it left out; Project References repairs missing types without this limit. An asset with a list of thousands of objects also opens faster. -- `GetDisplayName()` and `GetDisplayNameWithIndex()` no longer append " (Script)" when `[AddComponentMenu]` is inherited from a base class or its path is empty or ends with `/`; such types get the nicified type name. The title now comes from the attribute declared on the type itself, and an `[Obsolete]` type no longer gets " (Deprecated)". -- A `[TypeSelector(nameof(...))]` member reference on a field inside a `[Serializable]` class or a list element now resolves on the instance that declares the field, as analyzers `AFT0006`–`AFT0008` already check it; it used to be looked up on the inspected component or asset and showed a warning. The same applies to the picker of the Asset References window. -- A `[TypeSelector(nameof(...))]` member whose getter throws no longer breaks the field with exceptions in the Console: the field draws without that constraint and shows a warning with the exception message. -- `AFT0007` no longer fails compilation on a `Type?` member under `#nullable enable`, and it now reports a property without a getter, which the Inspector cannot read. `AFT0004` now also reports a `UnityEngine.Object?` field. -- `AFT0005` no longer warns about a generic field or base type (`IState`, `Base`, `typeof(IFoo)`) that has a closed or open generic implementation, or about an implementation through `out`/`in` variance, which also no longer triggers `AFT0003`. Neither warns about a field of a type parameter (`T` in `Slot`). An unbound `typeof(Base<>)` no longer triggers `AFT0003` or `AFT0005` when an open generic implementation such as `Impl : Base` can fill the field. -- `[field: TypeSelector]` and `[field: SerializeReference, TypeSelector]` on an auto-property are now checked by `AFT0001`–`AFT0009`, and `AFT0003` now also covers `SerializableType` and `SerializableMonoScript` fields. -- `AFT0008` now also reports a `[TypeSelector]` type name without an assembly, such as `"Game.IWeapon"`, and names the assembly to add: the Inspector looks such a name up only in mscorlib, so the picker lost its constraint without a compile-time warning. -- A field type or `typeof(...)` argument the compiler cannot resolve (a missing asmdef reference, a class not written yet), or whose base class or interface it cannot resolve, no longer triggers `AFT0001`, `AFT0003`, `AFT0005` or `AFT0009` on top of the compiler error. -- `AFT0005` now warns when a `typeof(...)` class does not fit the field type and no subclass of it does, such as `[TypeSelector(typeof(Sword))]` on an `IShield` field; the selector was empty without a warning. The `AFT0005` message now also names the field type when it narrows the selection. -- `AFT0001` no longer fails compilation on a field of a `[Serializable]` `SerializableType` subclass with a parameterless constructor, which the Inspector draws, and `AFT0007` accepts a member of any `ISerializableType` type, which the Inspector reads. -- `AFT0003`–`AFT0006` name types with their namespace and type arguments, so two closed types of one generic no longer read as `'Slot'` and `'Slot'`. -- **Fix** and **Smart Fix** of a missing type on a saved asset in a UI Toolkit inspector no longer log an exception; reference fields in other inspectors refresh right after the repair. -- A missing `[SerializeReference]` type stored without a namespace is no longer matched to an unrelated class whose `[MovedFrom]` names the same old class: the gate and Project References no longer list it as a pending migration, **Migrate all** no longer rewrites it to that class, and Smart Fix no longer ranks that class first. -- In Edit Mode the *Shared reference* notice, its number and the *Make Unique Reference* item now update right after an edit from an IMGUI inspector, *Link to Existing* or the reference graph window; they used to keep the state from before the edit until the selection changed. -- After you delete an element of an array that holds a `[SerializeReference]` list (a list of structs with a list inside), the list that moves into its place is no longer mistaken for a just-duplicated one; **Auto de-alias** used to split its intentional links, such as ones made with *Link to Existing*, into separate instances. -- An IMGUI `[SerializeReference]` field releases the copy of the object it opens for the context menu, the type picker and **Fix**; a cancelled menu or picker used to keep it until garbage collection, which grew native memory on a large asset. **Make Unique Reference** and a script dropped onto a field whose list element was removed meanwhile no longer throw `NullReferenceException`. -- A `[SerializeReference]` field now always opens to show the new value after a type pick, a dropped script, **Paste**, **Paste Template** or *Link to Existing*; it could stay closed, in the IMGUI Inspector after any of them and in the UI Toolkit Inspector after a drop, a template or a link. -- Selecting several objects whose `[SerializeReference]` field holds the same type now shows that type and its fields for editing together; the field used to show — and *Different types selected* unless the objects were exact copies. -- A type switch now keeps the same instances in `[SerializeReference]` fields inside structs, serializable classes, arrays and lists, and in private `[SerializeReference]` fields without `[SerializeField]` (including `[field: SerializeReference]` auto-properties), like it already did for other nested references; it used to put copies there, so fields that pointed at those instances lost the link. **Make unique** and the fix for a duplicated list element now copy such references with the rest of the reference, so two fields that shared an instance share its copy. -- A nested `[SerializeReference]` field now keeps a custom drawer registered for its declared type through an open generic type (`typeof(Effect<>)`), a base class or an interface, even without `useForChildren`, and a drawer registered for a base attribute class; the package used to draw its own header and type picker over them. In a nested list such a drawer draws each element in both IMGUI and UI Toolkit, and **+** keeps the type picker. A drawer of the stored type alone does not replace the type picker. -- A nested `[SerializeReference]` field without `[TypeSelector]` keeps its `[Header]`, `[Space]` and `[Tooltip]` in an IMGUI Inspector, as in UI Toolkit; IMGUI drew it with no heading, gap or tooltip. -- Several `[Header]` or `[Space]` attributes on one nested `[SerializeReference]` field no longer make the UI Toolkit Inspector throw `AmbiguousMatchException` and leave the object's other fields unbuilt; they are drawn by `order`. -- A nested `[SerializeReference]` list with a custom attribute for each element (a `PropertyAttribute` with a drawer and `applyToCollection` off) keeps its picker-backed **+**; it used to fall back to Unity's plain list, whose **+** adds an element with no type choice. The attribute's drawer still draws each element. -- A custom drawer marked `[SupportedOnRenderPipeline]` for a render pipeline other than the current one, or any marked drawer in the Built-in pipeline, no longer takes the type picker away from a nested `[SerializeReference]` field. Unity does not use such a drawer, so the field was left with neither; the package now ignores it too. -- The per-user settings reset no longer lists the removed "Dropdown without [TypeSelector]" option in its tooltip and confirmation dialog. -- Keyboard focus in the Settings tab is easy to see: the focused row, a reset button, a folder entry of **Excluded scan folders** and its **+** get a strong border. The fill alone looked like the hover. -- Enter on the **Build / CI gate** row of the Settings tab no longer cycles Off, Warn and Fail. The Left and Right arrows step through the values without wrapping, and a step to **Fail** or **Off** asks for confirmation, because Fail breaks the team's builds and Off skips the check. -- `ComponentTypeSelector` now adds the components the new class requires with `[RequireComponent]`, and refuses the switch with a Console warning when it would duplicate a `[DisallowMultipleComponent]` class, remove a class another component requires, or need a component that cannot be added. The required components are added before the new class, so its `OnValidate` finds them. It used to leave the object without the required components or with duplicates. -- `ComponentTypeSelector` no longer lists classes from Editor assemblies on a component of a runtime assembly: a build has no such class, so picking one left a missing script. -- `ComponentTypeSelector` refuses to change the class of a component inherited from a prefab (a prefab instance in a scene, a prefab variant) and shows a Console warning. Unity keeps no override for a changed script, so the new class was lost when the scene or variant was saved and reopened. Change the class in the source prefab; a component added to the instance can still be changed. -- **Create New Script…** on a `[SerializeReference]` field suggests `NewInteractable` for `IInteractable` (was `Newnteractable`) and `NewEffect` for `IEffect` or a generic base class (was the invalid ``NewEffect`1``, rejected on accept). -- **Create New Script…** on a `[SerializeReference]` field now writes a stub that compiles for an abstract class (it overrides every open abstract member and passes the arguments of a constructor that needs them), for `ref`, `out` and `in` parameters and ref returns, for generic methods with their constraints, for indexers, for a base type nested in a generic type, and for an internal base type in its own assembly (the stub is `internal` too); the file used to fail with compile errors that blocked Play Mode in the whole project. For a sealed class, a private or protected nested class, an internal class of another assembly, a class without an accessible constructor, or abstract members that the new script cannot override, a dialog explains why instead of writing the file. -- A saved template whose type does not resolve at the moment (another branch, a removed package, a class moved to another namespace or assembly) is now only hidden from **Paste Template**; opening the context menu used to delete it for good, in every copy of the project. **Paste Template → Remove Missing (N)…** deletes such templates on request, and overwriting one by name says that its type is missing. -- The name prompt of **Save as Template…** opens at the centre of the Editor window. It used to take the centre of the primary display's resolution and could open outside the Editor on a second monitor. -- **Excluded scan folders** accepts only `Assets` and folders under it, the only ones project scans walk; a folder under `Packages/` or elsewhere was saved but excluded nothing. -- Changing **Excluded scan folders** now restarts the baseline of breakage detection: a type that only an excluded folder uses no longer raises a breakage notification, and a folder that is no longer excluded is covered again. -- Breakage detection now also reacts to changes of `.asmdef`, `.asmref` and `.dll` files, which move types between assemblies. A scan that waits for scripts to compile is no longer lost with the domain reload that ends the compile. -- Type picker search no longer matches the assembly part of a type name: short queries such as `Key`, `Token`, `ver` or `null` used to match every type. Search compares the label, the type name and the full name with the namespace and declaring types (`Namespace.Outer.Name`). -- Typing and Backspace in the type picker edit the query again after the Down arrow moves into the results; they used to be ignored until the search field was clicked. -- A type from an assembly that Unity loads while the picker collects the loaded types is no longer missing from the first picker after a domain reload. -- Type picker search lists the exact type name first, then names that start with the query, then names that contain it, and last the types found only through their namespace; `Button` no longer sits behind `ButtonGroup`. Equal matches keep the namespace order. -- Enter in the type picker's search field chooses the first result; it used to do nothing until the Down arrow moved into the list. -- Left arrow in the type picker's search results no longer takes the picker up a level; Esc then opened the list in the wrong folder. -- Type picker search results show the type name first and its namespace after it, dimmed, so a long namespace no longer pushes the name out of the row. -- The Recent section of the type picker no longer goes empty after picks in other fields: the project keeps the last 20 picks, and the section shows the newest ones that the open picker offers, as many as the **Recent items** setting allows. It used to keep only that many picks across all fields. -- On Unity 6000.6 and later, a search that shortens the type picker's list past the selected row no longer overflows the stack, which usually crashed the Editor: the list's refresh reported a selection change, and the picker answered it with another refresh. -- For a missing type the type picker no longer highlights ``, so Enter right after opening does not erase the stored name. -- Picking the type a `[SerializeReference]` field already holds, or dropping its script, no longer creates a new instance: a reference shared with other fields stays shared, and the instance keeps every value. Under a multi-object selection only the objects that hold another type get a new instance. -- The type picker infers a generic argument that the field wraps in an array: for an `IHolder` field, `Box : IHolder` is offered as `Box`; it used to open the argument page. -- Generic argument pages of the type picker offer only types that meet constraints naming a type parameter (`where T : IComparable`, `where U : T`) and keep the generic type assignable to the field; such a choice used to fail with an error after the click. A `where T : unmanaged` parameter no longer accepts a struct that holds references, from which the picker built a type C# would reject. -- The type picker no longer offers open generic types that no argument fits into the field, such as `RefHandler where T : class` for an `IHandler` field or `Dictionary<,>` for an `IEnumerable` field; every choice on their argument page failed. -- For a field of a variant generic interface, such as `IHandler` or `IProvider`, where other arguments fit too, the type picker keeps the closed row inferred from the field, `Handler`, and adds the open row `Handler`: its argument page offers the other arguments that fit, such as `object`. It used to offer only the inferred row. -- Two nested types of the same name, such as `PlayerController.State` and `EnemyController.State`, no longer show as identical rows in the type picker: the outer class tells them apart, `State (PlayerController)`. The row tooltip reads `Namespace.Outer.Type, Assembly` with generics spelled `Box`, not the CLR name with the assembly version, and a type nested in a generic class lists only its own arguments (`Inner`, not `Inner`). -- The type picker no longer offers the compiler's static-data structs (`__StaticArrayInitTypeSize=12` in the `` group): types nested in compiler-generated types are left out. -- The key hint at the foot of the type picker fits the 400 pt window: **Type to search** and **Esc Close** used to be cut off. The arrow keys left the hint, and the favorite key reads `Space ☆`. -- A `[TypeSelectorDisplay(Icon = "SwordIcon")]` icon from `Resources`, named without a `/`, loads without the "Unable to load the icon" error in the Console. Such a name is looked up in `Resources` first, so a `Resources` texture now wins over a Unity icon of the same name. -- The type picker opened from the **+** of a `[SerializeReference]` list is placed by its real width of 400 pt instead of 350 pt, so it no longer runs 50 pt past the right edge of a narrow Inspector. -- The **Missing type** mark of a `[SerializeReference]` list element stays on that element after you delete, move or add elements and before you save; it used to follow the old index, so it moved to another element or disappeared. While the edits leave it unclear which element a slot holds, the slot shows no mark until the save. A reference inside an element of a list of plain classes or structs still follows that element's index until the save. A missing reference that you set to `` or paste an empty reference over no longer shows **Missing type** until the save; Undo brings the mark back. -- **Fix** on a missing `[SerializeReference]` list element of an asset with unsaved list edits now applies the chosen class after **Save and Continue**; the save gave the element a new id, so the fix used to do nothing until you clicked it again. -- A `SerializableType` field or a `[TypeSelector]` string selected on several objects with different values now shows "—", and the type picker highlights no row; it used to show the type of the first object, as if all objects held it. -- In a UI Toolkit Inspector, choosing `` now clears a `SerializableMonoScript` whose type is missing; the field used to keep showing ``. -- A `SerializableType` field or a `[TypeSelector]` string overridden on a prefab instance shows its label in bold and offers **Apply to Prefab** and **Revert** in its context menu; it could be reverted only from the component menu. A UI Toolkit Inspector still does not draw the blue override bar at its edge. -- The type picker of a `SerializableType` field, a `[TypeSelector]` string and `TypeField` offers generic classes for a closed generic base type, such as `Handler` for `IHandler`, as `[SerializeReference]` fields already did. -- `TypeField.Types` drops `null` entries; a click on the field used to throw `NullReferenceException` and open no picker. -- The type field (`TypeField`, and the `SerializableType` and `[TypeSelector]` string fields of a UI Toolkit Inspector) shows the full name of the selected type with its namespace and assembly as its tooltip, so two classes with the same name can be told apart; the open-script button has a tooltip too. -- A bound `TypeField` updates the `SerializedObject` of its property before it sends `ChangeEvent`: a change handler reads the picked type from that property, and edits the handler applies through that object no longer undo the pick. -- A `TypeField` bound to several objects no longer refreshes its display every 100 ms when no value changed, and stops checking once a target is destroyed. -- A `PropertyField` over a `SerializableType`, `SerializableMonoScript` or `[TypeSelector]` string now sends a `ChangeEvent` with the old and the new type name when a type is picked or a script is dropped on the field. It used to send none; Unity 6000.4 only passed on the event of the caption text, such as `Int32`. -- With several objects selected, a `SerializableMonoScript` field whose objects differ shows `—` without a script button, not the first object's type (UI Toolkit, IMGUI). In UI Toolkit, picking that first type now writes it to the other objects; it used to write nothing. -- In an IMGUI Inspector, a `SerializableType` or `[TypeSelector]` string field whose selected objects differ no longer shows a script button that opens only the first object's script, and a disabled `SerializableMonoScript` or `[SerializeReference]` field no longer accepts a dragged script. -- The UI Toolkit drawer of `SerializableType` and `[TypeSelector]` strings no longer leaves a `SerializedObject` copy behind on every refresh, and no longer throws `NullReferenceException` when its property is gone, such as a removed list element. -- The IMGUI type pickers of `SerializableType`, `SerializableMonoScript`, `[TypeSelector]` strings and `ComponentTypeSelector`, and the **→ TypeName** suggestion, no longer keep a copy of the object until garbage collection after a cancelled pick, which grew native memory on a large asset; the copy opens when a type is picked and is released at once. The UI Toolkit drawers of `SerializableMonoScript`, `[TypeSelector]` and `ComponentTypeSelector` no longer hold a copy of the object for as long as their Inspector is open. A component destroyed between the pick and the `ComponentTypeSelector` swap no longer throws, and the UI Toolkit drawer of `SerializableType` and `[TypeSelector]` strings keeps refreshing when its Inspector has already disposed its `SerializedObject`. -- **+** of a `[TypeSelector]` `[SerializeReference]` list nested in an element of another array (a list of structs, a list inside a list element) now appends to that list; it used to throw `InvalidOperationException` and add nothing. -- **+** of an array whose elements contain a `[TypeSelector]` `[SerializeReference]` field (such as `WeaponSlot[]`) now adds a regular element; once the array had an element, it used to open that field's type picker and throw. -- **+** of a managed-reference list with several objects selected now appends an independent instance to every object in one Undo group. In IMGUI it used to change only the first object; in UI Toolkit the new element shared its instance with the previous one. -- The `EnumValues` Inspector no longer rewrites keys while drawing: a row whose key the enum cannot parse (after switching `EnumValues` to another enum, or renaming or deleting a member) shows its key as, for example, `` and keeps it until you pick a member. It used to get the enum's first member, so switching the type back did not bring the rows back. A row added to an empty table now shows `` and is skipped with an error until you pick a member; it used to get the first member automatically. -- The `EnumValues` Inspector no longer writes to the asset while drawing: it used to add an Undo entry and mark the asset changed when a row's copy of the enum type differed from the table's. Rows no longer store that copy, so moving an enum no longer shows up in every row of a diff or merge; the old `_enumType` line of a row disappears from an existing asset the next time it is saved. -- **Populate Missing Enum Members** now works when the value is an array or a `List`; it used to throw and leave a half-created row. For an enum with aliases (`Default = Medium`) it adds each value once and is disabled once every value has a row; it used to add a duplicate on every click. -- **Populate Missing Enum Members** is disabled while several objects are selected, and it skips `[Obsolete]` enum members. With several objects selected it used to set one array size on all of them: an object with more rows lost the extra ones, and the rest were overwritten with the rows of the first. -- An `EnumValues` row of a `[Flags]` enum based on `long` or `ulong`, or on `uint` with a member in bit 31, gets a flags dropdown that keeps every bit; for a 64-bit enum the IMGUI Inspector used to throw on every repaint, and the UI Toolkit one showed a wrong mask and stored a different key. -- An `EnumValues` row whose key is an `[Obsolete]` enum member, or for a `[Flags]` enum includes one, now shows the key by name. The dropdown used to be empty, or read `None` or `Everything` for flags. -- In the UI Toolkit Inspector the key dropdown of an `EnumValues` row now follows Undo, Revert and Paste, and the table header shows the label passed to `PropertyField` instead of always the field name. -- The `EnumValues` drawer no longer throws `NullReferenceException` when Unity finds no field for the property. -- The type picker of `EnumValues` no longer offers the abstract `System.Enum`. Picking it filled the field, so the required check stayed quiet, but the table could never match a row and always returned **Default Value**. -- `EnumValues` initializes its rows safely when the first access comes from several threads: on a CPU with weak memory ordering another thread could see the table as initialized before its rows and return **Default Value** for a row that exists. -- The `EnumValues` enumerator returns `default` from `Current` after `MoveNext` returns `false`, as its documentation says. It used to keep the last row. -- Choosing **Everything**, or ticking every flag, in the key dropdown of an `EnumValues` row of a `[Flags]` enum now stores the enum's defined flags, for example `Left, Right`. It used to store `-1`, and `GetValue` never found that row. -- In the IMGUI Inspector, an `EnumValues` row whose value is a `Rect`, `RectInt` or `Bounds` is now as tall as that field and no longer overlaps the next row, and the notice of the enum type field (**Required type is not set**, **Missing type**) no longer draws over the table below it. -- Undo after **Fix** of a missing type in an open scene or Prefab Mode brings back the missing reference with its stored data; it used to leave the field empty, and the next save wrote `rid: -2`. The replaced entry is now dropped when the scene or prefab is saved (Prefab Mode Auto Save saves right after the Fix), so Unity's missing-types notice stays until then; that save also clears the object's Undo history, so the repair can no longer be undone. -- **Fix** of a missing type in an open scene or Prefab Mode now repairs every field that shares the missing reference, and the fields keep sharing one instance; the other fields used to show `` without **Fix** until the save, which wrote them empty. The class picker and the **→** suggestion offer only classes that fit every such field. -- **Fix** of a missing type in a scene or Prefab Mode carries more of the stored data over to the new class: floats that Unity writes with an exponent (`9.99e-05`) were lost, text with non-ASCII characters, tabs or line breaks used to keep its quotes and escape codes, long text lost the part Unity wraps onto the next lines, `Infinity` and `NaN` became 0, and text such as `1.5` became `1.500000`. A value the new class cannot take no longer drops the other fields. -- The package's editor assembly now compiles on Unity 6000.5, where `Object.GetInstanceID()` became an error (CS0619); it used to leave the project in Safe Mode with every editor tool of the package broken. -- `Aspid.FastTools.VisualElements.Math` now compiles on Unity 6000.5 and later in a project without `com.unity.mathematics`. `Unity.Mathematics` ships in the engine there, but `SetValue` and `AddValueChanged` for `float2`, `int3` and the other types stayed missing until the package was installed. -- Fields drawn in a regular Inspector, UI Toolkit or IMGUI, now follow the light editor skin: the `EnumValues` drawer takes its backgrounds from Unity's theme, reference notices and the missing-type caption of `[SerializeReference]` fields use Unity's warning colour, and the warning, info and folder icons switch to their light-skin variants. -- The type picker is readable on the light editor skin: opened from an Inspector field it takes a light palette, with light-skin folder, Favorites and Recent icons; it used to draw the dark palette's light text on Unity's light popup background. -- Help boxes in the FastTools windows read at 4.5:1 or more on every status colour: their title and message take the strongest text shade. On the light skin, help boxes take the light-skin icons, and status-coloured links and actions are darker. In the type picker dropdown, the counts, arrows, hints and error text are brighter on the dark skin and darker on the light one; on the light skin the Favorites star is darker too. In the Inspector on the light skin, the *Shared reference* notice darkens its text and **Make unique**, while the dot and stripe keep their colour. On the light skin, hovered notice links turn darker instead of paler. The hovered remove button in Excluded Folders reads better on both skins. -- The Welcome tab of the FastTools window takes the theme too; it kept the built-in palette. -- The version, the **GitHub** link and the logo of the FastTools window show the link cursor on hover, and the version and the keys hint in the footer use a higher-contrast text tone that is easier to read. -- The keys hint in the footer of the FastTools window no longer runs over the version in a narrow docked window: it gets the space between the version and the link and ends with an ellipsis when it does not fit. -- The keys hint in the footer of the FastTools window names the Left and Right arrows (`←→ adjust`) on the Settings tab, where they step the **Build / CI gate** and the sliders. The other tabs, where these arrows do nothing, keep `↑↓ navigate ⏎ activate esc dismiss`. -- When the package sits in `Assets` outside `Assets/Aspid/FastTools` (an Asset Store import moved to another folder), the footer shows its version instead of `v?` and the Welcome tab lists its samples; the package folder is now found by the GUID of its `package.json`. -- **Import** of a sample on the Welcome tab no longer fails silently when the project holds a copy of that sample from an older package version: it asks to replace the old copy and imports the current one. It used to show "Failed to import" and copy nothing. -- The Welcome window opens once after an update of a package installed into `Assets` (Asset Store, `.unitypackage`); the "already shown" flag followed a version that was always `unknown` there, so it never changed. -- Importing the package into `Assets` (Asset Store, `.unitypackage`) no longer logs five "Asset reference to GUID … was moved" warnings for the Welcome window: it takes its style sheet and logo from Resources instead of links by asset path. -- The Welcome window no longer promises "string ID tooling", which the package does not have; its text names the main features. -- A theme now recolours the cards, panels, status tints, scrollbars, dots background and switches of the Aspid windows: their colours moved into `--aspid-colors-*` tokens, and switches read the optional `--aspid-colors-switch-*` tokens. -- The borders of the dropdowns and the slider value box, and the slider track, in the Settings tab and in its pages in Project Settings and Preferences reach 3:1 contrast on the dark and the light skin; they were barely visible. The new `--aspid-colors-control-border` token sets their colour, so a theme can change it. -- On Unity 6000.0–6000.2 the `[SerializeReference]` field, the picker and the Project References and Asset References windows are styled again: two stylesheets used a color syntax these versions cannot parse, so each was dropped whole and the import logged an error. -- Buttons and foldouts inside a `[SerializeReference]` field drawn with UI Toolkit keep their own look: a button of a custom drawer or a nested list's `+` / `−` is no longer shrunk to 18×18 with a folder icon, and a nested foldout no longer takes the field header's layout. -- With several objects selected whose `[SerializeReference]` fields hold different types, the UI Toolkit field now tints its "—" like Unity's own mixed-value fields; it used to show it in the plain text colour. -- Fix, Fix all and the summary's Undo no longer rewrite the type of a healthy managed reference when a `[SerializeReference]` list inside another reference points at the broken one (a parent with a list of children). The Inspector reads the right stored type and fields of such references, and the Project References graph no longer shows phantom nodes whose Clear deleted healthy entries. -- When fields of different types share a missing reference, the class picker and **Smart Fix** in Asset References offer only classes that fit all of them, and so do those of a Project References group whose references all have the same field types; a `[MovedFrom]` target counts as a pending migration only if it fits all of them. They used to check one of the fields, so the others became empty after the rewrite. -- The missing-list guard now snapshots a missing list element that another reference's list also points at, and restores it into the object's own list instead of a same-named list nested in another field. -- The missing-list guard no longer brings back a missing list element after you delete it or set it to `` and save; when you delete another element, it restores the missing ones at their new indexes. If the deleted element sat among other missing or `` elements, the saved file doesn't say which one it was: the guard keeps the `` elements and the first missing ones and leaves the last missing one out. Loaded scenes and prefabs saved from Prefab Mode are no longer guarded: the guard doesn't rewrite their files and doesn't restore their missing list elements. -- A dropped script, **Paste Template**, *Link to Existing* and **Create New Script…** on a missing list element now tell the missing-list guard that the element was replaced, as the type picker and **Paste** do; after such a replace and the deletion of another element, the save could lose a different missing element of the same list. -- A list element restored by the missing-list guard keeps its original reference id when it is free, otherwise gets a random one. It used to take the next id after the file's maximum, which an override in a variant, nested prefab or scene often already used: that override lost its type and shared data with the restored element. -- The missing-list guard finds the slot of a missing element by the reference ids of the other elements, so the element survives a reorder, a delete plus an add, an insert or a move in the same save; the guard used to look at the old index and silently drop it. A missing element that two slots share comes back in both of them, and a `` pick on one of them no longer drops the other. -- The missing-list guard keeps a `` pick on a missing element after a script reload and after an Undo of another edit; only a save that writes the file uses it up, and a change to the file outside the editor, such as a revert in version control, cancels it. Its Console message names the restored elements and warns about the missing elements it found no slot for, with their index and `rid`. The guard reads and writes the file once per save and skips files without managed references, so saving a list of thousands of elements no longer freezes the Editor, and an edit made right after a save is no longer lost when the guard rewrites the file. -- Objects with a negative fileID (prefab components, sub-assets) are now read as separate documents: their missing references reach the scans and the build gate, their unset required fields reach the scans, and Fix, Clear and orphan removal no longer edit or delete entries of the neighbouring object. -- The SerializeReference scans now read Animator Controllers (`.controller`) and Timelines (`.playable`), so missing types in their state machine behaviours, tracks and clips reach Project References, the build gate and breakage detection; these files used to be skipped. -- A `[SerializeReference]` type whose class, namespace or assembly name has characters outside ASCII (Cyrillic, CJK) is no longer reported as missing by the scans and the build gate, and the delete guard now finds its usages. Unity writes such a name as `\uXXXX` escapes in double quotes, which are now decoded; the same applies to the names stored by `SerializableType` and `SerializableMonoScript`. -- A `[SerializeReference]` field of a prefab variant, nested prefab or scene instance whose type is missing now shows **Missing type** instead of an empty ``; the tooltip names the source prefab to repair, or says the type is stored in a prefab override. A required field with such a missing type no longer counts as unset in `-srGateRequired` and the References windows. -- A new element of a `[SerializeReference]` list that is empty in the saved file no longer shows the **Missing type** of an element of the next list until the asset is saved. -- The breakage notification no longer waits for Project References to scan the project in the session: a background read of the asset files at session start sets its baseline, and assets saved later update it, so a type first assigned during the session is covered too. A type that breaks before that read completes is not reported. -- Deleting a script that declares only components or ScriptableObjects no longer scans every asset of the project; for other scripts a progress bar appears when the check takes long, and cancelling it cancels the delete. -- The delete guard now warns for every type declared in a script, including a file with no class named after it (`Pistol` and `Rifle` in `Weapons.cs`) and nested types (`Outer.Inner`); it used to check only the class named after the file. A `partial` type counts only when no remaining script declares another part of it. -- The delete guard no longer slows down when you delete many scripts or a large folder: assets without managed references are skipped before any class name is searched, and of the several scripts or folders in one delete only the first sweeps the whole project, while the others re-read just the assets that hold managed references. Cancelling the progress bar cancels the delete of that script or folder and of every later one that needs the check. -- One answer of the delete guard can cover the whole delete. When the Project window selection holds more scripts or folders, its dialog gets a third button, **Delete All Anyway**, and **Cancel** keeps every other script or folder of that delete that is still used, without asking again; **Delete Anyway** still answers for one script and asks again for the next. The answer ends with the delete, so the next delete asks again. The dialog of a single script or folder is unchanged, and a delete from code that selects nothing shows the plain dialog first and the third button from the second dialog on. -- The SerializeReference scans skip binary assets and Git LFS pointers after reading their first bytes, instead of decoding every file as text on each build. The build gate and the CI check warn when files went unchecked (any binary file outside **Force Text**, a binary prefab, scene or ScriptableObject in **Force Text**, a pointer that was never pulled), and the CI report counts and lists them; before, such a project passed with 0 violations. -- The build gate and the CI check now warn about a file whose managed references are stored in an older format (`references: version: 1`, an asset last saved before Unity 2021.2) or in a format they do not know, and the CI report lists it as `UnsupportedReferencesVersion`; such a file used to pass as clean. The header line of the report is now `# Not scanned: N`, without `(not text YAML)`. -- The project scan of managed references (the index behind **Find Usages**, the delete guard and breakage detection) no longer builds a field path for every pointer of a file: a file with a list of 8000 references took about 9 seconds to read, now about 0.2 seconds. -- A `[TypeSelector(Required = true)]` array or list in a scene is no longer reported as unset by `-srGateRequired` and Project References; scenes skip collections, as documented. -- Project References no longer shows "Project clean" or "Nothing left to repair" while required fields are unchecked (before the first Scan Project, after a clear in Prefab Mode or an open scene, or with gate severity Off); it says why they were not checked and to Rescan. Clearing references on disk now re-checks the edited files and the variants and prefabs nesting an edited prefab, so their required violations stay listed and the header warns about them. -- Project References no longer says "Project clean" when Scan Project could not read some files: binary files and Git LFS pointers are counted in the window and listed in the Console, and Asset References shows "Not scanned" instead of "No managed references" for such an asset. It no longer says there are no type names when only the index was warm (after Unity Search or another tool read it); it asks to **Rescan**. The hint about **Fix all** appears only when a broken group is listed, and a hint beside type names or required violations says they are as of the last scan. -- A file that cannot be opened (another program has it locked, no read permission, removed during the scan) is no longer called binary by the SerializeReference scans: the build gate and the CI check warn that it could not be opened and to close the program that holds it, instead of advising **Force Text**; the CI report lists it as `Unreadable`, `-srGateStrict` counts it like the other unchecked files, Asset References names the real cause, and Project References counts the file and points to the Console. The scans also read a text asset that another program has open for writing (Windows refused it before) and list a file that turns unreadable between the format check and the read, instead of passing it as clean. -- The summary after **Fix all** and **Clear** in Project References now shows how many entries could not be rewritten (a read-only or locked file, an entry that changed since the scan) and points to the Console; a fix that changed nothing says so instead of "Rewrote 0". -- The required-field sweep of `-srGateRequired` and Scan Project now unloads the prefabs and assets it loaded, so its memory no longer grows with the size of the project. -- Project References no longer loads every affected prefab again each time you switch to its tab, which froze the window when a broken class is stored in hundreds of prefabs. The field types of a group are read once and kept until a prefab or asset is imported or you Rescan, the prefabs this loads are released in batches, and a required-violation row takes its component name from the scan instead of loading its file again. A group lists its first 200 entries, and **Show more** adds the next 200. -- Scan Project shows a progress bar for the required-field sweep, and both sweeps can be cancelled. A cancelled scan keeps the earlier results and summaries. -- Under `Warn` the CI check logs its violations as warnings instead of errors, so a wrapper that looks for errors in the log no longer takes a run with exit code `0` for a failure. -- The build and CI logs list at most 50 violations, count the rest, and carry no stack trace; the CI report still lists them all. A CI run whose report folder does not exist now logs the violations before it fails. -- Clearing references and repairing type names in Project References no longer ask Unity for the dependencies of every prefab in the project on each action to find the variants and prefabs nesting the edited one; the map is built once per Scan Project. -- Assign Required for a `SerializableMonoScript` field in Asset References now offers only types with a script asset, as the Inspector does; it used to accept nested, generic and DLL types and drop the script reference. -- An unset required `SerializableType`, `SerializableType` or `SerializableMonoScript` field of a prefab or ScriptableObject is now reported by `-srGateRequired`, the CI report and the References windows under its own path (`weaponType`), as in a scene; the path used to end in `._assemblyQualifiedName`. -- In the editor, `SerializableMonoScript` now takes the type from its script when the stored name no longer resolves, so an object loaded in Play Mode after a class rename (an additional scene, `Resources.Load`, entering Play Mode without domain and scene reload) no longer gets `null` before its asset is saved again. -- `SerializableType` and `SerializableMonoScript` now cache a failed lookup as well: reading `.Type` of a missing type no longer calls `Type.GetType` every time, and the cache resets when the stored name changes. -- In the editor, serializing a `SerializableMonoScript` off the main thread no longer calls `MonoScript.GetClass`, which works only on the main thread; the stored name re-syncs on the next main-thread save. -- Fixing a missing `[SerializeReference]` type (retype, clear, remove an orphan, restore a list element) now checks the asset out in version control first, as Unity's own saves do. A read-only asset is left untouched with a clear error instead of an access exception, the edit replaces the file in one step so a failed write no longer leaves it truncated, and a UTF-8 byte-order mark is kept. -- The repairs that edit asset files directly (missing `[SerializeReference]` types, missing type names, restored list elements) now check the edited text before they replace the file. When the edit would lose or cut into another object or managed reference, or the file changed on disk after the repair read it, the file is left untouched with an error. -- A repair that edits an asset file no longer replaces bytes that are not valid UTF-8 with U+FFFD across the whole file; such a file is left untouched with an error. -- Clearing a missing `[SerializeReference]` reference no longer sets a field of your own named `rid` to `-2` when it holds the id of the cleared reference; only the fields and list elements that point at the reference are nulled. -- The SerializeReference scans and repairs read and write ids such as `rid: -2` and negative fileIDs the same way in every system locale. On the CoreCLR runtime, a Swedish, Finnish or Norwegian locale wrote `−2` with a Unicode minus sign that Unity cannot read, and an Arabic, Hebrew or Persian locale failed to read negative ids. -- The shared SerializeReference settings (**Build / CI gate**, **Excluded scan folders**, **Auto de-alias duplicated list elements**) now follow `ProjectSettings/SerializeReferenceSharedSettings.asset` while the Editor is open. The settings page, a change of one setting (including adding or removing an excluded folder), **Scan Project** and the build gate re-read the file, so values pulled from the repository are no longer kept stale or overwritten by the next change. The file is also checked out in version control before it is written; if it stays read-only, the setting keeps its value and an error says why, instead of reverting after a restart. -- Repairing a missing type no longer silently discards unsaved changes of the asset being repaired. **Fix** and **Smart Fix** in the Inspector and repairs and clears in Asset References offer to save such an asset first; **Fix all**, **Clear** and **Undo** in Project References skip it or clear it in memory. **Fix** in the Inspector no longer rewrites a prefab asset that is open in Prefab Mode. -- Changing the type of a healthy reference or filling an empty or required field in Asset References (**Change ▼**, **Assign ▼**, **Assign Required ▼**) no longer writes into a prefab that is open in Prefab Mode; a dialog asks you to close it first. The change used to go into the file, and the next save of the stage overwrote it. -- The summaries in Project References and their **Undo** now survive a switch to another tab of the window, including the jump to Asset References from an entry row; they used to disappear with the tab. **Rescan**, closing the window or a domain reload still clears them. -- The FastTools window reopens on the tab you left after a script recompile or entering Play Mode; it used to return to Welcome. -- **Tools → Aspid 🐍 → FastTools → Asset References** with nothing selected, or with a selection it cannot map (a scene object that is not a prefab instance, a folder, a texture), keeps the asset the tab already shows; it used to replace it with an empty target. -- `this.Marker()` inside a `private` or `protected` nested type no longer breaks compilation with CS0122. The generated overload cannot see such a type, so the generator now skips it: the call compiles, opens no marker, and `AFT0010` reports it — make the type `internal` or `public` to profile it. -- `this.Marker()` in a type nested in a generic type (`Outer.Inner`) now compiles; the generated overload used to miss the outer type parameters (CS0246). -- `this.Marker()` in an indexer accessor or a static constructor now compiles; the generated field names were invalid. The markers are named `Type.Indexer (line)` and `Type.StaticCtor (line)`. -- `this.Marker()` in an event accessor is now named after the event, like a property accessor: `Type.Changed (line)` instead of `Type.add_Changed (line)` / `Type.remove_Changed (line)`, including explicit interface implementations. -- `this.Marker()` no longer breaks compilation in an auto-property initializer, a static class or a default interface method, in a namespace or type parameter named with a keyword (`Game.@event`, `Foo<@event>`), or when type names differ only in case or flatten to the same name (`Foo`/`foo`, `Foo`/`Foo_1`, `Outer.Inner`/`Outer_Inner`); some of these made every marker of the assembly disappear. -- `this.Marker()` in an `[Obsolete]` type, a type nested in one or a generic type constrained to one no longer raises CS0618 in the generated code, and in an `[Obsolete(..., true)]` type no longer breaks compilation with CS0619. -- `Foo`, `Foo` and `Foo` in one namespace no longer share one generated class in which only the first type got markers; the package's own `EnumValues` markers now open. -- A `this.Marker()` call split over several lines or under a `#line` directive now opens its own marker; the generator used a different line than `[CallerLineNumber]`. -- A generic struct marked `[BurstCompile]` no longer fails the Burst build (BC1025/BC1360). -- A type deriving from a type of another assembly that shares its namespace through `InternalsVisibleTo` now gets markers of its own; its calls used to bind to the base type's overload and open nothing. -- `WithName($"Br{{ace}}")` gives `Br{ace}`, `WithName` text with U+2028, U+2029 or U+0085 compiles, and a user's own `WithName` extension no longer renames the marker. -- `WithName` now reads a `const`, `nameof(...)` and a concatenation or interpolation of constants; such a name used to leave the member name without a warning. -- `Persistent()` no longer leaks the `SerializedObject` it creates when the property path no longer exists on the targets; it disposes that object before returning `null`. -- `AddChildren`, `InsertChildren` and their `…If` variants with an `IEnumerable` no longer throw `InvalidOperationException` ("Collection was modified") when given `Children()` of another element: `target.AddChildren(source.Children())` moves every child. -- `TryGetByEnum` returns `false` for a USS number that is not a member of the enum (`--preview-theme: 7;`) and for a comma-separated list on an enum without `[Flags]`, so the element keeps its default instead of an undefined value. A `[Flags]` enum accepts names only. -- Types sample: the `Enemy Type` picker no longer offers the abstract `Enemy`, which spawned empty capsules and an error per enemy; the rename step of its tutorial now uses the IDE's Rename refactoring, so `ArmoredGrunt` keeps compiling. -- Types sample: `Brute` no longer sinks halfway into the platform; its height now follows its scale. -- SerializeReferences sample: no more CS0414 warning on import, and deleting the Training Dummy in Play Mode no longer throws `MissingReferenceException` on every shot. -- EditorTools sample: the Ability Catalog window follows assets created or deleted in the Project window, and **Create** selects the new asset even while a search is active. -- EditorTools sample: the Ability Catalog window keeps its search text in the saved window layout, so it survives an Editor restart. -- EditorTools sample: the Ability Catalog window disposes the `SerializedObject` of the ability it showed when you select another one or close the window; it used to keep each until garbage collection. -- EnumValues and ProfilerMarkers samples no longer break compilation of a project without the built-in Physics module; their scripts are skipped there, and the sample descriptions say they need it. -- EnumValues sample: the Walker no longer puts `[InspectorName]` on fields, where Unity ignores it (it reads the attribute only on enum values); its Inspector labels are **Step Interval** and **Footprint Lifetime**, and **Log Tables** prints the same label. -- Types and SerializeReferences samples: the descriptions say that the colliders of their scenes need the built-in Physics module. -- The package's internal editor elements (`AspidBox`, `AspidLabel` and ten more) no longer show in the UI Builder Library of your project: they are made for the FastTools windows and look unstyled in your UXML. -- The tab icon of the FastTools window is a 64×64 texture with mipmaps (7 KB) instead of a 1022×1011 one without them (583 KB): the package is smaller and the icon edges stay smooth at 16 pt. -- `Persistent()` keeps the `context` of the source `SerializedObject`, so an `ExposedReference` read or written through the copy resolves in the same table (for example a `PlayableDirector`) instead of the default value in the asset. -- *Link to Existing* in the `[SerializeReference]` context menu now offers only instances the field's type picker accepts under its `[TypeSelector]` base types, including member-referenced ones; it used to offer any instance assignable to the declared field type. -- A generic class picked in the `[SerializeReference]` type picker now fits every `[TypeSelector]` type: a closed type outside the attribute, such as `Modifier` under `[TypeSelector(typeof(IModifier))]`, shows an error. It used to be stored although the attribute rejects it. -- The type picker infers generic arguments from every `[TypeSelector]` type: when they pin every argument, as `[TypeSelector(typeof(IModifier))]` pins `Modifier` to `Modifier`, picking the generic closes it at once. It used to look only at the field type of a `[SerializeReference]` field, and at the first `[TypeSelector]` type elsewhere. -- On a generic argument page of the `[SerializeReference]` type picker, a nested generic is checked like any other argument: a class without `[Serializable]` and a .NET generic struct such as `Nullable` or `KeyValuePair<,>`, whose values Unity silently drops, are no longer offered. Your own `[Serializable]` generic struct can now be a nested argument, as in `Container>`. -- The `[SerializeReference]` type picker no longer offers or accepts, as a generic argument, a .NET type that carries `[Serializable]` but whose values Unity silently drops: `DateTime`, `TimeSpan`, `Guid`, `Decimal`, `Dictionary<,>`, `HashSet`, `Queue`, `Stack`, `LinkedList`, `Tuple<…>`, `object` and `IntPtr`. Among the .NET types Unity serializes only primitives, `string`, enums, `T[]` and `List`, so those still fit; a multidimensional or jagged array, a `List>` and a collection of an element Unity drops are rejected as well. Your own `[Serializable]` types are not affected. -- `SerializeReferenceEditorGUI.CreateField` and `DrawFieldLayout` now add the `[TypeSelector]` constraints of the field to `baseTypes`, as `CreateList` already did. The type picker used to offer every type that fits the declared field type, where `PropertyField` offers only the selected ones. `CreateField` reads the constraint once, when the field is created. -- *Find Usages* in the `[SerializeReference]` context menu now lists usages of the exact type in the field (namespace and assembly included); it used to match every stored class name containing its name, such as `PistolMk2` or a `Pistol` from another namespace. A typed `sr:` query still matches class names by substring. -- *Find Usages of …* and *Link to Existing* in the `[SerializeReference]` context menu name a generic type as the type picker does, `Modifier` or its `[TypeSelectorDisplay]` name; they used to show ``Modifier`1``. A `/` in a display name no longer opens a submenu. -- In the default UI Toolkit Inspector, **+** of an empty `[TypeSelector]` `[SerializeReference]` list now opens the type picker; it used to append a `` entry, and the picker appeared only once the list had an element. -- The breakage notification and the breakage detection setting point at Project References; they still named its old tab, Repair. -- An `EnumValues` table in an array or a list is titled `Element 0`, `Element 1` and so on, as other array elements are; it used to show the full name of its enum type, since Unity names an element after its first string field. A long title ends in an ellipsis inside the card instead of running past its border, in both the UI Toolkit and the IMGUI Inspector. - -## [1.0.0-rc.8] — 2026-09-06 - -First release. Unity **6000.0**, assemblies `Aspid.FastTools` / `Aspid.FastTools.Editor`, prebuilt Roslyn DLLs `Aspid.FastTools.Generators` / `Aspid.FastTools.Analyzers`. Every inspector feature works in both IMGUI and UI Toolkit. - -### Added - -#### Serializable Type System - -- `SerializableType` / `SerializableType` — `[Serializable]` wrapper over `System.Type`, lazy resolution, implicit conversion to `Type`, `Type`-taking constructor, `AssemblyQualifiedName`. -- `SerializableMonoScript` / `SerializableMonoScript` — the same, referenced through the script asset so renames and moves do not break it; the player serializes the name alone. -- `SerializableTypeBase` and `ISerializableType` for polymorphic access to any wrapper. -- `[TypeSelector]` — a hierarchical type picker on `string`, `SerializableType` / `SerializableMonoScript` and `[SerializeReference]` fields, and on arrays / lists of them. Base-type constraints, `Allow` (`TypeAllow`), `Required`, member references in string arguments (`Type`, `string`, `SerializableType`, arrays of these, resolved live). -- `[TypeSelectorDisplay]` — `Name`, `Group`, `Tooltip`, `Icon`, `Hidden` for a type's row in the picker. -- `ComponentTypeSelector` — swaps a sibling `Component` in place through a type dropdown. -- `TypeSelectorWindow` with a public `Show(...)` API: namespace tree, search, keyboard navigation, Favorites and Recent, `TypeSelectorFilter` (`Predicate`, `AdditionalTypes`, `HideNoneOption`). -- `TypeField` / `InspectorTypeField` UI Toolkit elements behind the drawers. - -#### SerializeReference Selector - -- Type dropdown on `[SerializeReference]` fields, nested references included (8 levels deep); custom drawers and `[Header]` / `[Space]` / `[Tooltip]` are honored. -- Open generic implementations: arguments inferred from the field's type arguments and interfaces, otherwise collected on a second picker page. -- Data carry-over on type switch, Copy / Paste, multi-object editing, duplicate de-aliasing. -- Shared-reference notices with **Make unique**, color-coded groups and member navigation. -- Drag a `MonoScript` to assign, named templates, **Link to Existing**, picker-backed list `+`, **Create New Script…**, **Find Usages**. - -#### Missing-reference repair - -- Inline **Fix** on a missing type, keeping the stored data; works for saved assets, Prefab Mode and scene objects. -- **Smart Fix** ranks the likely replacement (`[MovedFrom]`, same name elsewhere, casing, field-shape match). -- `[MovedFrom]` renames are shown as pending migrations with one-click **Migrate all**, never as violations. -- Breakage notification after a script rename / delete or reimport; delete guard for scripts used as managed references; YAML diff preview before every bulk rewrite. - -#### Workbench window (`Tools → Aspid 🐍 → FastTools`) - -- **Welcome** — samples with install markers; auto-opens once per package version. -- **Asset References** — the asset's whole `[SerializeReference]` graph from YAML with a warning band on missing types and `SHARED` badges, inline Fix, Clear for orphans, Open Source Prefab. -- **Project References** — `Scan Project` over `Assets/`, **Fix all** per type with Undo, Smart Fix, Migrate all, Required violations. -- **Settings** — all package settings with shared / per-user scope stripes and per-scope reset. -- Keyboard navigation, legends, row context menus on every tab. -- Project-wide usage index, `sr:` Quick Search provider. -- Build / CI gate: `IPreprocessBuildWithReport` plus headless `SerializeReferenceCiGate.RunCheck` with `-srGateReport`, `-srGateRequired`, `-srGateWarnOnly`, `-srGateFail`; severity `Off` / `Warn` / `Fail` and excluded folders in the committed `ProjectSettings/SerializeReferenceSharedSettings.asset`. - -#### Settings - -- **Project Settings → Aspid.FastTools → SerializeReference** — auto de-alias, breakage detection, gate severity, excluded folders. -- **Preferences → Aspid.FastTools** — mirror of the Settings tab: References, Type Selector (Favorites, Recent capacity), Welcome, theme. - -#### Analyzer diagnostics - -- `AFT0001` (error) — `[TypeSelector]` on an unsupported field. -- `AFT0002` (warning) — `Allow` on a managed reference is ignored. -- `AFT0003` (warning) — base type shares no concrete type with the field. -- `AFT0004` (error) — `[SerializeReference]` on a `UnityEngine.Object` type. -- `AFT0005` (warning) — no concrete serializable type satisfies the constraints. -- `AFT0006` (error) — string argument is neither a member nor a type name. -- `AFT0007` (error) — referenced member cannot supply base types. -- `AFT0008` (warning) — non-identifier string is not a valid type name. - -#### ProfilerMarkers - -- `this.Marker()` — a `ProfilerMarker` unique to the call site. -- `ProfilerMarkersGenerator` — emits one marker field per call site; supports lambdas, local functions, `.WithName(...)` and `$"..."` names; compiled out without `ENABLE_PROFILER`. - -#### EnumValues - -- `EnumValues` — serializable enum-keyed dictionary with a default value and `[Flags]` support. -- `EnumValues` — typed variant, boxing-free lookups, struct enumerator. -- Drawers with inline editing and **Populate Missing Enum Members**. - -#### VisualElement fluent extensions - -- Fluent API on `VisualElement`: layout, style, borders, colors, transitions, callbacks, USS, child management with `*If` variants, style presets. -- Helpers for `Button`, `BaseField` (`SetLabel` for 29 types), `Focusable`, `Foldout`, `HelpBox`, `Image`, `IMGUIContainer`, `IMixedValueSupport`, `INotifyValueChanged`, `IStyle`, `ICustomStyle`, list views, `Manipulators`, `ProgressBar`, `Slider`, `TextElement`. -- Editor: `BindTo` / `UnbindFrom`, `BindPropertyTo`, `SetBindingPath`, `SetLabel` for `PropertyField`, `AddOpenScriptCommand`, `GetOwnerWindow`. -- `Aspid.FastTools.VisualElements.Math` — `SetValue` / `ValueChanged` for `Unity.Mathematics` types, compiled only with `com.unity.mathematics`. - -#### SerializedProperty extensions - -- Typed `Set*` / `Set*AndApply` setters, `Update`, `ApplyModifiedProperties`, `Persistent`, path helpers, `GetPropertyType` / `GetFieldInfo` / `GetDeclaringInstance`. - -#### Editor helpers - -- `GetScriptName()` / `GetScriptNameWithIndex()`. -- Open-script command that handles interfaces in differently named files and nested types. - -#### Samples - -- **Types**, **SerializeReferences**, **EnumValues**, **ProfilerMarkers**, **EditorTools** — one working scene (or window) each with a `README.md`. - -#### Documentation and tooling - -- English and Russian docs in `Documentation/`, published at https://vpdpersonal.github.io/Aspid.FastTools/. -- `aspid-fasttools` Claude Code plugin in [Aspid.Claude.Plugins](https://github.com/VPDPersonal/Aspid.Claude.Plugins). -- `upm` / `upm/` for stable releases, `upm-preview` for prereleases. Until the first stable release, the `upm` branch still holds the older `com.aspid.fasttools` package (`1.0.0-rc.2`). -- EditMode tests for the YAML editor and the CI-gate scan. - -[1.0.0-rc.9]: https://github.com/VPDPersonal/Aspid.FastTools/releases/tag/v1.0.0-rc.9 -[1.0.0-rc.8]: https://github.com/VPDPersonal/Aspid.FastTools/releases/tag/v1.0.0-rc.8 +- `SerializableType` and `SerializableMonoScript` store a `System.Type` in a component or an asset; `[TypeSelector]` picks it in the Inspector from compatible types. +- SerializeReference Selector picks the class of a `[SerializeReference]` field and carries compatible data over when the class changes. +- `ComponentTypeSelector` changes an added component to a derived class without losing shared field values. +- Project References finds missing `[SerializeReference]` references and `SerializableType` names across the project and repairs them in groups; the build and CI checks catch new ones. +- `EnumValues` maps enum keys to values that you edit in the Inspector, flags included. +- `this.Marker()` opens a profiler marker named after the type, the method and the line of the call; a source generator builds it. +- Analyzers `AFT0001`–`AFT0014` report `[TypeSelector]` and `this.Marker()` misuse in the IDE. +- VisualElement Extensions set element properties, styles and events in a chain. +- SerializedProperty Extensions update the object, write a value and apply the change in one chain. +- Editor Helpers: `GetDisplayName()` and `GetDisplayNameWithIndex()` label objects and components with readable names. +- The FastTools window (**Tools → Aspid 🐍 → FastTools**) with the Welcome, Asset References, Project References and Settings tabs, and themes for the FastTools windows. +- Samples for every feature, and Agent Skills that teach a coding agent to write code with FastTools. + +[1.0.0]: https://github.com/VPDPersonal/Aspid.FastTools/releases/tag/v1.0.0 diff --git a/README.md b/README.md index 6ec7628a4..9367ca624 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Unity 6000.0.53f1+](Website/docs/Images/status-badge-unity.svg)](https://assetstore.unity.com/packages/package/2333465) -[![Preview 1.0.0-rc.9](Website/docs/Images/status-badge-preview.svg)](https://github.com/VPDPersonal/Aspid.FastTools/releases/tag/v1.0.0-rc.9) +[![Release 1.0.0](Website/docs/Images/status-badge-preview.svg)](https://github.com/VPDPersonal/Aspid.FastTools/releases/tag/v1.0.0) [![MIT License](Website/docs/Images/status-badge-license.svg)](https://github.com/VPDPersonal/Aspid.FastTools/blob/main/LICENSE) Aspid.FastTools is a Unity package that takes the routine out of serialization, profiling and editor code. @@ -29,10 +29,10 @@ Documentation: [EN](https://vpdpersonal.github.io/Aspid.FastTools/docs), [RU](ht ```text -https://github.com/VPDPersonal/Aspid.FastTools.git#upm-preview +https://github.com/VPDPersonal/Aspid.FastTools.git#upm ``` -The URL installs the latest preview; **Update** in the Package Manager installs the next one. To pin a version or switch channels, see [Installation](https://vpdpersonal.github.io/Aspid.FastTools/docs#installation) in the documentation. +The URL installs the latest release; **Update** in the Package Manager installs the next one. To pin a version or switch channels, see [Installation](https://vpdpersonal.github.io/Aspid.FastTools/docs#installation) in the documentation. Requires Unity 6000.0.53f1 or newer. If you got the package from the Asset Store, skip the git URL and install it from **My Assets** in the Package Manager. diff --git a/Website/docs/13-agent-skills.md b/Website/docs/13-agent-skills.md index c9f27f7b6..27383dbdc 100644 --- a/Website/docs/13-agent-skills.md +++ b/Website/docs/13-agent-skills.md @@ -13,13 +13,13 @@ Ask your agent: ```text prompt Install the skills from VPDPersonal/Aspid.FastTools in the current project, -not globally. Run npx skills add VPDPersonal/Aspid.FastTools#skills-preview. +not globally. Run npx skills add VPDPersonal/Aspid.FastTools#skills. ``` Or run in the project root: ```bash -npx skills add VPDPersonal/Aspid.FastTools#skills-preview +npx skills add VPDPersonal/Aspid.FastTools#skills ``` In the installer, choose the **Project** scope: a global install applies to every Unity project, whatever its package version. @@ -39,7 +39,7 @@ The skills come from release branches, never from `main`. Each channel of the pa Update the package at the same time: skills newer than your package can describe API that it does not have, so the agent writes code that does not compile. To keep the skills at your package version, install them from its tag, which `npx skills update` does not move: ```bash -npx skills add VPDPersonal/Aspid.FastTools#skills-preview/ +npx skills add VPDPersonal/Aspid.FastTools#skills/ ``` The tag is on the channel of your package: `skills/` for a stable release, `skills-preview/` for a preview one. diff --git a/Website/docs/Images/readme-previews/install.webp b/Website/docs/Images/readme-previews/install.webp index 7c196465f..7d60813c6 100644 Binary files a/Website/docs/Images/readme-previews/install.webp and b/Website/docs/Images/readme-previews/install.webp differ diff --git a/Website/docs/Images/status-badge-preview.svg b/Website/docs/Images/status-badge-preview.svg index 21eaf60ed..c32e09a67 100644 --- a/Website/docs/Images/status-badge-preview.svg +++ b/Website/docs/Images/status-badge-preview.svg @@ -1,5 +1,5 @@ - - Preview 1.0.0-rc.9 + + Release 1.0.0 - + - Preview - 1.0.0-rc.9 + Release + 1.0.0 diff --git a/Website/docs/README.md b/Website/docs/README.md index 1afd25422..0e9cee600 100644 --- a/Website/docs/README.md +++ b/Website/docs/README.md @@ -4,7 +4,7 @@ [![Unity 6000.0.53f1+](Images/status-badge-unity.svg)](https://assetstore.unity.com/packages/package/2333465) -[![Preview 1.0.0-rc.9](Images/status-badge-preview.svg)](https://github.com/VPDPersonal/Aspid.FastTools/releases/tag/v1.0.0-rc.9) +[![Release 1.0.0](Images/status-badge-preview.svg)](https://github.com/VPDPersonal/Aspid.FastTools/releases/tag/v1.0.0) [![MIT License](Images/status-badge-license.svg)](https://github.com/VPDPersonal/Aspid.FastTools/blob/main/LICENSE) Aspid.FastTools is a Unity package that takes the routine out of serialization, profiling and editor code. @@ -16,10 +16,10 @@ Aspid.FastTools is a Unity package that takes the routine out of serialization, In **Window → Package Manager**, choose **+ → Install package from git URL…**, paste this URL and click **Install**: ```text -https://github.com/VPDPersonal/Aspid.FastTools.git#upm-preview +https://github.com/VPDPersonal/Aspid.FastTools.git#upm ``` -The URL installs the latest preview; **Update** in the Package Manager installs the next one. +The URL installs the latest release; **Update** in the Package Manager installs the next one. Requires Unity 6000.0.53f1 or newer. If you got the package from the Asset Store, skip the git URL and install it from **My Assets** in the Package Manager. diff --git a/Website/i18n/ru/CHANGELOG.md b/Website/i18n/ru/CHANGELOG.md index 130eea048..611ac30c5 100644 --- a/Website/i18n/ru/CHANGELOG.md +++ b/Website/i18n/ru/CHANGELOG.md @@ -9,444 +9,23 @@ ## [Unreleased] -## [1.0.0-rc.9] — 2026-10-24 +## [1.0.0] — 2026-11-05 -Последняя prerelease-версия перед 1.0.0. Ниже перечислено, что изменилось с `1.0.0-rc.8`. +Первый стабильный релиз. Нужен Unity **6000.0.53f1** или новее; все функции Inspector работают и в IMGUI, и в UI Toolkit. Prerelease-версии `1.0.0-rc.*` и их заметки лежат в [GitHub Releases](https://github.com/VPDPersonal/Aspid.FastTools/releases). ### Добавлено -- Выпадающие списки типов показывают иконку типа слева от имени: иконку из `[TypeSelectorDisplay]`, а без неё — иконку Unity для этого типа. Выключить их можно переключателем **Type icons** в разделе Appearance вкладки Settings. -- Переключатель **Field stripes** в разделе Appearance вкладки Settings скрывает статусную полосу слева от полей `[SerializeReference]`, `[TypeSelector]`, `SerializableType` и `SerializableMonoScript` в Inspector, а также отступ, который оставляет для неё общая ссылка. Уведомления под полями остаются. -- На вкладке Settings стрелка вправо включает выбранный переключатель, а стрелка влево выключает; Enter по-прежнему переключает его. -- Alt+Shift+R (Option+Shift+R на macOS) открывает Asset References на выбранном ассете из любого окна Editor. Переназначить сочетание можно в окне Shortcuts: Aspid FastTools/Open Asset References. -- Окно FastTools переключает вкладки по Alt+← и Alt+→ (Option на macOS), в дополнение к Ctrl+Tab. Переназначить их можно в окне Shortcuts, раздел Aspid FastTools/Window. -- Добавлены `RemoveChildren` и `RemoveChildrenIf`: удаляют несколько дочерних элементов за один вызов и принимают те же перегрузки `params`, `IEnumerable`, `List` и `ReadOnlySpan`, что и `AddChildren`. -- Добавлены `AddClasses`, `RemoveClasses`, `ToggleClasses` и `EnableClasses`: меняют несколько USS-классов за один вызов, принимают те же перегрузки `params`, `IEnumerable`, `List` и `ReadOnlySpan`, что и `AddChildren`. `IEnumerable` может читать `GetClasses()` того же элемента. `EnableClasses` принимает флаг первым: `EnableClasses(isFree, "selected", "free")`. -- `AddAspidWindowTheme()` даёт элементу вашего окна редактора цвета окон FastTools: палитру под скин редактора и тему из раздела **Appearance**, в том числе тему проекта. Элемент сразу следует новому выбору темы, а стили, добавленные после него, читают токены `--aspid-colors-*`. -- `TypeSelectorWindow.Show` принимает стиль. Тогда окно выбора берёт палитру и тему FastTools, светлую на светлом скине, вместо цветов всплывающих окон Unity, а стиль ложится поверх, и окно выбора выглядит как окно, которое его открывает. -- `InsertStyleSheet` вставляет таблицу стилей по индексу, `EnableStyleSheet(sheet, enable)` добавляет или убирает её, а `ClearStyleSheets` удаляет все таблицы стилей. -- `AddStyleSheets`, `InsertStyleSheets`, `RemoveStyleSheets` и `EnableStyleSheets` принимают несколько таблиц стилей с теми же перегрузками, что у `AddClasses`. -- У каждого метода таблиц стилей есть вариант `…FromResources`; методы во множественном числе принимают несколько путей: `AddStyleSheetsFromResources("UI/Base", "UI/Dark")`. -- У каждого метода для классов и таблиц стилей есть вариант `…If`, например `AddClassIf`, `EnableClassIf`, `AddStyleSheetFromResourcesIf`. -- Для `ToggleButtonGroup` добавлены типизированные перегрузки `SetValue`, `AddValueChanged`, `RemoveValueChanged` и `SetLabel` для `ToggleButtonGroupState`, поэтому вызовы вроде `AddValueChanged(evt => …)` не требуют аргументов типа. -- `GUIDField` (Unity 6000.4+) получил те же цепочечные сеттеры, что и `Hash128Field`: `SetLabel`, `SetReadOnly`, `SetMaxLength` и остальные сеттеры ввода и выделения текста, поэтому `SetLabel("Id")` не требует аргументов типа. -- Для `RectIntField` добавлен типизированный `SetLabel`, поэтому `SetLabel("Area")` не требует аргументов типа, как и у `RectField`. -- `DropdownField`, `PopupField`, `RadioButtonGroup` и `MinMaxSlider` получили цепочечные сеттеры: `SetChoices` для первых трёх, `SetIndex`, `SetFormatListItemCallback` и `SetFormatSelectedValueCallback` для полей с выпадающим списком, `SetLowLimit`, `SetHighLimit`, `SetMinValue` и `SetMaxValue` для `MinMaxSlider`. `SetChoices` не требует аргументов типа; `DropdownField.SetChoices` также принимает любой `IEnumerable`, например массив, и копирует его. Остальные сеттеры `PopupField` требуют их (`SetIndex, int>(1)`); у `DropdownField` есть перегрузки без них. -- `SetBackgroundImage` принимает `Sprite` или `VectorImage` наряду со `StyleBackground`: `icon.SetBackgroundImage(sprite)`. -- Начиная с Unity 6000.6, `SetTextSelf` принимает также `int`, `long`, `ulong`, `float` с форматом, `ReadOnlySpan`, `StringBuilder` или срез `char[]` и задаёт текст через `TextElement.SetText` из Unity без выделения памяти, поэтому текст, который меняется каждый кадр, не требует `ToString()`. Элемент, ещё не прикреплённый к панели, получает строку без предупреждения Unity. -- `SetRootItemsSelf` заполняет `TreeView` или `MultiColumnTreeView` в цепочке: `tree.SetAutoExpand(true).SetRootItemsSelf(items)`. -- Для `ScrollView`, `TabView`, `Tab` и `TwoPaneSplitView` добавлены сеттеры для цепочек. `ScrollView`: `SetMode`, `SetHorizontalScrollerVisibility`, `SetVerticalScrollerVisibility`, `SetScrollOffset`, `SetHorizontalPageSize`, `SetVerticalPageSize`, `SetMouseWheelScrollSize`, `SetScrollDecelerationRate`, `SetElasticity`, `SetElasticAnimationIntervalMs`, `SetTouchScrollBehavior`, `SetNestedInteractionKind`. `TabView`: `SetActiveTab`, `SetSelectedTabIndex`, `SetReorderable`, `AddActiveTabChanged`, `AddTabReordered`, `AddTabClosed` и парные `Remove…`. `Tab`: `SetLabel`, `SetIconImage`, `SetCloseable`, `AddSelected`, `AddClosing`, `AddClosed` и парные `Remove…`. `TwoPaneSplitView`: `SetFixedPaneIndex`, `SetFixedPaneInitialDimension`, `SetOrientation`. -- Для `ListView`, `TreeView` и других списочных представлений добавлен `SetShowBorder`. -- `RegisterCallbackSelf`, `RegisterCallbackOnceSelf` (обработчик срабатывает на одно событие) и `UnregisterCallbackSelf` добавляют и убирают обработчик события в цепочке, с параметрами `userArgs` и `TrickleDown` как у `RegisterCallback` из Unity: `button.RegisterCallbackSelf((PointerEnterEvent evt) => Hover()).SetTooltip("Apply")`. -- `TextField`, `IntegerField`, `LongField`, `UnsignedIntegerField`, `UnsignedLongField`, `FloatField`, `DoubleField` и `Hash128Field` получили цепочечные сеттеры: `SetMaxLength`, `SetMaskChar`, `SetDelayed`, `SetReadOnly`, `SetPassword`, `SetPlaceholder`, `SetHidePlaceholderOnFocus`, `SetKeyboardType`, `SetAutoCorrection`, `SetHideMobileInput`, `SetHideSoftKeyboard`, а для выделения текста — `SetSelectable`, `SetSelectAllOnFocus`, `SetSelectAllOnMouseUp`, `SetDoubleClickSelectsWord`, `SetTripleClickSelectsLine`, `SetCursorIndex`, `SetSelectIndex`, `AddOnCursorIndexChange` / `RemoveOnCursorIndexChange`, `AddOnSelectIndexChange` / `RemoveOnSelectIndexChange`. Сеттеры `ITextEdition` и `ITextSelection` к этим полям не применяются. Для других типов значений есть `TextInputBaseFieldExtensions` и `TextInputBaseFieldTextSelectionExtensions`. -- `TextField` получил `SetMultiline` и `SetVerticalScrollerVisibilitySelf`: в имени есть `Self`, потому что устаревший `SetVerticalScrollerVisibility` самого Unity перекрывает расширение с таким именем. `IntegerField`, `LongField`, `UnsignedIntegerField`, `UnsignedLongField`, `FloatField` и `DoubleField` получили `SetFormatString`; другие типы `TextValueField` используют `SetFormatString` из `TextInputBaseFieldExtensions`. -- Добавлены варианты `AndApplyWithoutUndo` для всех сеттеров `SerializedProperty` с немедленным применением, включая перегрузки `SetValue`, ссылки на объекты, перечисления и методы изменения размера массивов. -- `SetEnum`, `SetEnumAndApply` и `SetEnumAndApplyWithoutUndo` записывают значение перечисления в `SerializedProperty`, а `SetValue(Rarity.Rare)` вызывает их. `SetEnumIndex` принимает индекс записи перечисления, а не значение: для `Rare = 20` вызов `SetEnumIndex((int)Rarity.Rare)` выберет не ту запись. -- На Unity 6000.4 и новее `SetGuid`, `SetGuidAndApply`, `SetGuidAndApplyWithoutUndo` и перегрузки `SetValue` записывают поле `GUID`; раньше для этого нужен был `SetBoxed`. -- В **Settings** и **Preferences → Aspid.FastTools** появился раздел **Appearance**. Выпадающий список **Theme** перекрашивает окна FastTools и окно выбора типа: **Default** (почти чёрные карточки, зелёный акцент), **Venom** (сине-чёрная палитра сайта документации с его синим акцентом) или **Unity** (серые тона скина редактора Unity, так что окна выглядят как панели редактора), у каждой есть светлый вариант для светлого скина редактора. Статус success во всех остаётся зелёным. Акцент ссылок, рамок фокуса и наведения, активной вкладки, кнопок, переключателей, заголовка и логотипа на Welcome переехал в собственные токены `--aspid-colors-accent-*` и `--aspid-icons-accent`, так что тема может менять его отдельно от статуса success; `--aspid-colors-surface-control` и `--aspid-colors-surface-field` задают заливку кнопок и выпадающих списков, а также полей значений в настройках; `--aspid-radius-card` и `--aspid-radius-control` задают их скругления, `--aspid-colors-slider-track` — дорожку слайдера, `--aspid-colors-dots-1`…`-3` красят точки за окнами, а `--aspid-dots-radius: 0` скрывает их. Под встроенными темами список показывает темы проекта — `.uss`-файлы в `Assets` с меткой `AspidFastToolsTheme`, а пункт **Create theme…** в его конце копирует текущую тему в новый файл, ставит на него метку и выбирает его. Тема проекта выбирается для этого проекта, встроенная — для всех проектов на компьютере. Выбор темы перекрашивает уже открытые окна, а файл, выбранный раньше как theme override, становится темой проекта. На вкладке Settings Enter открывает список, а стрелки влево и вправо переключают темы. -- Анализатор `AFT0009` (предупреждение) — два базовых типа `[TypeSelector]` не имеют общего типа, поэтому селектор пуст. -- Анализатор `AFT0012` (предупреждение) — `[TypeSelector]` на поле, которое Unity не сериализует, поэтому инспектор его не показывает: непубличное поле без `[SerializeField]` или `[SerializeReference]`, автосвойство без `[field: SerializeField]`, а также поле `static`, `const`, `readonly` или `[NonSerialized]`. -- Анализатор `AFT0010` (предупреждение) — вызов `this.Marker()` не открывает маркер профайлера, потому что генератор не может его поддержать: вызов записан в типе `private` или `protected` (или вложенном в такой тип), в интерфейсе (метод интерфейса по умолчанию) либо в типе, который повторяет имя параметра типа внешнего типа; получатель другого типа (`other.Marker()`, вызовы в статических классах); у вызова явный аргумент (`this.Marker(5)`) или аргумент типа; либо это `this?.Marker()`, статическая форма вызова, группа методов или вызов внутри дерева выражений. Для таких вызовов генератор не создаёт маркер. -- Анализатор `AFT0011` (предупреждение) — scope из `this.Marker()` выброшен (`this.Marker();` отдельной инструкцией, `_ = this.Marker();`, локальная переменная, которую никто не читает), поэтому начатый сэмпл никогда не заканчивается. -- `SerializeReferenceIMGUIList.Draw(listProperty, label, baseTypes)` берёт тип элемента из поля списка, как `SerializeReferenceEditorGUI.CreateList`; перегрузка с `elementType` остаётся. -- У `EnumValues` и `EnumValues` появились `TryGetValue`, который отличает подходящую строку от запасного **Default Value**, и `Count` — число строк, которые отдаёт `foreach`. У `EnumValues` также есть `GetValue` и `TryGetValue`: они принимают ключ без упаковки, и вызов вида `table.GetValue(damageType)` после перекомпиляции выбирает их. -- Анализатор `AFT0013` (предупреждение) — scope из `this.Marker()` остаётся открытым через `yield return` или `await`: корутина или `async`-метод продолжают работу в другом кадре или потоке, поэтому Profiler получает несбалансированные сэмплы. -- Анализатор `AFT0014` (предупреждение) — имя в `WithName`, которое генератор не может прочитать при компиляции, например переменная, поэтому маркер сохраняет имя члена. -- У каждой диагностики анализатора есть описание исправления и ссылка на страницу документации; раньше Rider и Visual Studio открывали поиск по ID в интернете. -- Потерянные типы `[SerializeReference]`, заданные override'ами экземпляров префабов (варианты, вложенные префабы, экземпляры префабов в сценах), теперь находятся: build / CI gate считает их потерянными типами, Project References показывает их в карточке **Prefab instance overrides**, а защита от удаления скрипта и детектор поломок их учитывают. Они не переписываются автоматически: исправьте тип на самом экземпляре или отмените override. Старое имя, которое сопоставляет `[MovedFrom]`, показывается там как ожидающая миграция, потому что **Migrate all** не переписывает override'ы. В отчёте CI появился последний столбец `origin`, для таких строк — `override`. -- **Assets → Aspid 🐍 → FastTools → Asset References** в главном меню и в контекстном меню окна Project открывает Asset References на выбранном префабе, ScriptableObject, сцене или экземпляре префаба; для другого выделения пункт неактивен. -- `-srGateStrict` заставляет CI-проверку считать нарушениями файлы, которые она не смогла проверить (нескачанные файлы Git LFS, двоичные ассеты, способные хранить ссылки), поэтому в режиме `Fail` запуск без `git lfs pull` больше не завершается с кодом `0`. -- В CI-отчёте появились замыкающие колонки `ns` и `asm` с сохранёнными пространством имён и сборкой строки `MissingType`. Журналы сборки и CI называют потерянный тип вместе с пространством имён (`Game.Pistol`, а не `Pistol`), чтобы одноимённые классы можно было различить. -- Поле `[SerializeReference]`, у которого на экземпляре префаба переопределены класс или собственные данные, имеет жирную подпись, а меню его заголовка предлагает **Revert** и **Apply to Prefab 'Name'**, как у собственных полей Unity. Изменение внутри вложенной ссылки отмечает только изменённое поле, а **Apply** не предлагается у варианта префаба, выбранного в **Project**. Синяя полоса override не рисуется; при выделении нескольких объектов нет ни подписи, ни пунктов. -- Поле `SerializableType` или `SerializableMonoScript` либо строка с `[TypeSelector]`, чей сохранённый тип больше не находится, показывает под полем уведомление **Missing type**. **Fix** открывает окно выбора, чтобы подобрать замену. Если класс только перенесли в другой namespace или сборку и подходящий тип с таким именем один, кнопка **→ ИмяТипа** заменяет сохранённое имя одним нажатием. Подпись показывает имя типа без сборки, ``, а всплывающая подсказка — сохранённое имя целиком. -- `TypeField.AssemblyQualifiedName` возвращает сохранённое имя потерянного типа, для которого `value` равен `null`, так что кастомный редактор может записать имя обратно без изменений. `TypeField.ExcludeEditorOnlyTypes` стал публичным: непривязанное поле тоже может скрыть типы из editor-only сборок, как это делает привязанное поле на runtime-объекте. -- У `SerializableType`, `SerializableMonoScript` и их generic-вариантов появились `IsEmpty` (тип не сохранён) и `IsMissing` (имя сохранено, но больше не находится); `Type` в обоих случаях `null`. Unity заполняет сериализуемое поле пустой обёрткой, когда загружает ассет, сцену или префаб, поэтому одного `field == null` мало: проверяйте `field is null || field.IsEmpty`. -- Потерянные имена `SerializableType` и `SerializableMonoScript` находятся по всему проекту. **Project References → Scan Project** показывает их в группах **type name** с **Fix all**, **Smart Fix** и **Undo**; override экземпляров префабов и поля внутри managed-ссылок тоже переписываются. Проверка сборки и CI сообщает о них строками `MissingTypeName`: сохранённое имя — в столбце `className`, поле обёртки — в `fieldPath`. Обнаружение новых поломок сообщает об имени, которое перестало находиться. Строки с `[TypeSelector]` по-прежнему проверяются только в инспекторе. -- Кнопка-папка у полей `SerializableType`, `SerializableMonoScript`, `[TypeSelector]` и `[SerializeReference]`, а также `OpenInScriptEditor` открывают справку по типу, который поставляется с Unity и не имеет скрипта в проекте: тип `UnityEngine`, `UnityEditor` или `Unity`, например `CharacterController`, открывает свою страницу Scripting API на docs.unity3d.com для вашей версии редактора, тип `System` — свою страницу на learn.microsoft.com. Раньше для такого типа кнопка только писала предупреждение в консоль. - -### Изменено - -- IMGUI-отрисовка `EnumValues` выглядит как в UI Toolkit: имя поля стоит над полем типа во всю ширину, шапку отделяет линия, **Default Value** больше не сдвинут вправо, а заголовок **Values** — обычный текст вместо жирного на плашке. -- **Excluded scan folders** на вкладке Settings выглядит как список Unity: подпись и папки стоят в одном блоке с рамкой, у каждой папки в конце строки есть **−**, а в последней строке (или в строке **List is empty**) — **+**. Клик выделяет папку, двойной клик позволяет выбрать вместо неё другую. С клавиатуры Enter или Delete на выбранной папке удаляет её, а её **−** подсвечивается, пока на ней фокус. -- Минимальная версия Unity теперь 6000.0.53f1 вместо 6000.0.0f1. Пакет использует API UI Toolkit, которые появились в более поздних патчах 6000.0 (`IStyle.unityEditorTextRenderingMode`, `IStyle.unitySliceType`, `UxmlElement.libraryPath`), поэтому на ранних патчах он не компилировался. -- Пакет больше не содержит папку `Documentation` со страницами и картинками, поэтому они не импортируются в ваш проект; документация находится на сайте: https://vpdpersonal.github.io/Aspid.FastTools/. README в примерах тоже больше нет: описание примера в Package Manager заканчивается ссылкой на его руководство на сайте, а карточка примера на вкладке Welcome показывает её как ссылку **Tutorial**. -- `README.md` пакета больше не указывает git URL, чтобы покупатель из Asset Store не добавил вторую копию пакета; установка по git URL осталась на сайте. -- Agent Skills для пакета переехали из плагина `aspid-fasttools` для Claude Code в [Aspid.Claude.Plugins](https://github.com/VPDPersonal/Aspid.Claude.Plugins) в этот репозиторий (`skills/`). Устанавливайте их в Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI или другой агент командой `npx skills add VPDPersonal/Aspid.FastTools#skills`, или `#skills-preview` для preview-версии: `npx skills update` затем следует за релизами этого канала, а не за `main`; плагин больше не публикуется. Установленный плагин остаётся на машине и учит агента API, которого больше нет: удалите его в Claude Code командой `/plugin uninstall aspid-fasttools@aspid-claude-plugins`. -- У примеров новый вид. В каждом примере есть папка `Fonts` со шрифтами IBM Plex Serif и iA Writer Quattro S, а в EnumValues и EditorTools ещё и IBM Plex Mono, под лицензией SIL Open Font License 1.1 (тексты лицензий лежат рядом со шрифтами, а `Third-Party Notices.txt` в корне пакета перечисляет шрифты с лицензиями и путями). В примерах со сценами (EnumValues, Types, SerializeReferences, ProfilerMarkers) есть ещё папки `Materials` с цветными материалами и `Shaders` с небольшим шейдером `Studio`. Ability Catalog из примера EditorTools берёт шрифты через `SampleFonts.uss`, а тему FastTools — через `AddAspidWindowTheme()`; окно выбора типа открывает поле **Effect** вместо кнопки **Change…** и показывает имя и иконку эффекта из `[TypeSelectorDisplay]`, **+** заменил **Create**, **Reset to defaults**, видная, пока стоимость или перезарядка отличается от значения по умолчанию, — **Halve cooldown, +5 MP**, а кнопки строки выделяют её ассет или переносят его в корзину. Кастомного инспектора в примере больше нет: ассет `AbilityConfig` показывается в стандартном инспекторе Unity. Примеры выросли примерно с 0,2 до 3 МБ, в основном из-за копий шрифтов: пример импортируется отдельно, поэтому каждый несёт свои. -- Пять примеров упрощены и идут в порядке Types, SerializeReferences, EnumValues, ProfilerMarkers, EditorTools. Сцены и описанный выше внешний вид остались прежними, а их C# сократился примерно с 2660 строк до 1560: без комментариев, тултипов и `Debug.Log`, по одному типу на файл, скрипты лежат в папке `Scripts` рядом со своим assembly definition, а связанные типы — в подпапках, а классов, которые только наполняли демо, стало меньше. Ни одному примеру больше не нужен модуль Physics, в сценах нет света и коллайдеров. SerializeReferences не поставляет сломанных ассетов: пресеты, сломанный префаб и IMGUI-инспектор пресета удалены, а его руководство ломает ссылку переименованием класса. -- `GetScriptName()` переименован в `GetDisplayName()`, а `GetScriptNameWithIndex()` — в `GetDisplayNameWithIndex()`; замените старые вызовы новыми именами. Оба метода возвращают `string.Empty` для null и уничтоженных объектов. Поиск индекса компонента использует список из пула вместо временных массивов и LINQ. -- Переименованы расширения VisualElement; замените старые вызовы: - - `SetIsDelayed` / `SetIsPassword` / `SetIsReadOnly` / `SetIsSelectable` → `SetDelayed` / `SetPassword` / `SetReadOnly` / `SetSelectable`; - - `IsFocus` → `IsFocused`, `SetFocus` / `SetBlur` → `FocusSelf` / `BlurSelf`; - - `EnableInClass` / `ToggleInClass` → `EnableClass` / `ToggleClass`; - - `AddStyleSheetsFromResource` / `RemoveStyleSheetsFromResource` → `AddStyleSheetFromResources` / `RemoveStyleSheetFromResources`; `AddStyleSheets(sheet)` и `RemoveStyleSheets(sheet)` по-прежнему компилируются: имена во множественном числе теперь принимают несколько таблиц; - - `SetImageFromResource`, `SetSpriteFromResource`, `SetVectorImageFromResource`, `SetBackgroundImageFromResource` → `…FromResources`; - - `MarkDirtyLayout` → `MarkDirtyLayoutSelf`: `IMGUIContainer.MarkDirtyLayout()` перекрывал старое расширение, и вызов возвращал `void`; новое имя встраивается в цепочку. - - `SetText` у `TextElement` (`Label`, `Button` и других) → `SetTextSelf`: начиная с Unity 6000.6 строковый аргумент связывается с собственным `TextElement.SetText(ReadOnlySpan)` из Unity, который возвращает `void`, поэтому цепочки вида `label.SetText(x).SetTooltip(y)` не компилировались; новое имя встраивается в цепочку на любой версии Unity. `SetText` у `Foldout`, `HelpBox` и `Toggle` сохраняет имя. -- Вызов с голым `null` у `SetBackgroundImage` и, начиная с Unity 6000.6, у `SetTextSelf` больше не компилируется, потому что `null` подходит и к новым перегрузкам. Приведите его к типу, например `(string)null`, или передайте `StyleKeyword.None`, чтобы убрать фон. -- Классы расширений `BaseFieldExtensionsSetLabel` переименованы в `BaseFieldExtensions` (`BaseFieldExtensionsSetLabelInt` → `BaseFieldIntExtensions`), а `ProgressBarExtensions` — в `AbstractProgressBarExtensions`. Вызовы методов расширения не меняются; меняются только вызовы через имя класса. -- Класс расширений `SerializePropertyExtensions` переименован в `SerializedPropertyExtensions`. Вызовы методов расширения не меняются; меняются только вызовы через имя класса, например `SerializePropertyExtensions.GetFieldInfo(property)`. -- У `SetShowMixedValue` больше нет значения аргумента по умолчанию `true`; передавайте значение явно. -- `SetDirection`, `SetFill`, `SetInverted`, `SetPageSize` и `SetShowInputField` теперь возвращают собственный тип слайдера (`Slider`, `SliderInt`) вместо `BaseSlider`, поэтому цепочка сохраняет члены слайдера. Они принимают `BaseSlider` и `BaseSlider`; открытые перегрузки для `BaseSlider` удалены. Перегрузки для `BaseSlider` находятся в новом классе `SliderIntExtensions`: вызовы методов расширения не меняются, но вызов через `SliderExtensions.` на `SliderInt` нужно заменить на `SliderIntExtensions.`. -- Конструкторы без параметров у `SerializableType` / `SerializableType` больше не публичные: создавайте обёртку через `new SerializableType(type)` или `new SerializableType(type)` (`null` даёт пустую). У `SerializableMonoScript` / `SerializableMonoScript` нет публичных конструкторов: объявляйте их сериализуемыми полями и выбирайте скрипт в инспекторе. -- `SerializableType`, `SerializableMonoScript` и их generic-варианты теперь сравниваются по значению; `Equals` и `GetHashCode` раньше сравнивали ссылки. Обёртки с одним и тем же именем типа равны и дают одинаковый хеш-код, поэтому подходят в качестве ключей `Dictionary` и `HashSet`, а `List.Contains` и `IndexOf` находят равную обёртку. Оператор `==` по-прежнему сравнивает ссылки. -- `[TypeSelector]` на поле `[SerializeReference]` теперь предлагает только типы, совместимые со всеми типами атрибута, — по тому же правилу, что уже действовало для полей `string` и `SerializableType`; раньше достаточно было совпасть с одним из них. То же относится к `baseTypes` у `SerializeReferenceEditorGUI.CreateField`, `CreateList` и `DrawFieldLayout`. Список альтернатив вроде `typeof(Pistol), typeof(Rifle)` теперь оставляет селектор пустым и вызывает `AFT0009`: дайте разрешённым классам общий интерфейс или базовый класс и укажите его. `AFT0005` теперь проверяет все типы атрибута вместе. -- Анализатор `[TypeSelector]` больше не разбирает атрибуты полей без `[TypeSelector]` и пропускает сборки, которые не ссылаются на пакет; раньше это замедляло каждую компиляцию большого проекта. -- IMGUI-инспектор больше не проверяет список `[SerializeReference]` на дубликаты целиком для каждого элемента на каждом GUI-событии: проверка идёт один раз на список за такт редактора или при изменении размера списка. Поле с общей ссылкой больше не создаёт `SerializedObject` на каждой перерисовке. -- Определение поломок хранит свой baseline в памяти и записывает его в сессию один раз, перед перезагрузкой скриптов, вместо разбора и перезаписи целиком при каждом сохранении ассета, что стоило миллисекунды на тысячу ассетов. Стартовый проход декодирует только ассеты, где есть управляемая ссылка или имя типа, а не читает каждый ассет целиком. -- Удаление или перенос ассета больше не сбрасывает прогретый индекс использований Project References, защиты удаления и определения поломок. Удаление убирает использования этого ассета, перенос в **Excluded scan folder** или из неё убирает или добавляет их, а перенос между сканируемыми папками ничего не меняет. Импорт больше чем 64 сканируемых ассетов сбрасывает индекс один раз вместо обновления по ассету. -- `GetFieldInfo()` и `GetDeclaringInstance()` кэшируют поиск поля, а проверка, есть ли у вложенного поля `[SerializeReference]` собственный drawer, кэшируется для каждого поля. IMGUI-инспектор больше не создаёт массивы и экземпляры атрибутов для каждой вложенной ссылки на каждом событии, а строк создаёт меньше, поэтому на большом дереве при движении мыши выделяется меньше памяти. -- **Fix all**, **Smart Fix**, **Migrate all**, `` и **Undo** в сводке Project References больше не перечитывают файл на каждую сломанную ссылку в нём, а записывают его один раз. Проверка, открыт ли файл или есть ли в нём несохранённые изменения, тоже идёт один раз на файл. Поэтому файл с большим числом сломанных ссылок исправляется намного быстрее. -- Пустое поле `[SerializeReference]` больше не разбирает файл ассета на каждой перерисовке, чтобы проверить потерянный тип: неизменённый файл читается один раз, поэтому пустые поля в большой сцене или префабе больше не замедляют инспектор. -- В инспекторе runtime-объекта селектор типов больше не предлагает типы из editor-only сборок (`UnityEditor`, asmdef только для Editor и папки `Editor`): плеер не может их найти, и в билде значение молча становилось `null` или потерянной ссылкой. Поля окон редактора и других editor-only объектов по-прежнему предлагают любые типы. -- **Paste**, **Paste Template**, *Link to Existing*, перетаскивание скрипта и **Smart Fix** в инспекторе runtime-объекта следуют тому же правилу: они больше не назначают тип из editor-only сборки или generic-тип с таким аргументом. Селектор типов в Asset References тоже больше не предлагает такие типы для runtime-объекта. **Create New Script…** не меняет поле и пишет предупреждение, если новый скрипт сохранён в папке `Editor`. -- Селектор типов без ограничений (`SerializableType` без `T`, `[TypeSelector]` на строке, `TypeField`) переиспользует список типов между открытиями, а не собирает его заново из всех загруженных типов. -- Селектор типов сначала проверяет базовый тип поля, когда перебирает загруженные типы, поэтому селектор с узким базовым типом, например **+** списка `[SerializeReference]` конкретного интерфейса, открывается в большом проекте в несколько раз быстрее. IMGUI-поле типа разрешает сохранённое имя типа один раз, а не на каждой перерисовке; потерянный тип делал это медленным. -- Селектор типов с предикатом, например у поля `SerializableMonoScript`, у `TypeField.Predicate` или у поля `[SerializeReference]`, больше не проверяет все загруженные типы заново при каждом открытии: типы, проходящие все проверки кроме предиката, перечисляются один раз для набора базовых типов и переиспользуются, пока не загрузится сборка, а при открытии выполняется только предикат. В проекте с примерно 55 000 загруженных типов селектор поля `SerializableMonoScript` открывается примерно за 6 мс вместо примерно 85 мс, а селектор поля `[SerializeReference] object` — примерно за 90 мс вместо примерно 190 мс. -- `TypeField(string label, Type defaultValue = null)` разделён на `TypeField(string label)` и `TypeField(string label, Type defaultValue)`, `InspectorTypeField` — так же. `new TypeField(null)` раньше выбирал конструктор со свойством и бросал `NullReferenceException`; теперь вызов не компилируется — укажите имя аргумента: `new TypeField(label: null)`. Привязанные конструкторы бросают `ArgumentNullException` для свойства `null` и `ArgumentException` для свойства не строкового типа. С `binding-path` в UXML поле пишет предупреждение, что привязать его можно только из C#. -- Чтение `Type` у `SerializableType` и `SerializableMonoScript` открывает маркер профайлера только для поиска типа, а не для чтения из кэша, поэтому чтение у многих объектов в каждом кадре больше не забивает профайлер сэмплами. -- `EnumValues` открывает маркер профайлера только при построении записей на первом обращении, а не в `GetValue`, `TryGetValue` и `Equals`, поэтому поиск для многих объектов в каждом кадре больше не забивает профайлер сэмплами. -- `SerializeReferenceIMGUIList.Draw` теперь бросает `ArgumentNullException` для свойства `null` и `ArgumentException` для свойства, которое не является списком managed references, как `SerializeReferenceEditorGUI.CreateList`; раньше он ничего не рисовал. Метка `null` теперь показывает отображаемое имя свойства; чтобы скрыть её, передайте `GUIContent.none`. -- Параметр `currentAqn` метода `TypeSelectorWindow.Show` переименован в `assemblyQualifiedName`, как и другие параметры, которые принимают assembly-qualified name. Обновите вызовы, где он передаётся по имени: `currentAqn: name` становится `assemblyQualifiedName: name`. Позиционные вызовы менять не нужно. -- Сгенерированный код `this.Marker()` теперь объявляет поля маркеров только под `ENABLE_PROFILER`, как и тело `Marker()`, которое их читает: сборки без профайлера больше не создают все маркеры в статическом конструкторе. -- `ProfilerMarkerExtensionsForGenerator.Marker(this object)` стал `Marker(this T, [CallerLineNumber] int line = -1)`: вызов в структуре, которую генератор не может обработать, больше не упаковывается, и Burst-джоба компилируется. Параметры у него те же, что у сгенерированной перегрузки, поэтому маркеры получает и тип без пространства имён, как в шаблоне скрипта Unity. Вызов `this.Marker()` внутри дерева выражений больше не компилируется (CS0854), а группе методов теперь нужен `Func`. -- Generic-класс называет вложенные аргументы типа так, как их пишет C# (`Foo>.Run (line)`, `Foo.Inner>.Run (line)` вместо ``Foo``, `Foo`). Generic-структура получает один маркер на точку вызова для всех закрытых типов с именем `Job.Execute (line)`, потому что Burst не может выполнить метку для каждого типа. -- Сгенерированный `Marker()` выбирает маркер по строке через `switch`, поэтому его стоимость больше не растёт с числом точек вызова в типе. -- Сгенерированный `Marker()` принимает структуру по `in`, поэтому `this.Marker()` в структуре, например в большой джобе, больше не копирует весь экземпляр при каждом вызове. Копия делалась в Mono (редактор, Mono-плееры) и в IL2CPP, когда вызов и перегрузка попадали в разные C++-файлы. -- Скриптовый символ, который вырезает собственные маркеры профилировщика пакета, теперь называется `ASPID_FASTTOOLS_UNITY_PROFILER_DISABLED`, как и остальные символы `ASPID_FASTTOOLS_*`. Старый `ASPID_FAST_TOOLS_UNITY_PROFILER_DISABLED` больше не работает: переименуйте его в **Scripting Define Symbols**. -- `Aspid.FastTools.VisualElements.Math` больше не компилируется пустой сборкой в проектах без `com.unity.mathematics`. -- Анимированный фон из точек в окне FastTools и на странице настроек рисует все точки одним мешем, а не тесселирует отдельный путь на каждую точку в каждом кадре, и замирает, пока Unity в фоне, поэтому открытое окно без действий больше не нагружает редактор. -- Фон из точек перерисовывается 20 раз в секунду вместо 30. Новый переключатель **Animated background** (окно FastTools → Settings → Appearance и Preferences → Aspid.FastTools → Appearance) скрывает точки и останавливает таймер их перерисовки, а также анимацию заголовка и логотипа на вкладке Welcome. -- Градиент при наведении на кнопку в окнах FastTools запускает таймер только на время затухания, а все градиентные кнопки используют одну общую текстуру градиента вместо собственной. -- Окно FastTools (Welcome, Asset References, Project References и Settings) и его страницы в Project Settings и Preferences учитывают светлую тему редактора: фон, карточки, текст, статусные цвета и окно выбора типа внутри него берут светлую палитру `Aspid-FastTools-Default-Light.uss`; раньше они оставались тёмными в обеих темах. Тема по-прежнему накладывается поверх любой из палитр. -- Окно FastTools сохраняет вид каждой вкладки между посещениями: позиция прокрутки, раскрытые строки, итоги исправлений и фокус клавиатуры переживают переход на другую вкладку и обратно. Asset References и Project References при возвращении заново читают ассет и проект. -- Карточки окна FastTools и его страниц в Project Settings и Preferences непрозрачные, поэтому точки фона больше не проступают сквозь текст. Фон и заголовок вкладки Welcome движутся, только пока их окно в фокусе или под курсором, а логотип Welcome пульсирует только под курсором. -- Вкладка Settings отмечает, где хранится настройка: фиолетовой полосой — настройку проекта (в репозитории, одна на всю команду), серой — личную. Легенда и кнопка сброса пишут **Project** вместо **Shared**: этим словом Asset References называет общую managed-ссылку и отмечает её цветной точкой и приглушённым словом **shared** вместо синего бейджа **SHARED**. Строка над легендой убрана; что значат полосы, говорит подсказка легенды. Выпадающие списки, слайдеры, поля объектов и кнопки строк в Settings стоят одной колонкой у правого края, а не занимают половину строки. Строк описания под настройками SerializeReference больше нет: как и все остальные настройки, их объясняет подсказка строки. **Excluded scan folders** показывает папки в рамке, а пустая рамка пишет **No excluded folders**. -- **Rescan** в Asset References и **Scan Project** в Project References получили иконку обновления. Project References показывает каждый файл одной строкой с его rid, а если их несколько, с их числом (список в подсказке), приглушает папку в пути и добавляет **Copy Path** в контекстное меню строки. Строки **Smart Fix** и **Migrate** на обеих вкладках называют целевой тип вместе с пространством имён (`Smart Fix → Game.Weapons.Pistol`), а потерянный тип с тем же именем класса, что у его исправления, показывает различающуюся часть своего пространства имён (`Legacy.Pistol`). Осиротевшая ссылка очищается из шапки своей карточки, как Change и Assign у остальных карточек, а раздел Orphaned стал обычным подзаголовком вместо янтарной рамки. **Undo** и **Open Source Prefab** теперь обычные кнопки с контуром, как действия во вкладке Settings; градиентные полосы остались у действий во всю ширину карточки. Иконка пустой вкладки Asset References или Project References стоит посередине вкладки и больше не прыгает при переключении вкладок; текст идёт под ней. В узком окне карточка группы в Project References сокращает имя типа и счётчик многоточием, а не переносит имя посреди слова, **Fix all** сохраняет ширину, а строки **Smart Fix** и **Migrate** на обеих вкладках сокращают имя типа посередине, так что видны и действие, и имя класса. -- Подсказка сочетания клавиш вкладки в панели окна (`⌥2`) стоит сразу за названием и скрывается, когда вкладке не хватает ширины на оба. -- Окно FastTools взяло цвета и скругления сайта документации: зелёный акцент, янтарный, синий, красный и фиолетовый — с сайта, у карточек и полос углы 6 px вместо 8–10 px. Переключатели везде берут зелёный сайта; в светлой теме включённый переключатель заливает дорожку зелёным под белой ручкой и обводит её тёмно-зелёным контуром, а не бледным оттенком под тёмной ручкой. -- Строка под заголовком Project References оставляет только то, что требует внимания, например устаревшие данные или непрочитанные файлы, а у Asset References строки «N managed references mapped» больше нет; как действовать, теперь в подсказке заголовка. Project References раскладывает карточки под заголовки **Broken**, **Required**, **Prefab instance overrides** и **Renamed** вместо цветовой легенды; у списка только сломанных или только переименованных типов заголовка нет. Нарушения Required и оверрайды экземпляров префабов разложены по карточке на файл с путём и числом записей в шапке. Asset References показывает необязательное пустое поле однострочной строкой на его месте среди полей, а не целой карточкой, а у каждого объекта есть сворачиваемый заголовок вида «GameObject › Component», или просто «Component», если GameObject называется так же, с иконкой объекта: они на размер крупнее разделов внутри них и нейтрального цвета, а счётчики показываются в подсказке. Каждое поле `[TypeSelector]`-строки, `SerializableType` и `SerializableMonoScript`, обязательное или нет, показано среди карточек своего объекта в порядке полей, а путь поля записан так же, как у них: заданное — карточкой с типом и **Change**, пустое обязательное — янтарной карточкой, пустое необязательное — однострочной строкой с **Assign**, как поля `[SerializeReference]`. Объект с такими полями, но без managed-ссылок, тоже получает свой заголовок. Карточка известного типа показывает иконку типа из выбора типа. Вкладка Welcome описывает пакет так же, как сайт, и называет все возможности. -- `[TypeSelector]` на поле-массиве или `List` теперь относится ко всей коллекции (`applyToCollection`): его drawer рисует список и выбор типа для каждого элемента. `PropertyField` и `EditorGUILayout.PropertyField` для такого списка теперь получают **+** с выбором типа в UI Toolkit и IMGUI, а `PropertyField` для отдельного элемента больше не показывает выбор типа. `SerializeReferenceIMGUIList.Draw` и `SerializeReferenceEditorGUI.CreateList` добавляют к `baseTypes` ограничения `[TypeSelector]` с поля списка. Списки managed references, которые рисует пакет, теперь учитывают `[NonReorderable]`. -- Параметр `value` у `AddClass`, `RemoveClass`, `ToggleClass`, `AddStyleSheet`, `RemoveStyleSheet` и их вариантов `…If` переименован в `className` и `styleSheet`; вызов с именованным аргументом `value:` нужно обновить. -- Методы таблиц стилей, например `AddStyleSheet` и `RemoveStyleSheet`, пропускают `null` вместо `ArgumentNullException`. -- `RemoveChild` и `RemoveChildren` пропускают `null` и элементы, которые не являются дочерними, вместо исключения, поэтому `RemoveChildren` больше не останавливается на полпути. -- Расширения для дочерних элементов, классов и таблиц стилей размечены для nullable reference types: проект с включённой проверкой видит, какие аргументы могут быть `null`. - -### Удалено - -- Из расширений `SerializedProperty` удалён `SetExposedReferenceAndApply()`; вызывайте `SetExposedReference()`. Без контекста `IExposedPropertyTable` сеттер `exposedReferenceValue` в Unity сам применяет запись и записывает Undo, поэтому дополнительное применение ничего не делало, а вариант без Undo поверх него построить нельзя. -- Удалено editor-only свойство `SerializableMonoScript.Script`, которое возвращало ассет `MonoScript`; публичного доступа к ассету больше нет. Тип по-прежнему доступен через `Type` или неявное преобразование в `Type`. -- Удалены `AddMakeItem` / `RemoveMakeItem` у `ListView` и `TreeView`, а также `AddMakeHeader` / `AddMakeFooter` / `AddMakeNoneElement` у `BaseListView` вместе с парами `Remove*`; у списка одна фабрика, поэтому вызывайте `SetMakeItem`, `SetMakeHeader`, `SetMakeFooter` или `SetMakeNoneElement`. -- Удалены перегрузки `Span` у `AddChildren`, `InsertChildren` и их вариантов `…If`. Аргумент `Span` преобразуется в перегрузку `ReadOnlySpan`, поэтому существующие вызовы компилируются без изменений. -- Runtime-методы `Aspid.FastTools.StringExtensions.ToKebabCase` и `Aspid.FastTools.TypeExtensions.GetMembersInfosIncludingBaseClasses` убраны из публичного API без замены. - -### Исправлено - -- Ссылка **Asset Store** и логотип на вкладке Welcome открывают страницу пакета в Asset Store; раньше они вели на несуществующую страницу. -- Unity 6000.6 больше не предупреждает при импорте, что семь `.meta`-файлов таблиц стилей пакета ниже поддерживаемой версии сериализации. -- `InsertChildren` и `InsertChildrenIf` пропускают `null` без сдвига индекса: `InsertChildren(0, a, null, b)` ставит `b` сразу после `a`; раньше оставался пропуск, а в конце родителя вызов бросал `ArgumentOutOfRangeException`. -- `SetValue`, `SetValueAndApply` и `SetValueAndApplyWithoutUndo` снова компилируются с аргументом `byte`, `sbyte`, `short`, `ushort` или `char` на Unity 6000.2 и новее: перегрузка для `EntityId` делала вызов неоднозначным (CS0121). Теперь у каждого из этих типов своя перегрузка, которая вызывает `SetInt`. -- XML-документация расширений UI Toolkit теперь совпадает с поведением. `SetValue(value, notify: true)` шлёт событие изменения, только если элемент в панели, а значение отличается. `SetPadding(8, 4)`, как `SetMargin`, `SetBorderWidth`, `SetBorderColor`, `SetDistance`, задаёт верхнюю и правую стороны. Слайдеру нужен диапазон до `SetValue`. Встроенную лямбду, переданную в `AddValueChanged`, нельзя снять через `RemoveValueChanged`. У `ListView` и `TreeView` `AddChild` бросает исключение, а `InsertChild`, `RemoveChildAt`, `ClearChildren` ничего не делают. Каждый метод, который есть только в новых версиях Unity, содержит строку `Available in Unity 6000.x and newer`. -- Документация `SerializableType`, `SerializableMonoScript`, `EnumValues` и строк `[TypeSelector]` теперь называет верный Managed Stripping Level для класса или enum, на которые поле ссылается только по сохранённому имени: Medium и High вырезают его из плеера, Minimal и Low сохраняют; раньше там стоял Low. Страница Serializable Types также перечисляет способы сохранить такой класс: `[Preserve]`, `link.xml` и `[RequireImplementors]` или `[RequireDerived]`. -- Значок `SHARED` в Asset References теперь вмещает свой текст; раньше он сжимался до ширины цветной точки, текст вылезал за его край, а точка закрывала букву «H». -- Asset References показывает незаполненные обязательные поля (карточки **Required type is not set** и значки REQUIRED) ассета из папки **Excluded scan folders**, как уже показывал его потерянные типы; в Project References и проверки build / CI такой ассет по-прежнему не попадает. -- Asset References больше не показывает сразу два состояния ассета с несохранёнными изменениями, например карточку заполненной ссылки рядом с янтарной карточкой о том, что то же поле не задано. Окно читает сохранённый файл, поэтому теперь сначала просит сохранить ассет и предлагает **Save Asset**. -- Незаполненное обязательное поле получает янтарную полосу у левого края, как поле с потерянным типом, в обоих Inspector: поле `[SerializeReference]` на UI Toolkit, а также строка `[TypeSelector]`, `SerializableType` и `SerializableMonoScript` на IMGUI и UI Toolkit. Раньше у них была только плашка; у поля `[SerializeReference]` на IMGUI полоса уже была. -- В обоих Inspector подпись пустого поля `[SerializeReference]` или поля, которое нечего раскрывать, а также поля имени типа с предупреждающей полосой стоит там же, где у заполненного поля, в одной колонке с соседними подписями, и больше не прыгает, когда поле заполняют или очищают. Раньше она была левее на ширину стрелки свёртки или правее на 5 px; полоса теперь висит слева от подписи, на месте стрелки свёртки. В UI Toolkit иконка плашки под полем начинается под подписью, как в IMGUI; раньше она была на 3 px левее. Текст плашки **Shared reference** в обоих Inspector начинается под подписью поля; в IMGUI он был на 3 px правее. -- В IMGUI Inspector у общей ссылки `[SerializeReference]` выпадающий список типа и значения дочерних полей стоят в одной колонке с полями вокруг, как в UI Toolkit; отступ под её полосу сдвигал их на 5 px вправо. -- Asset References больше не вешает редактор на ассете, где объекты `[SerializeReference]` ссылаются друг на друга: окно рисовало карточку на каждый путь по графу, а число путей растёт экспоненциально. Теперь объект показывает свои дочерние ссылки один раз, под первой карточкой, которая не стоит под потерянным типом; другое поле, которое на него указывает, получает свою карточку и свой путь поля, с пометкой **children on another card** в подвале. Окно рисует не больше 1000 карточек ссылок и сообщает, сколько пропустило; Project References исправляет потерянные типы без этого предела. Ассет со списком из тысяч объектов к тому же открывается быстрее. -- `GetDisplayName()` и `GetDisplayNameWithIndex()` больше не добавляют « (Script)», когда `[AddComponentMenu]` унаследован от базового класса или его путь пуст либо заканчивается на `/`; такие типы получают «очеловеченное» имя типа. Заголовок теперь берётся из атрибута, объявленного на самом типе, а тип с `[Obsolete]` больше не получает « (Deprecated)». -- Ссылка на член `[TypeSelector(nameof(...))]` у поля внутри `[Serializable]`-класса или элемента списка теперь разрешается на экземпляре, который объявляет поле, — так её уже проверяют анализаторы `AFT0006`–`AFT0008`. Раньше член искался на инспектируемом компоненте или ассете, и инспектор показывал предупреждение. То же относится к селектору окна Asset References. -- Если getter члена, на который ссылается `[TypeSelector(nameof(...))]`, бросает исключение, поле больше не ломается ошибками в консоли: оно рисуется без этого ограничения, а под ним появляется предупреждение с текстом исключения. -- `AFT0007` больше не ломает компиляцию на члене типа `Type?` при `#nullable enable` и теперь сообщает о свойстве без getter, которое инспектор не может прочитать. `AFT0004` теперь сообщает и о поле `UnityEngine.Object?`. -- `AFT0005` больше не предупреждает о generic-типе поля или базовом типе (`IState`, `Base`, `typeof(IFoo)`), у которого есть закрытая или открытая generic-реализация, и о реализации через `out`/`in`-вариантность — она больше не вызывает и `AFT0003`. Ни одно из них не срабатывает на поле типа generic-параметра (`T` в `Slot`). Несвязанный `typeof(Base<>)` больше не вызывает `AFT0003` и `AFT0005`, если поле может заполнить открытая generic-реализация вроде `Impl : Base`. -- `[field: TypeSelector]` и `[field: SerializeReference, TypeSelector]` на автосвойстве теперь проверяются правилами `AFT0001`–`AFT0009`, а `AFT0003` теперь проверяет и поля `SerializableType` и `SerializableMonoScript`. -- `AFT0008` теперь сообщает также об имени типа в `[TypeSelector]` без сборки, например `"Game.IWeapon"`, с подсказкой, какую сборку дописать: инспектор ищет такое имя только в mscorlib, поэтому пикер терял ограничение без предупреждения при компиляции. -- Тип поля или аргумент `typeof(...)`, который компилятор не может найти (пропала ссылка asmdef, класс ещё не создан) или чей базовый класс либо интерфейс он не может найти, больше не вызывает `AFT0001`, `AFT0003`, `AFT0005` или `AFT0009` вдобавок к ошибке компилятора. -- `AFT0005` теперь предупреждает, если класс из `typeof(...)` не подходит под тип поля и ни один его наследник тоже не подходит, например `[TypeSelector(typeof(Sword))]` на поле `IShield`; раньше селектор был пуст без предупреждения. Сообщение `AFT0005` теперь называет и тип поля, если он сужает выбор. -- `AFT0001` больше не ломает компиляцию на поле `[Serializable]`-наследника `SerializableType` с конструктором без параметров, которое инспектор рисует, а `AFT0007` принимает член любого типа `ISerializableType`, который инспектор читает. -- `AFT0003`–`AFT0006` называют типы с пространством имён и аргументами типа, поэтому два закрытых типа одного generic больше не выглядят как `'Slot'` и `'Slot'`. -- **Fix** и **Smart Fix** отсутствующего типа в сохранённом ассете в инспекторе UI Toolkit больше не выводят исключение; поля ссылок в других инспекторах обновляются сразу после ремонта. -- Потерянный тип `[SerializeReference]`, сохранённый без namespace, больше не сопоставляется с посторонним классом, у которого `[MovedFrom]` называет то же старое имя класса: gate и Project References не показывают его как ожидающую миграцию, **Migrate all** не переписывает его на этот класс, а Smart Fix не ставит этот класс первым. -- В Edit Mode уведомление *Shared reference*, его номер и пункт *Make Unique Reference* теперь обновляются сразу после правки из IMGUI-инспектора, через *Link to Existing* или в окне графа ссылок; раньше они показывали состояние до правки, пока не сменится выделение. -- После удаления элемента массива, внутри которого лежит список `[SerializeReference]` (список структур со списком внутри), список, занявший его место, больше не принимается за только что продублированный: **Auto de-alias** раньше разрывал его намеренные связи, например созданные через *Link to Existing*, на отдельные экземпляры. -- IMGUI-поле `[SerializeReference]` освобождает копию объекта, которую открывает для контекстного меню, выбора типа и **Fix**; отменённое меню или выбор держали её до сборки мусора, и на большом ассете росла нативная память. **Make Unique Reference** и скрипт, брошенный на поле, чей элемент списка тем временем удалён, больше не падают с `NullReferenceException`. -- Поле `[SerializeReference]` теперь всегда раскрывается и показывает новое значение после выбора типа, перетаскивания скрипта, **Paste**, **Paste Template** или *Link to Existing*. Раньше оно могло остаться свёрнутым: в IMGUI-инспекторе после любого из этих действий, в инспекторе UI Toolkit — после перетаскивания, шаблона или ссылки. -- Если у нескольких выделенных объектов поле `[SerializeReference]` хранит один и тот же тип, поле показывает этот тип с его полями для общей правки; раньше оно показывало «—» с подсказкой *Different types selected*, если объекты не были точными копиями. -- Смена типа теперь сохраняет те же экземпляры в полях `[SerializeReference]` внутри структур, сериализуемых классов, массивов и списков, а также в приватных полях `[SerializeReference]` без `[SerializeField]` (включая автосвойства с `[field: SerializeReference]`), как уже сохраняла другие вложенные ссылки; раньше туда попадали копии, поэтому поля, которые указывали на эти экземпляры, теряли связь. **Make unique** и исправление продублированного элемента списка теперь копируют такие ссылки вместе с остальными данными ссылки: два поля с общим экземпляром получают общую копию. -- Вложенное поле `[SerializeReference]` теперь сохраняет пользовательский drawer, зарегистрированный для его объявленного типа через открытый generic-тип (`typeof(Effect<>)`), базовый класс или интерфейс, даже без `useForChildren`, а также drawer базового класса атрибута; раньше пакет рисовал поверх них свой заголовок и выбор типа. Во вложенном списке такой drawer рисует каждый элемент и в IMGUI, и в UI Toolkit, а **+** сохраняет выбор типа. Drawer только хранимого типа выбор типа не заменяет. -- Вложенное поле `[SerializeReference]` без `[TypeSelector]` сохраняет `[Header]`, `[Space]` и `[Tooltip]` в IMGUI-инспекторе, как в UI Toolkit; IMGUI рисовал его без заголовка, отступа и подсказки. -- Несколько атрибутов `[Header]` или `[Space]` на одном вложенном поле `[SerializeReference]` больше не заставляют UI Toolkit Inspector бросать `AmbiguousMatchException` и не оставляют остальные поля объекта нерисованными; они рисуются по `order`. -- Вложенный список `[SerializeReference]` с пользовательским атрибутом для каждого элемента (`PropertyAttribute` с drawer-ом и выключенным `applyToCollection`) сохраняет **+** с выбором типа; раньше он превращался в обычный список Unity, где **+** добавляет элемент без выбора типа. Drawer атрибута по-прежнему рисует каждый элемент. -- Пользовательский drawer с `[SupportedOnRenderPipeline]` для другого render pipeline, а в Built-in pipeline любой drawer с такой пометкой, больше не отнимает выбор типа у вложенного поля `[SerializeReference]`. Unity такой drawer не использует, поэтому поле оставалось ни с чем; теперь пакет тоже его игнорирует. -- Сброс пользовательских настроек больше не перечисляет в подсказке и диалоге подтверждения удалённую опцию «Dropdown without [TypeSelector]». -- Клавиатурный фокус на вкладке Settings хорошо виден: у выбранной строки, кнопки сброса, папки в списке **Excluded scan folders** и его **+** появляется заметная рамка. Одна заливка выглядела как наведение. -- Enter на строке **Build / CI gate** вкладки Settings больше не перебирает Off, Warn и Fail по кругу. Стрелки влево и вправо переключают значения без зацикливания, а переход на **Fail** или **Off** спрашивает подтверждение: Fail ломает сборки команды, Off отключает проверку. -- `ComponentTypeSelector` теперь добавляет компоненты из `[RequireComponent]` нового класса и отменяет смену типа с предупреждением в Console, если она создала бы дубликат класса с `[DisallowMultipleComponent]`, убрала класс, который нужен другому компоненту, или потребовала компонент, который нельзя добавить. Нужные компоненты добавляются раньше нового класса, поэтому его `OnValidate` их уже находит. Раньше объект оставался без нужных компонентов или с дубликатами. -- `ComponentTypeSelector` больше не предлагает классы из Editor-сборок для компонента из runtime-сборки: в билде такого класса нет, и выбор оставлял missing script. -- `ComponentTypeSelector` отказывается менять класс компонента, унаследованного от префаба (экземпляр префаба в сцене, вариант префаба), и показывает предупреждение в Console. Unity не хранит переопределения для изменённого скрипта, поэтому новый класс терялся после сохранения и повторного открытия сцены или варианта. Меняйте класс в исходном префабе; компонент, добавленный на экземпляр, менять по-прежнему можно. -- **Create New Script…** у поля `[SerializeReference]` предлагает `NewInteractable` для `IInteractable` (было `Newnteractable`) и `NewEffect` для `IEffect` или generic-базового класса (было недопустимое ``NewEffect`1``, которое отклонялось при подтверждении). -- **Create New Script…** у поля `[SerializeReference]` теперь создаёт заглушку, которая компилируется для абстрактного класса (переопределяет все незакрытые абстрактные члены и передаёт аргументы конструктору, которому они нужны), для параметров `ref`, `out` и `in` и ref-возвратов, для generic-методов с их ограничениями, для индексаторов, для базового типа, вложенного в generic-тип, и для internal-базового типа в его сборке (заглушка тоже `internal`); раньше файл не компилировался, и ошибка блокировала Play Mode во всём проекте. Для sealed-класса, private- или protected-вложенного класса, internal-класса другой сборки, класса без доступного конструктора и абстрактных членов, которые новый скрипт не может переопределить, диалог объясняет причину и файл не создаётся. -- Сохранённый шаблон, тип которого сейчас не находится (другая ветка, удалённый пакет, класс перенесён в другой namespace или сборку), теперь только скрывается из **Paste Template**. Раньше открытие контекстного меню удаляло его навсегда, во всех копиях проекта. **Paste Template → Remove Missing (N)…** удаляет такие шаблоны по запросу, а перезапись такого шаблона по имени сообщает, что его тип не найден. -- Окно имени у **Save as Template…** открывается в центре окна редактора. Раньше оно брало центр разрешения основного монитора и могло открыться вне редактора на втором мониторе. -- **Excluded scan folders** принимает только `Assets` и папки внутри неё — только их обходят проектные сканирования. Папка из `Packages/` или другого места сохранялась, но ничего не исключала. -- Смена **Excluded scan folders** теперь перезапускает baseline определения поломок: тип, который используется только в исключённой папке, больше не вызывает уведомление о поломке, а папка, которую перестали исключать, снова попадает под проверку. -- Определение поломок теперь реагирует и на изменения файлов `.asmdef`, `.asmref` и `.dll`, которые переносят типы между сборками. Проверка, которая ждёт компиляции скриптов, больше не теряется при перезагрузке домена, которой компиляция заканчивается. -- Поиск в селекторе типов больше не совпадает с частью имени, где указана сборка: короткие запросы вроде `Key`, `Token`, `ver` или `null` находили все типы. Поиск сравнивает подпись, имя типа и полное имя с пространством имён и внешними типами (`Namespace.Outer.Name`). -- Ввод и Backspace в селекторе типов снова меняют запрос после перехода в результаты стрелкой вниз; раньше они пропадали, пока не щёлкнуть по полю поиска. -- Тип из сборки, которую Unity загружает во время сбора загруженных типов, больше не пропадает из первого селектора после перезагрузки домена. -- Поиск в селекторе типов ставит первым точное имя типа, затем имена, которые начинаются с запроса, затем имена, которые его содержат, и в конце типы, найденные только по пространству имён; `Button` больше не стоит после `ButtonGroup`. Равные совпадения идут в порядке пространств имён. -- Enter в поле поиска селектора типов выбирает первый результат; раньше он ничего не делал, пока стрелка вниз не переходила в список. -- Стрелка влево в результатах поиска селектора типов больше не поднимает селектор на уровень выше; после Esc список открывался не в той папке. -- Результаты поиска в селекторе типов показывают сначала имя типа, а после него приглушённо пространство имён, поэтому длинное пространство имён больше не вытесняет имя из строки. -- Раздел Recent селектора типов больше не пустеет после выбора типов в других полях: проект хранит последние 20 выборов, а раздел показывает самые новые из тех, что предлагает открытый селектор, столько, сколько разрешает настройка **Recent items**. Раньше хранилось столько выборов на все поля сразу. -- На Unity 6000.6 и новее поиск, после которого список селектора типов кончается выше выбранной строки, больше не переполняет стек, что обычно роняло Editor: обновление списка сообщало о смене выделения, а селектор отвечал на неё новым обновлением. -- Для потерянного типа селектор больше не выделяет ``, поэтому Enter сразу после открытия не стирает сохранённое имя. -- Выбор типа, который уже стоит в поле `[SerializeReference]`, или перетаскивание его скрипта больше не создаёт новый экземпляр: общая с другими полями ссылка остаётся общей, а экземпляр сохраняет все значения. При выделении нескольких объектов новый экземпляр получают только объекты с другим типом. -- Селектор типов выводит generic-аргумент, который поле оборачивает в массив: для поля `IHolder` тип `Box : IHolder` предлагается как `Box`; раньше открывалась страница аргумента. -- Страницы generic-аргументов селектора типов предлагают только типы, которые выполняют ограничения со ссылкой на параметр типа (`where T : IComparable`, `where U : T`) и оставляют generic-тип совместимым с полем; раньше такой выбор заканчивался ошибкой после щелчка. Параметр `where T : unmanaged` больше не принимает структуру со ссылочными полями: селектор собирал из неё тип, который C# не принял бы. -- Селектор типов больше не предлагает открытые generic-типы, которые никакой аргумент не делает совместимыми с полем, например `RefHandler where T : class` для поля `IHandler` или `Dictionary<,>` для поля `IEnumerable`; любой выбор на их странице аргумента заканчивался ошибкой. -- Для поля вариантного generic-интерфейса, например `IHandler` или `IProvider`, где подходят и другие аргументы, селектор типов сохраняет закрытую строку, выведенную из поля, `Handler`, и добавляет открытую строку `Handler`: её страница аргумента предлагает другие подходящие аргументы, например `object`. Раньше была только выведенная строка. -- Два вложенных типа с одним именем, например `PlayerController.State` и `EnemyController.State`, больше не показываются в пикере одинаковыми строками: их различает внешний класс, `State (PlayerController)`. Подсказка строки читается как `Namespace.Outer.Type, Assembly`, generic пишется `Box`, а не CLR-именем с версией сборки; у типа, вложенного в generic-класс, перечислены только его собственные аргументы (`Inner`, а не `Inner`). -- Пикер типов больше не предлагает служебные структуры компилятора (`__StaticArrayInitTypeSize=12` в группе ``): типы, вложенные в служебные типы компилятора, пропускаются. -- Подсказка клавиш внизу пикера типов умещается в окно шириной 400 pt: **Type to search** и **Esc Close** раньше обрезались. Стрелки ушли из подсказки, а клавиша избранного записана как `Space ☆`. -- Иконка `[TypeSelectorDisplay(Icon = "SwordIcon")]` из `Resources`, названная без `/`, загружается без ошибки «Unable to load the icon» в консоли. Такое имя сначала ищется в `Resources`, поэтому текстура из `Resources` теперь важнее иконки Unity с тем же именем. -- Пикер, открытый кнопкой **+** списка `[SerializeReference]`, размещается по своей настоящей ширине 400 pt вместо 350 pt, поэтому в узком инспекторе он больше не выходит за правый край на 50 pt. -- Пометка **Missing type** у элемента списка `[SerializeReference]` остаётся на этом элементе, если до сохранения вы удалили, переместили или добавили элементы; раньше она шла по старому индексу, поэтому переходила на другой элемент или пропадала. Пока по правкам не понять, какой элемент стоит в слоте, слот до сохранения не помечается. Ссылка внутри элемента списка обычных классов или структур до сохранения по-прежнему следует индексу этого элемента. Потерянная ссылка, для которой вы выбрали `` или вставили поверх пустую ссылку, больше не показывает **Missing type** до сохранения; Undo возвращает пометку. -- **Fix** у потерянного элемента списка `[SerializeReference]` в ассете с несохранёнными правками списка теперь применяет выбранный класс после **Save and Continue**; сохранение давало элементу новый id, поэтому исправление ничего не делало, пока вы не нажимали **Fix** ещё раз. -- Поле `SerializableType` или строка с `[TypeSelector]`, выбранные на нескольких объектах с разными значениями, теперь показывают «—», а селектор типов не выделяет ни одной строки; раньше поле показывало тип первого объекта, как будто он общий для всех. -- В инспекторе UI Toolkit выбор `` теперь очищает `SerializableMonoScript` с потерянным типом; раньше поле продолжало показывать ``. -- Поле `SerializableType` или строка с `[TypeSelector]`, переопределённые на экземпляре префаба, показывают подпись жирным, а их контекстное меню предлагает **Apply to Prefab** и **Revert**; раньше откатить значение можно было только через меню компонента. Инспектор UI Toolkit по-прежнему не рисует синюю полосу переопределения у своего края. -- Окно выбора у поля `SerializableType`, строки с `[TypeSelector]` и `TypeField` предлагает generic-классы для закрытого generic базового типа, например `Handler` для `IHandler`, как уже делали поля `[SerializeReference]`. -- `TypeField.Types` отбрасывает элементы `null`; раньше клик по полю бросал `NullReferenceException`, а окно выбора не открывалось. -- Всплывающая подсказка поля типа (`TypeField`, а также полей `SerializableType` и строк с `[TypeSelector]` в инспекторе UI Toolkit) показывает полное имя выбранного типа с namespace и сборкой, так что два класса с одним именем различимы; у кнопки открытия скрипта тоже есть подсказка. -- Привязанный `TypeField` обновляет `SerializedObject` своего свойства до отправки `ChangeEvent`: обработчик изменения читает выбранный тип из этого свойства, а правки, которые обработчик применяет через этот объект, больше не отменяют выбор. -- `TypeField`, привязанный к нескольким объектам, больше не обновляет отображение каждые 100 мс без изменений и перестаёт проверять значения, когда цель удалена. -- `PropertyField` над `SerializableType`, `SerializableMonoScript` или строкой с `[TypeSelector]` теперь отправляет `ChangeEvent` со старым и новым именем типа, когда выбран тип или на поле брошен скрипт. Раньше он не отправлял ничего; Unity 6000.4 пропускал лишь событие с подписью поля, например `Int32`. -- При выделении нескольких объектов с разными значениями поле `SerializableMonoScript` показывает `—` без кнопки скрипта, а не тип первого объекта (UI Toolkit, IMGUI). В UI Toolkit выбор этого первого типа теперь записывается в остальные объекты; раньше ничего не записывалось. -- В IMGUI-инспекторе поле `SerializableType` или строка с `[TypeSelector]` при разных значениях выделенных объектов больше не показывает кнопку скрипта, которая открывала скрипт только первого объекта, а выключенное поле `SerializableMonoScript` или `[SerializeReference]` больше не принимает перетащенный скрипт. -- Drawer `SerializableType` и строк с `[TypeSelector]` в UI Toolkit больше не оставляет копию `SerializedObject` при каждом обновлении и не бросает `NullReferenceException`, когда свойства уже нет, например после удаления элемента списка. -- Выбор типа в IMGUI-инспекторе у `SerializableType`, `SerializableMonoScript`, строк с `[TypeSelector]` и `ComponentTypeSelector`, а также подсказка **→ TypeName** больше не держат копию объекта до сборки мусора после отменённого выбора, из-за чего на большом ассете росла нативная память; копия открывается, когда тип выбран, и сразу освобождается. Drawer'ы `SerializableMonoScript`, `[TypeSelector]` и `ComponentTypeSelector` в UI Toolkit больше не держат копию объекта, пока открыт их инспектор. Компонент, уничтоженный между выбором и заменой класса в `ComponentTypeSelector`, больше не вызывает исключение, а drawer `SerializableType` и строк с `[TypeSelector]` в UI Toolkit продолжает обновляться, когда инспектор уже освободил свой `SerializedObject`. -- **+** у списка `[TypeSelector]` `[SerializeReference]`, вложенного в элемент другого массива (список структур, список внутри элемента списка), теперь добавляет элемент в этот список; раньше он бросал `InvalidOperationException` и ничего не добавлял. -- **+** у массива, элементы которого содержат поле `[TypeSelector]` `[SerializeReference]` (например, `WeaponSlot[]`), теперь добавляет обычный элемент; раньше, если в массиве уже был элемент, он открывал селектор типа этого поля и бросал исключение. -- **+** у списка managed references при выборе нескольких объектов теперь добавляет независимый экземпляр в каждый объект одной группой Undo. В IMGUI раньше менялся только первый объект, а в UI Toolkit новый элемент делил экземпляр с предыдущим. -- Инспектор `EnumValues` больше не переписывает ключи при отрисовке: строка, ключ которой enum не может распознать (после смены enum в `EnumValues`, переименования или удаления члена), показывается со своим ключом, например ``, и сохраняет его, пока вы не выберете член. Раньше ей подставлялся первый член enum, и возврат прежнего типа строки не восстанавливал. Строка, добавленная в пустую таблицу, теперь показывается как `` и пропускается с ошибкой, пока вы не выберете член; раньше ей автоматически подставлялся первый член. -- Инспектор `EnumValues` больше не пишет в ассет при отрисовке: раньше он добавлял запись Undo и помечал ассет изменённым, когда копия типа enum в строке отличалась от типа таблицы. Строки больше не хранят эту копию, поэтому перенос enum не затрагивает каждую строку в diff и слияниях; старая строка `_enumType` у строк существующего ассета исчезает при его следующем сохранении. -- **Populate Missing Enum Members** теперь работает, когда значение — массив или `List`; раньше пункт бросал исключение и оставлял недосозданную строку. Для enum с алиасами (`Default = Medium`) каждое значение добавляется один раз, а пункт становится неактивным, когда строки есть у всех значений; раньше каждое нажатие добавляло дубликат. -- **Populate Missing Enum Members** неактивен, пока выделено несколько объектов, и пропускает члены enum с `[Obsolete]`. Раньше при нескольких выделенных объектах всем ставился один размер массива: у объекта с большим числом строк лишние пропадали, а остальные перезаписывались строками первого. -- Строка `EnumValues` с `[Flags]`-enum на `long` или `ulong`, а также на `uint` с членом в 31-м бите, получает выпадающий список флагов, который сохраняет все биты; для 64-битного enum IMGUI-инспектор раньше бросал исключение при каждой перерисовке, а UI Toolkit показывал неверную маску и записывал другой ключ. -- Строка `EnumValues`, ключ которой — член enum с `[Obsolete]` (для `[Flags]` — комбинация, включающая такой член), теперь показывает ключ по имени. Раньше выпадающий список был пустым, а для флагов показывал `None` или `Everything`. -- В UI Toolkit-инспекторе выпадающий список ключа строки `EnumValues` теперь следует за Undo, Revert и Paste, а заголовок таблицы показывает метку, переданную в `PropertyField`, а не всегда имя поля. -- Drawer `EnumValues` больше не бросает `NullReferenceException`, когда Unity не находит поле для свойства. -- Окно выбора типа у `EnumValues` больше не предлагает абстрактный `System.Enum`. Выбор этого типа заполнял поле, поэтому проверка обязательных полей молчала, но таблица не могла найти ни одну строку и всегда возвращала **Default Value**. -- `EnumValues` безопасно инициализирует строки, когда первое обращение приходит из нескольких потоков: на процессоре со слабым порядком памяти другой поток мог увидеть таблицу готовой раньше её строк и вернуть **Default Value** для существующей строки. -- Энумератор `EnumValues` возвращает `default` из `Current` после того, как `MoveNext` вернул `false`, как сказано в его документации. Раньше там оставалась последняя строка. -- Выбор **Everything** или всех флагов в выпадающем списке ключа строки `EnumValues` с `[Flags]`-enum теперь сохраняет определённые флаги enum, например `Left, Right`. Раньше сохранялось `-1`, и `GetValue` такую строку не находил. -- В IMGUI-инспекторе строка `EnumValues` со значением `Rect`, `RectInt` или `Bounds` теперь такой же высоты, как поле, и не налезает на следующую строку, а заметка поля типа enum (**Required type is not set**, **Missing type**) больше не рисуется поверх таблицы под ней. -- Undo после **Fix** отсутствующего типа в открытой сцене или Prefab Mode возвращает отсутствующую ссылку вместе с сохранёнными данными; раньше поле оставалось пустым, а следующее сохранение записывало `rid: -2`. Заменённая запись теперь удаляется при сохранении сцены или префаба (Auto Save в Prefab Mode сохраняет сразу после Fix), поэтому предупреждение Unity об отсутствующих типах остаётся до сохранения; это сохранение также очищает историю Undo объекта, поэтому восстановление уже не отменить. -- **Fix** отсутствующего типа в открытой сцене или Prefab Mode теперь чинит все поля, которые делят эту отсутствующую ссылку, и поля по-прежнему указывают на один экземпляр; раньше остальные поля до сохранения показывали `` без **Fix**, а сохранение записывало их пустыми. Пикер классов и подсказка **→** предлагают только классы, подходящие каждому такому полю. -- **Fix** отсутствующего типа в сцене или Prefab Mode переносит в новый класс больше сохранённых данных: раньше числа с плавающей точкой в экспоненциальной записи (`9.99e-05`) терялись, текст с не-ASCII-символами, табуляцией или переводами строк сохранял кавычки с escape-кодами, длинный текст терял часть, которую Unity переносит на следующие строки, `Infinity` и `NaN` превращались в 0, а текст вида `1.5` — в `1.500000`. Значение, которое новый класс не принимает, больше не отменяет перенос остальных полей. -- Editor-сборка пакета теперь компилируется в Unity 6000.5, где `Object.GetInstanceID()` стал ошибкой (CS0619); раньше проект оставался в Safe Mode, и ни один editor-инструмент пакета не работал. -- `Aspid.FastTools.VisualElements.Math` теперь компилируется на Unity 6000.5 и новее в проекте без `com.unity.mathematics`. `Unity.Mathematics` там входит в движок, но `SetValue` и `AddValueChanged` для `float2`, `int3` и остальных типов оставались недоступны, пока не поставлен пакет. -- Поля в обычном инспекторе, UI Toolkit или IMGUI, теперь учитывают светлую тему редактора: drawer `EnumValues` берёт фон из темы Unity, уведомления о ссылках и подпись пропавшего типа у полей `[SerializeReference]` — цвет предупреждения Unity, а иконки предупреждения, информации и папки — варианты для светлой темы. -- Окно выбора типа читается в светлой теме редактора: открытое из поля инспектора, оно берёт светлую палитру и светлые иконки папок, Favorites и Recent; раньше светлый текст тёмной палитры рисовался на светлом фоне всплывающего окна Unity. -- Блоки подсказок в окнах FastTools читаются с контрастом от 4,5:1 на любом статусном цвете: их заголовок и текст берут самый контрастный оттенок. На светлой теме блоки подсказок берут светлые иконки, а ссылки и действия статусных цветов стали темнее. В выпадающем окне выбора типа счётчики, стрелки, подсказки и текст ошибки на тёмной теме стали ярче, а на светлой — темнее. Звезда Favorites на светлой теме тоже стала темнее. В инспекторе на светлой теме уведомление *Shared reference* затемняет текст и **Make unique**. Точка с полосой при этом сохраняют свой цвет. На светлой теме ссылки уведомлений при наведении темнеют, а не бледнеют. Кнопка удаления в Excluded Folders при наведении читается лучше на обеих темах. -- Вкладка Welcome окна FastTools тоже учитывает тему; раньше она оставалась во встроенной палитре. -- Версия, ссылка **GitHub** и логотип окна FastTools показывают курсор-ссылку при наведении, а версия и подсказка клавиш в футере набраны более контрастным тоном, который легче читать. -- Подсказка клавиш в футере окна FastTools больше не заходит на версию в узком закреплённом окне: она занимает место между версией и ссылкой и заканчивается многоточием, если не помещается. -- Подсказка клавиш в футере окна FastTools на вкладке Settings называет стрелки влево и вправо (`←→ adjust`): там они переключают **Build / CI gate** и слайдеры. На остальных вкладках, где эти стрелки ничего не делают, остаётся прежняя подсказка `↑↓ navigate ⏎ activate esc dismiss`. -- Если пакет лежит в `Assets` не в `Assets/Aspid/FastTools` (импорт из Asset Store, перенесённый в другую папку), футер показывает версию вместо `v?`, а вкладка Welcome перечисляет примеры; папка пакета теперь находится по GUID его `package.json`. -- **Import** примера на вкладке Welcome больше не падает молча, если в проекте есть копия этого примера от старой версии пакета: окно спрашивает подтверждение, заменяет старую копию и импортирует текущую. Раньше оно показывало «Failed to import» и ничего не копировало. -- Окно Welcome открывается один раз после обновления пакета, установленного в `Assets` (Asset Store, `.unitypackage`); флаг «уже показано» следовал версии, которая там всегда была `unknown`, поэтому не менялся. -- Импорт пакета в `Assets` (Asset Store, `.unitypackage`) больше не пишет в Console пять предупреждений «Asset reference to GUID … was moved» для окна Welcome: оно берёт лист стилей и логотип из Resources, а не по ссылкам с путём к ассету. -- Окно Welcome больше не обещает «string ID tooling», которого нет в пакете; его текст называет основные возможности. -- Тема теперь перекрашивает карточки, панели, статусные заливки, полосы прокрутки, фон из точек и переключатели окон Aspid: их цвета вынесены в токены `--aspid-colors-*`, а переключатели читают необязательные токены `--aspid-colors-switch-*`. -- Рамки выпадающих списков и поля значения слайдера, а также дорожка слайдера на вкладке Settings и на её страницах в Project Settings и Preferences достигают контраста 3:1 в тёмной и светлой темах; раньше они были едва заметны. Цвет задаёт новый токен `--aspid-colors-control-border`, поэтому тема может его изменить. -- На Unity 6000.0–6000.2 поле `[SerializeReference]`, пикер и окна Project References и Asset References снова получают стили: два листа стилей использовали запись цвета, которую эти версии не разбирают, поэтому каждый отбрасывался целиком, а при импорте в Console появлялась ошибка. -- Кнопки и foldout'ы внутри поля `[SerializeReference]`, нарисованного на UI Toolkit, сохраняют свой вид: кнопка пользовательского drawer'а или `+` / `−` вложенного списка больше не сжимается до 18×18 с иконкой папки, а вложенный foldout больше не перенимает раскладку заголовка поля. -- Когда выделены несколько объектов с разными типами в поле `[SerializeReference]`, поле на UI Toolkit теперь красит «—» так же, как стандартные поля Unity при разных значениях; раньше оно показывало его обычным цветом текста. -- Fix, Fix all и Undo в сводке больше не переписывают тип исправной managed-ссылки, если на сломанную указывает `[SerializeReference]`-список внутри другой ссылки (родитель со списком детей). Inspector читает у таких ссылок правильный сохранённый тип и поля, а граф Project References больше не показывает фантомные узлы, чей Clear удалял исправные entry. -- Если отсутствующую ссылку делят поля разных типов, пикер классов и **Smart Fix** в Asset References предлагают только классы, подходящие всем этим полям, как и в группе Project References, где у всех ссылок одинаковые типы полей; цель `[MovedFrom]` считается ожидающей миграцией, только если подходит им всем. Раньше проверялось одно из полей, и после перезаписи остальные становились пустыми. -- Защита missing-списков теперь сохраняет снимок missing-элемента, на который указывает ещё и список другой ссылки, и восстанавливает его в собственный список объекта, а не в одноимённый список, вложенный в другое поле. -- Защита missing-списков больше не возвращает missing-элемент списка, который вы удалили или сделали `` и сохранили; если удалён другой элемент, она восстанавливает missing-элементы по их новым индексам. Если удалённый элемент стоял среди других missing- или ``-элементов, по сохранённому файлу не понять, какой именно: защита оставляет ``-элементы и первые missing-элементы, а последний missing-элемент не восстанавливает. Загруженные сцены и префабы, сохранённые из Prefab Mode, больше не защищаются: защита не переписывает их файлы и не восстанавливает их missing-элементы списков. -- Как выбор типа и **Paste**, перетаскивание скрипта, **Paste Template**, *Link to Existing* или **Create New Script…** на missing-элементе списка теперь сообщают защите missing-списков, что элемент заменён. Раньше после такой замены и удаления другого элемента сохранение могло потерять другой missing-элемент того же списка. -- Элемент списка, восстановленный защитой missing-списков, сохраняет исходный id ссылки, если он свободен, а иначе получает случайный. Раньше он брал следующий id после максимального в файле, который часто уже занимал override в варианте, вложенном префабе или сцене: такой override терял свой тип и делил данные с восстановленным элементом. -- Защита missing-списков находит слот missing-элемента по id ссылок остальных элементов, поэтому элемент переживает перестановку, удаление вместе с добавлением, вставку или перемещение за одно сохранение; раньше защита смотрела на старый индекс и молча теряла его. Missing-элемент, на который указывают два слота, теперь возвращается в оба, а выбор `` для одного из них больше не теряет другой. -- Защита missing-списков сохраняет выбор `` для missing-элемента после перезагрузки скриптов, а также после Undo другой правки; расходует его только сохранение, которое записало файл, а изменение файла вне редактора, например откат в системе контроля версий, его отменяет. Сообщение в Console называет восстановленные элементы, а о missing-элементах без слота предупреждает с их индексом и `rid`. Защита читает и записывает файл один раз за сохранение, а файлы без managed-ссылок пропускает: сохранение списка из тысяч элементов больше не замораживает редактор, правка сразу после сохранения больше не теряется при перезаписи файла. -- Объекты с отрицательным fileID (компоненты префабов, под-ассеты) теперь читаются как отдельные документы: их missing-ссылки попадают в сканы и build gate, незаполненные required-поля — в сканы, а Fix, Clear и удаление orphan больше не правят и не удаляют entry соседнего объекта. -- Сканы SerializeReference теперь читают Animator Controller (`.controller`) и Timeline (`.playable`). Потерянные типы в их StateMachineBehaviour, треках и клипах попадают в Project References, build gate, обнаружение поломок; раньше эти файлы пропускались. -- Тип `[SerializeReference]`, в имени класса, пространства имён или сборки которого есть символы вне ASCII (кириллица, CJK), больше не считается потерянным в сканах и build gate, а защита удаления теперь находит его использования. Unity пишет такое имя escape-последовательностями `\uXXXX` в двойных кавычках, теперь они раскодируются; то же относится к именам, которые хранят `SerializableType` и `SerializableMonoScript`. -- Поле `[SerializeReference]` в варианте префаба, вложенном префабе или экземпляре в сцене с потерянным типом теперь показывает **Missing type** вместо пустого ``; подсказка называет исходный префаб, где нужно чинить тип, или сообщает, что тип хранится в override префаба. Обязательное поле с таким потерянным типом больше не считается незаданным в `-srGateRequired` и окнах References. -- Новый элемент списка `[SerializeReference]`, пустого в сохранённом файле, больше не показывает **Missing type** элемента следующего списка до сохранения ассета. -- Уведомление о поломке больше не ждёт, пока Project References просканирует проект в этой сессии: базовую линию задаёт фоновое чтение файлов ассетов в начале сессии, а ассеты, сохранённые позже, её обновляют, поэтому тип, впервые назначенный в этой сессии, тоже отслеживается. О типе, сломавшемся до окончания этого чтения, уведомление не появляется. -- Удаление скрипта, в котором объявлены только компоненты или ScriptableObject, больше не сканирует все ассеты проекта; для остальных скриптов при долгой проверке появляется прогресс-бар, и кнопка отмены в нём отменяет удаление. -- Защита удаления теперь предупреждает обо всех типах, объявленных в скрипте, в том числе в файле без класса с его именем (`Pistol` и `Rifle` в `Weapons.cs`) и о вложенных типах (`Outer.Inner`); раньше проверялся только класс с именем файла. `partial`-тип учитывается, только если ни один оставшийся скрипт не объявляет другую его часть. -- Защита удаления больше не тормозит при удалении многих скриптов или большой папки: ассеты без managed-ссылок пропускаются до поиска имён классов, а из нескольких скриптов или папок одного удаления весь проект просматривает только первый, остальные перечитывают лишь ассеты с managed-ссылками. Отмена в прогресс-баре отменяет удаление этого скрипта или папки, а также каждого следующего, которым нужна проверка. -- Один ответ защиты удаления может покрыть всё удаление. Если в выделении Project window несколько скриптов или папок, в её диалоге появляется третья кнопка **Delete All Anyway**, а **Cancel** оставляет каждый другой скрипт или папку этого удаления, которым всё ещё пользуются, без повторных вопросов; **Delete Anyway** по-прежнему отвечает за один скрипт и спрашивает про следующий. Ответ действует до конца удаления, поэтому следующее удаление спросит снова. Диалог одного скрипта или одной папки не изменился, а удаление из кода без выделения сначала показывает обычный диалог, а третью кнопку добавляет со второго. -- Сканы SerializeReference пропускают двоичные ассеты и указатели Git LFS по первым байтам файла, а не декодируют каждый файл как текст при каждой сборке. Build gate и проверка в CI предупреждают, если файлы остались непроверенными (любой двоичный файл вне режима **Force Text**, двоичный префаб, сцена или ScriptableObject в режиме **Force Text**, нескачанный указатель), а отчёт CI считает и перечисляет такие файлы; раньше такой проект проходил с 0 нарушений. -- Build gate и проверка в CI теперь предупреждают о файле, где managed-ссылки хранятся в старом формате (`references: version: 1`, ассет, последний раз сохранённый до Unity 2021.2) или в неизвестном им формате, а отчёт CI перечисляет его как `UnsupportedReferencesVersion`; раньше такой файл проходил как чистый. Строка заголовка отчёта теперь `# Not scanned: N`, без `(not text YAML)`. -- Проектный скан managed-ссылок (индекс для **Find Usages**, защита от удаления и обнаружение поломок) больше не строит путь поля для каждого указателя файла: файл со списком из 8000 ссылок читался около 9 секунд, теперь около 0,2 секунды. -- Массив или список с `[TypeSelector(Required = true)]` на сцене больше не считается незаполненным в `-srGateRequired` и Project References: как и обещает документация, коллекции на сценах не проверяются. -- Project References больше не пишет «Project clean» и «Nothing left to repair», пока required-поля не проверены (до первого Scan Project, после очистки в Prefab Mode либо в открытой сцене или при gate severity Off), а объясняет, почему они не проверены, и предлагает Rescan. После очистки ссылок на диске заново проверяются изменённые файлы, а также варианты и префабы, вкладывающие изменённый префаб, поэтому их required-нарушения остаются в списке, а заголовок предупреждает о них. -- Project References больше не пишет «Project clean», если Scan Project не смог прочитать часть файлов: двоичные файлы и указатели Git LFS считаются в окне и перечислены в Console, а Asset References для такого ассета пишет «Not scanned» вместо «No managed references». Окно больше не утверждает, что имён типов нет, когда был прогрет только индекс (после Unity Search или другой функции): оно предлагает **Rescan**. Подсказка про **Fix all** появляется, только если в списке есть группа сломанных типов, а подсказка рядом с именами типов или required-нарушениями говорит, что они взяты на момент последнего скана. -- Файл, который не удаётся открыть (его заблокировала другая программа, нет прав на чтение, его удалили во время скана), сканы SerializeReference больше не называют двоичным: build gate и проверка в CI предупреждают, что файл не удалось открыть и нужно закрыть программу, которая его держит, а не советуют **Force Text**; отчёт CI перечисляет такой файл как `Unreadable`, `-srGateStrict` считает его, как остальные непроверенные файлы, Asset References называет настоящую причину, а Project References считает файл и отсылает к Console. Сканы также читают текстовый ассет, который другая программа держит открытым на запись (Windows раньше отказывал в чтении), и перечисляют файл, ставший нечитаемым между проверкой формата и чтением, а не пропускают его как чистый. -- Сводка после **Fix all** и **Clear** в Project References показывает, сколько записей не удалось переписать (файл только для чтения или заблокирован, запись изменилась после скана), и отсылает к Console; если исправление ничего не изменило, сводка так и пишет, а не «Rewrote 0». -- Проверка required-полей в `-srGateRequired` и Scan Project теперь выгружает загруженные префабы и ассеты, поэтому её память больше не растёт с размером проекта. -- Project References больше не загружает заново все затронутые префабы при каждом возврате на его вкладку, из-за чего окно зависало, если потерянный класс хранится в сотнях префабов. Типы полей группы читаются один раз и хранятся до импорта префаба или ассета либо до Rescan, загруженные при этом префабы выгружаются пачками, а строка required-нарушения берёт имя компонента из скана, а не загружает файл заново. Группа показывает первые 200 записей, а **Show more** добавляет следующие 200. -- Scan Project показывает индикатор прогресса при проверке required-полей, и оба прохода можно отменить. Отменённый скан оставляет прежние результаты и сводки. -- В режиме `Warn` CI-проверка пишет нарушения в журнал как предупреждения, а не как ошибки, поэтому обёртка, которая ищет в журнале ошибки, больше не принимает запуск с кодом `0` за сбой. -- Журналы сборки и CI перечисляют не больше 50 нарушений, считают остальные и не несут стека вызовов; CI-отчёт по-прежнему содержит все. CI-запуск, у которого нет папки отчёта, теперь пишет нарушения в журнал до сбоя. -- Очистка ссылок и исправление имён типов в Project References больше не запрашивают у Unity зависимости каждого префаба проекта при каждом действии, чтобы найти варианты и префабы, вложившие изменённый; карта строится один раз за Scan Project. -- Assign Required для поля `SerializableMonoScript` в Asset References теперь предлагает только типы со скриптом, как и Inspector; раньше можно было выбрать вложенный, generic-тип или тип из DLL, и ссылка на скрипт терялась. -- Незаданное обязательное поле `SerializableType`, `SerializableType` или `SerializableMonoScript` в префабе или ScriptableObject теперь указывается в `-srGateRequired`, CI-отчёте и окнах References по своему пути (`weaponType`), как на сцене; раньше путь оканчивался на `._assemblyQualifiedName`. -- В редакторе `SerializableMonoScript` теперь берёт тип из своего скрипта, если сохранённое имя больше не находится. Объект, загруженный в Play Mode после переименования класса (дополнительная сцена, `Resources.Load`, вход в Play Mode без перезагрузки домена и сцены), больше не получает `null`, пока его ассет не пересохранён. -- `SerializableType` и `SerializableMonoScript` теперь кешируют и неудачный поиск: чтение `.Type` у потерянного типа больше не вызывает `Type.GetType` каждый раз, а кеш сбрасывается при смене сохранённого имени. -- В редакторе сериализация `SerializableMonoScript` вне главного потока больше не вызывает `MonoScript.GetClass`, который работает только на главном потоке; сохранённое имя обновится при следующем сохранении на главном потоке. -- Исправление пропавшего типа `[SerializeReference]` (смена типа, очистка, удаление осиротевшей записи, восстановление элемента списка) теперь сначала делает checkout ассета в системе контроля версий, как это делают сохранения самого Unity. Ассет только для чтения остаётся нетронутым с понятной ошибкой вместо исключения доступа, правка заменяет файл за один шаг, поэтому сбой записи больше не оставляет его обрезанным, а BOM UTF-8 сохраняется. -- Исправления, которые правят файлы ассетов напрямую (пропавшие типы `[SerializeReference]`, пропавшие имена типов, восстановленные элементы списков), теперь проверяют новый текст перед заменой файла. Если правка теряет или задевает другой объект либо managed reference, или файл изменился на диске после того, как исправление его прочитало, файл остаётся нетронутым с ошибкой. -- Исправление, которое правит файл ассета, больше не заменяет байты, не являющиеся корректным UTF-8, на U+FFFD во всём файле: такой файл остаётся нетронутым с ошибкой. -- Очистка пропавшей ссылки `[SerializeReference]` больше не ставит `-2` в ваше собственное поле `rid`, если в нём хранится id очищаемой ссылки: обнуляются только поля и элементы списков, которые указывают на ссылку. -- Сканы `[SerializeReference]` с исправлениями больше не зависят от языка системы, когда читают или пишут идентификаторы вроде `rid: -2` либо отрицательные fileID. На рантайме CoreCLR шведская, финская или норвежская локаль писала `−2` с юникодным минусом, который Unity не читает, а арабская, ивритская или персидская не читала отрицательные идентификаторы. -- Общие настройки SerializeReference (**Build / CI gate**, **Excluded scan folders**, **Auto de-alias duplicated list elements**) теперь следуют за файлом `ProjectSettings/SerializeReferenceSharedSettings.asset`, пока редактор открыт. Страница настроек, изменение одной настройки (в том числе добавление или удаление исключённой папки), **Scan Project** и build gate перечитывают файл, поэтому значения, полученные из репозитория, больше не остаются устаревшими и не перезаписываются следующим изменением. Перед записью файл ещё и берётся на checkout в системе контроля версий; если он остаётся только для чтения, настройка сохраняет значение, а ошибка объясняет причину, вместо отката после перезапуска. -- Восстановление потерянного типа больше не отбрасывает молча несохранённые изменения восстанавливаемого ассета. **Fix** и **Smart Fix** в инспекторе, а также восстановление и очистка в Asset References предлагают сначала сохранить такой ассет; **Fix all**, **Clear** и **Undo** в Project References пропускают его или очищают в памяти. **Fix** в инспекторе больше не переписывает префаб, открытый в Prefab Mode. -- Смена типа здоровой ссылки и заполнение пустого или обязательного поля в Asset References (**Change ▼**, **Assign ▼**, **Assign Required ▼**) больше не пишут в префаб, открытый в Prefab Mode: диалог просит сначала закрыть его. Раньше изменение попадало в файл, а следующее сохранение стейджа перезаписывало его. -- Итоги в Project References вместе с их **Undo** теперь переживают переход на другую вкладку окна, в том числе переход в Asset References по строке записи; раньше они пропадали вместе с вкладкой. **Rescan**, закрытие окна или перезагрузка домена по-прежнему очищают их. -- Окно FastTools после перекомпиляции скриптов или входа в Play Mode открывается на той вкладке, где вы остановились; раньше оно возвращалось на Welcome. -- **Tools → Aspid 🐍 → FastTools → Asset References** без выделения или с выделением, которое нельзя разобрать (объект сцены, не являющийся экземпляром префаба, папка, текстура), оставляет ассет, который вкладка уже показывает; раньше он заменялся пустым. -- `this.Marker()` внутри вложенного типа `private` или `protected` больше не ломает компиляцию ошибкой CS0122. Сгенерированная перегрузка не видит такой тип, поэтому генератор теперь его пропускает: вызов компилируется, маркер не открывается, а `AFT0010` сообщает об этом — чтобы профилировать тип, сделайте его `internal` или `public`. -- `this.Marker()` в типе, вложенном в generic-тип (`Outer.Inner`), теперь компилируется; раньше сгенерированной перегрузке не хватало параметров внешнего типа (CS0246). -- `this.Marker()` в аксессоре индексатора и в статическом конструкторе теперь компилируется; раньше имена сгенерированных полей были недопустимыми. Маркеры называются `Type.Indexer (line)` и `Type.StaticCtor (line)`. -- `this.Marker()` в аксессоре события теперь называется по имени события, как в аксессоре свойства: `Type.Changed (line)` вместо `Type.add_Changed (line)` / `Type.remove_Changed (line)`, в том числе в явной реализации интерфейса. -- `this.Marker()` больше не ломает компиляцию в инициализаторе авто-свойства, в статическом классе и в методе интерфейса по умолчанию, в пространстве имён или параметре типа с именем-ключевым словом (`Game.@event`, `Foo<@event>`), а также когда имена типов различаются только регистром или сводятся к одному имени (`Foo`/`foo`, `Foo`/`Foo_1`, `Outer.Inner`/`Outer_Inner`); в части этих случаев пропадали все маркеры сборки. -- `this.Marker()` в типе с `[Obsolete]`, во вложенном в него типе и в generic-типе с таким ограничением больше не вызывает CS0618 в сгенерированном коде, а в типе с `[Obsolete(..., true)]` больше не ломает компиляцию ошибкой CS0619. -- `Foo`, `Foo` и `Foo` в одном пространстве имён больше не делят один сгенерированный класс, в котором маркеры получал только первый тип; маркеры собственного `EnumValues` пакета теперь открываются. -- Вызов `this.Marker()`, разбитый на несколько строк или стоящий под директивой `#line`, теперь открывает свой маркер; генератор брал не ту строку, что `[CallerLineNumber]`. -- Generic-структура с `[BurstCompile]` больше не ломает сборку Burst (BC1025/BC1360). -- Тип, унаследованный от типа другой сборки, с которой он делит пространство имён через `InternalsVisibleTo`, теперь получает собственные маркеры; раньше его вызовы попадали в перегрузку базового типа и ничего не открывали. -- `WithName($"Br{{ace}}")` даёт `Br{ace}`, текст `WithName` с U+2028, U+2029 или U+0085 компилируется, а собственное расширение `WithName` пользователя больше не переименовывает маркер. -- `WithName` теперь читает `const`, `nameof(...)`, а также конкатенацию или интерполяцию констант; раньше такое имя молча оставляло имя члена. -- `Persistent()` больше не оставляет неосвобождённым созданный `SerializedObject`, если путь свойства больше не существует на целевых объектах: он освобождается перед возвратом `null`. -- `AddChildren`, `InsertChildren` и их варианты `…If` с `IEnumerable` больше не бросают `InvalidOperationException` («Collection was modified»), когда получают `Children()` другого элемента: `target.AddChildren(source.Children())` переносит всех детей. -- `TryGetByEnum` возвращает `false` для числа из USS, которого нет среди значений enum (`--preview-theme: 7;`) и для списка через запятую у enum без `[Flags]`, и элемент сохраняет значение по умолчанию вместо несуществующего. `[Flags]`-enum принимает только имена. -- Пример Types: селектор `Enemy Type` больше не предлагает абстрактный `Enemy`, из-за которого появлялись пустые капсулы и ошибка на каждого врага; шаг руководства с переименованием теперь использует Rename-рефакторинг IDE, и `ArmoredGrunt` продолжает компилироваться. -- Пример Types: `Brute` больше не уходит наполовину под платформу; его высота теперь зависит от масштаба. -- Пример SerializeReferences: при импорте больше нет предупреждения CS0414, а удаление Training Dummy в Play Mode больше не бросает `MissingReferenceException` на каждом выстреле. -- Пример EditorTools: окно Ability Catalog отслеживает ассеты, созданные или удалённые в окне Project, а **Create** выделяет новый ассет и при активном поиске. -- Пример EditorTools: окно Ability Catalog сохраняет текст поиска в раскладке окон, поэтому он переживает перезапуск редактора. -- Пример EditorTools: окно Ability Catalog освобождает `SerializedObject` показанной способности, когда вы выбираете другую или закрываете окно; раньше каждый держался до сборки мусора. -- Примеры EnumValues и ProfilerMarkers больше не ломают компиляцию проекта без встроенного модуля Physics: там их скрипты пропускаются, а в описаниях примеров сказано, что модуль нужен. -- Пример EnumValues: Walker больше не ставит `[InspectorName]` на поля, где Unity его игнорирует (атрибут читается только у значений enum); подписи в инспекторе — **Step Interval** и **Footprint Lifetime**, а **Log Tables** выводит ту же подпись. -- Примеры Types и SerializeReferences: в описаниях сказано, что коллайдерам их сцен нужен встроенный модуль Physics. -- Внутренние элементы редактора пакета (`AspidBox`, `AspidLabel` и ещё десять) больше не показываются в UI Builder Library вашего проекта: они сделаны для окон FastTools и в вашем UXML выглядят без оформления. -- Иконка вкладки окна FastTools — текстура 64×64 с mipmaps (7 КБ) вместо 1022×1011 без них (583 КБ): пакет стал меньше, а края иконки остаются гладкими при 16 pt. -- `Persistent()` сохраняет `context` исходного `SerializedObject`, поэтому `ExposedReference`, прочитанный или записанный через копию, разрешается в той же таблице (например, `PlayableDirector`), а не в значении по умолчанию в ассете. -- *Link to Existing* в контекстном меню `[SerializeReference]` теперь предлагает только экземпляры, которые принимает выбор типа поля с учётом базовых типов `[TypeSelector]`, в том числе заданных ссылкой на член; раньше он предлагал любой экземпляр, совместимый с объявленным типом поля. -- Generic-класс, выбранный в селекторе типов `[SerializeReference]`, теперь подходит под все типы `[TypeSelector]`: закрытый тип вне атрибута, например `Modifier` при `[TypeSelector(typeof(IModifier))]`, показывает ошибку. Раньше такой тип сохранялся, хотя атрибут его не допускает. -- Селектор типов выводит аргументы generic-типа из всех типов `[TypeSelector]`: если они задают все аргументы, как `[TypeSelector(typeof(IModifier))]` задаёт для `Modifier` тип `Modifier`, выбранный generic закрывается сразу. Раньше селектор смотрел только на тип поля `[SerializeReference]`, а в остальных случаях — на первый тип `[TypeSelector]`. -- На странице аргумента generic в селекторе типов `[SerializeReference]` вложенный generic проверяется как любой другой аргумент: класс без `[Serializable]` или generic-структура .NET вроде `Nullable` либо `KeyValuePair<,>`, значения которых Unity молча теряет, больше не предлагаются. Вложенным аргументом теперь может быть собственная generic-структура с `[Serializable]`, например `Container>`. -- Селектор типов `[SerializeReference]` больше не предлагает и не принимает как аргумент generic .NET-типы с `[Serializable]`, значения которых Unity молча теряет: `DateTime`, `TimeSpan`, `Guid`, `Decimal`, `Dictionary<,>`, `HashSet`, `Queue`, `Stack`, `LinkedList`, `Tuple<…>`, `object` и `IntPtr`. Из типов .NET Unity сериализует только примитивы, `string`, перечисления, `T[]` и `List`, поэтому они по-прежнему подходят; многомерный и ступенчатый массив, `List>` и коллекция с элементом, который Unity теряет, тоже отклоняются. Собственные типы с `[Serializable]` это не затрагивает. -- `SerializeReferenceEditorGUI.CreateField` и `DrawFieldLayout` теперь добавляют к `baseTypes` ограничения `[TypeSelector]` поля, как это уже делал `CreateList`. Раньше окно выбора предлагало все типы, подходящие объявленному типу поля, а `PropertyField` предлагает только выбранные. `CreateField` читает ограничение один раз, при создании поля. -- *Find Usages* в контекстном меню `[SerializeReference]` теперь находит использования именно того типа, что лежит в поле (с учётом пространства имён и сборки); раньше в результаты попадало любое хранимое имя класса, содержащее его имя, например `PistolMk2` или `Pistol` из другого пространства имён. Запрос `sr:`, набранный вручную, по-прежнему ищет по подстроке имени класса. -- *Find Usages of …* и *Link to Existing* в контекстном меню `[SerializeReference]` называют generic-тип так же, как выбор типа: `Modifier` или имя из `[TypeSelectorDisplay]`; раньше там было ``Modifier`1``. Символ `/` в отображаемом имени больше не открывает подменю. -- В стандартном UI Toolkit Inspector **+** пустого списка `[TypeSelector]` `[SerializeReference]` теперь открывает выбор типа; раньше он добавлял элемент ``, а выбор типа появлялся, только когда в списке уже был элемент. -- Уведомление о поломке ссылок и настройка детектора поломок указывают на Project References, а не на старое имя вкладки — Repair. -- Таблица `EnumValues` в массиве или списке подписана `Element 0`, `Element 1` и так далее, как другие элементы массива; раньше в заголовке стояло полное имя её enum-типа, потому что Unity называет элемент по его первому строковому полю. Длинный заголовок обрезается многоточием внутри карточки, а не вылезает за её границу, и в UI Toolkit, и в IMGUI Inspector. - -## [1.0.0-rc.8] — 2026-09-06 - -Первый релиз. Unity **6000.0**, сборки `Aspid.FastTools` / `Aspid.FastTools.Editor`, предсобранные Roslyn-DLL `Aspid.FastTools.Generators` / `Aspid.FastTools.Analyzers`. Все инспекторные возможности работают и в IMGUI, и в UI Toolkit. - -### Добавлено - -#### Serializable Type System - -- `SerializableType` / `SerializableType` — `[Serializable]`-обёртка над `System.Type`, ленивое разрешение, неявное приведение к `Type`, конструктор с `Type`, `AssemblyQualifiedName`. -- `SerializableMonoScript` / `SerializableMonoScript` — то же, но через ассет скрипта, поэтому переименование и перенос класса ничего не ломают; плеер сериализует одно имя. -- `SerializableTypeBase` и `ISerializableType` для полиморфной работы с любой обёрткой. -- `[TypeSelector]` — иерархический пикер типов на полях `string`, `SerializableType` / `SerializableMonoScript` и `[SerializeReference]`, а также на массивах и списках из них. Ограничения базовыми типами, `Allow` (`TypeAllow`), `Required`, ссылки на члены в строковых аргументах (`Type`, `string`, `SerializableType`, массивы из них, разрешаются вживую). -- `[TypeSelectorDisplay]` — `Name`, `Group`, `Tooltip`, `Icon`, `Hidden` для строки типа в пикере. -- `ComponentTypeSelector` — заменяет соседний `Component` на месте через дропдаун типов. -- `TypeSelectorWindow` с публичным API `Show(...)`: дерево пространств имён, поиск, навигация с клавиатуры, Favorites и Recent, `TypeSelectorFilter` (`Predicate`, `AdditionalTypes`, `HideNoneOption`). -- UI Toolkit-элементы `TypeField` / `InspectorTypeField`, на которых построены drawer'ы. - -#### SerializeReference Selector - -- Дропдаун типов на полях `[SerializeReference]`, включая вложенные ссылки (до 8 уровней); кастомные drawer'ы и `[Header]` / `[Space]` / `[Tooltip]` учитываются. -- Открытые generic-реализации: аргументы выводятся из аргументов типа поля и его интерфейсов, иначе собираются на второй странице пикера. -- Перенос данных при смене типа, Copy / Paste, мультиредактирование, развязывание дубликатов. -- Уведомления об общих ссылках с **Make unique**, цветными группами и переходом к участникам. -- Назначение перетаскиванием `MonoScript`, именованные шаблоны, **Link to Existing**, `+` списка через пикер, **Create New Script…**, **Find Usages**. - -#### Починка потерянных ссылок - -- Встроенный **Fix** на потерянном типе с сохранением данных; работает для сохранённых ассетов, Prefab Mode и объектов сцены. -- **Smart Fix** ранжирует вероятную замену (`[MovedFrom]`, то же имя в другом месте, регистр, совпадение формы полей). -- Переименования `[MovedFrom]` показываются как ожидающие миграции с **Migrate all** в один клик и не считаются нарушениями. -- Уведомление о поломке после переименования / удаления скрипта или реимпорта; защита удаления скриптов, используемых как managed reference; предпросмотр YAML-diff перед каждой массовой перезаписью. - -#### Рабочее окно (`Tools → Aspid 🐍 → FastTools`) - -- **Welcome** — примеры с отметками установки; открывается автоматически один раз на версию пакета. -- **Asset References** — весь граф `[SerializeReference]` ассета из YAML с предупреждающей полосой на отсутствующих типах и бейджами `SHARED`, встроенным Fix, Clear для осиротевших записей, Open Source Prefab. -- **Project References** — `Scan Project` по `Assets/`, **Fix all** на тип с Undo, Smart Fix, Migrate all, Required violations. -- **Settings** — все настройки пакета с полосками области (общая / пользовательская) и сбросом по областям. -- Навигация с клавиатуры, легенды, контекстные меню строк на каждой вкладке. -- Проектный индекс использований, провайдер Quick Search `sr:`. -- Build / CI gate: `IPreprocessBuildWithReport` плюс headless `SerializeReferenceCiGate.RunCheck` с `-srGateReport`, `-srGateRequired`, `-srGateWarnOnly`, `-srGateFail`; строгость `Off` / `Warn` / `Fail` и исключённые папки в коммитимом `ProjectSettings/SerializeReferenceSharedSettings.asset`. - -#### Настройки - -- **Project Settings → Aspid.FastTools → SerializeReference** — авторазвязывание, обнаружение поломок, строгость gate, исключённые папки. -- **Preferences → Aspid.FastTools** — зеркало вкладки Settings: References, Type Selector (Favorites, ёмкость Recent), Welcome, тема. - -#### Диагностики анализатора - -- `AFT0001` (ошибка) — `[TypeSelector]` на неподдерживаемом поле. -- `AFT0002` (предупреждение) — `Allow` на managed reference игнорируется. -- `AFT0003` (предупреждение) — базовый тип не имеет общих конкретных типов с полем. -- `AFT0004` (ошибка) — `[SerializeReference]` на типе `UnityEngine.Object`. -- `AFT0005` (предупреждение) — ни один конкретный сериализуемый тип не удовлетворяет ограничениям. -- `AFT0006` (ошибка) — строковый аргумент не является ни членом, ни именем типа. -- `AFT0007` (ошибка) — указанный член не может задавать базовые типы. -- `AFT0008` (предупреждение) — строка-не-идентификатор не является корректным именем типа. - -#### ProfilerMarkers - -- `this.Marker()` — `ProfilerMarker`, уникальный для места вызова. -- `ProfilerMarkersGenerator` — создаёт по полю маркера на место вызова; поддерживает лямбды, локальные функции, `.WithName(...)` и имена `$"..."`; вырезается без `ENABLE_PROFILER`. - -#### EnumValues - -- `EnumValues` — сериализуемый словарь с ключом-enum, значением по умолчанию и поддержкой `[Flags]`. -- `EnumValues` — типизированный вариант, поиск без боксинга, структурный перечислитель. -- Drawer'ы с редактированием на месте и **Populate Missing Enum Members**. - -#### Fluent-расширения VisualElement - -- Fluent API на `VisualElement`: раскладка, стиль, границы, цвета, переходы, колбэки, USS, управление детьми с вариантами `*If`, пресеты стилей. -- Помощники для `Button`, `BaseField` (`SetLabel` для 29 типов), `Focusable`, `Foldout`, `HelpBox`, `Image`, `IMGUIContainer`, `IMixedValueSupport`, `INotifyValueChanged`, `IStyle`, `ICustomStyle`, list view, `Manipulators`, `ProgressBar`, `Slider`, `TextElement`. -- Редактор: `BindTo` / `UnbindFrom`, `BindPropertyTo`, `SetBindingPath`, `SetLabel` для `PropertyField`, `AddOpenScriptCommand`, `GetOwnerWindow`. -- `Aspid.FastTools.VisualElements.Math` — `SetValue` / `ValueChanged` для типов `Unity.Mathematics`, компилируется только с `com.unity.mathematics`. - -#### Расширения SerializedProperty - -- Типизированные сеттеры `Set*` / `Set*AndApply`, `Update`, `ApplyModifiedProperties`, `Persistent`, помощники путей, `GetPropertyType` / `GetFieldInfo` / `GetDeclaringInstance`. - -#### Редакторские помощники - -- `GetScriptName()` / `GetScriptNameWithIndex()`. -- Команда открытия скрипта, понимающая интерфейсы в файлах с другим именем и вложенные типы. - -#### Примеры - -- **Types**, **SerializeReferences**, **EnumValues**, **ProfilerMarkers**, **EditorTools** — по одной работающей сцене (или окну) с `README.md`. - -#### Документация и инструменты - -- Документация на английском и русском в `Documentation/`, публикуется на https://vpdpersonal.github.io/Aspid.FastTools/. -- Плагин `aspid-fasttools` для Claude Code в [Aspid.Claude.Plugins](https://github.com/VPDPersonal/Aspid.Claude.Plugins). -- `upm` / `upm/` для стабильных релизов, `upm-preview` для предрелизов. До первого стабильного релиза в ветке `upm` остаётся старый пакет `com.aspid.fasttools` (`1.0.0-rc.2`). -- EditMode-тесты для YAML-редактора и сканирования CI gate. - -[1.0.0-rc.9]: https://github.com/VPDPersonal/Aspid.FastTools/releases/tag/v1.0.0-rc.9 -[1.0.0-rc.8]: https://github.com/VPDPersonal/Aspid.FastTools/releases/tag/v1.0.0-rc.8 +- `SerializableType` и `SerializableMonoScript` хранят `System.Type` в компоненте или ассете; `[TypeSelector]` выбирает его в Inspector из совместимых типов. +- SerializeReference Selector выбирает класс поля `[SerializeReference]` и переносит совместимые данные при смене класса. +- `ComponentTypeSelector` меняет добавленный компонент на производный класс без потери общих значений полей. +- Project References находит потерянные ссылки `[SerializeReference]` и имена `SerializableType` по всему проекту и чинит их группами; проверки при сборке и в CI ловят новые. +- `EnumValues` сопоставляет значениям enum данные, которые редактируются в Inspector, включая флаги. +- `this.Marker()` открывает маркер профайлера с именем из типа, метода и строки вызова; его строит source generator. +- Анализаторы `AFT0001`–`AFT0014` сообщают в IDE о неверном использовании `[TypeSelector]` и `this.Marker()`. +- VisualElement Extensions задают свойства, стили и события элемента цепочкой. +- SerializedProperty Extensions обновляют объект, записывают значение и применяют изменение одной цепочкой. +- Editor Helpers: `GetDisplayName()` и `GetDisplayNameWithIndex()` дают объектам и компонентам читаемые имена. +- Окно FastTools (**Tools → Aspid 🐍 → FastTools**) с вкладками Welcome, Asset References, Project References и Settings и темы для окон FastTools. +- Сэмплы для каждой функции и Agent Skills, которые учат агента писать код с FastTools. + +[1.0.0]: https://github.com/VPDPersonal/Aspid.FastTools/releases/tag/v1.0.0 diff --git a/Website/i18n/ru/docusaurus-plugin-content-docs/current/13-agent-skills.md b/Website/i18n/ru/docusaurus-plugin-content-docs/current/13-agent-skills.md index c02767da5..91c80d8b4 100644 --- a/Website/i18n/ru/docusaurus-plugin-content-docs/current/13-agent-skills.md +++ b/Website/i18n/ru/docusaurus-plugin-content-docs/current/13-agent-skills.md @@ -13,13 +13,13 @@ ```text prompt Установи скиллы из репозитория VPDPersonal/Aspid.FastTools в текущий проект, -не глобально. Выполни npx skills add VPDPersonal/Aspid.FastTools#skills-preview. +не глобально. Выполни npx skills add VPDPersonal/Aspid.FastTools#skills. ``` Или выполните в корне проекта: ```bash -npx skills add VPDPersonal/Aspid.FastTools#skills-preview +npx skills add VPDPersonal/Aspid.FastTools#skills ``` В установщике выберите область **Project**: глобальная установка действует во всех Unity-проектах, какая бы версия пакета в них ни стояла. @@ -39,7 +39,7 @@ npx skills add VPDPersonal/Aspid.FastTools#skills-preview Обновляйте пакет одновременно со скиллами: скиллы новее пакета могут описывать API, которого в нём нет, и тогда агент пишет код, который не собирается. Чтобы скиллы оставались на версии вашего пакета, поставьте их с её тега — `npx skills update` его не двигает: ```bash -npx skills add VPDPersonal/Aspid.FastTools#skills-preview/ +npx skills add VPDPersonal/Aspid.FastTools#skills/ ``` Тег лежит на канале вашего пакета: `skills/` для стабильного релиза, `skills-preview/` для preview. diff --git a/Website/i18n/ru/docusaurus-plugin-content-docs/current/README.md b/Website/i18n/ru/docusaurus-plugin-content-docs/current/README.md index 236ba8b7c..81b9ce84f 100644 --- a/Website/i18n/ru/docusaurus-plugin-content-docs/current/README.md +++ b/Website/i18n/ru/docusaurus-plugin-content-docs/current/README.md @@ -4,7 +4,7 @@ [![Unity 6000.0.53f1+](../../../../docs/Images/status-badge-unity.svg)](https://assetstore.unity.com/packages/package/2333465) -[![Preview 1.0.0-rc.9](../../../../docs/Images/status-badge-preview.svg)](https://github.com/VPDPersonal/Aspid.FastTools/releases/tag/v1.0.0-rc.9) +[![Release 1.0.0](../../../../docs/Images/status-badge-preview.svg)](https://github.com/VPDPersonal/Aspid.FastTools/releases/tag/v1.0.0) [![MIT License](../../../../docs/Images/status-badge-license.svg)](https://github.com/VPDPersonal/Aspid.FastTools/blob/main/LICENSE) Aspid.FastTools — пакет для Unity, который убирает рутину из сериализации, профилирования и редакторского кода. @@ -16,10 +16,10 @@ Aspid.FastTools — пакет для Unity, который убирает ру В **Window → Package Manager** выберите **+ → Install package from git URL…**, вставьте этот URL и нажмите **Install**: ```text -https://github.com/VPDPersonal/Aspid.FastTools.git#upm-preview +https://github.com/VPDPersonal/Aspid.FastTools.git#upm ``` -URL указывает на последнюю preview-версию; кнопка **Update** в Package Manager установит следующую. +URL указывает на последнюю версию; кнопка **Update** в Package Manager установит следующую. Нужна Unity 6000.0.53f1 или новее. Если пакет у вас из Asset Store, git URL не нужен: установите его из **My Assets** в Package Manager.