Changelog
All notable changes to Aspid.FastTools will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
Added
RemoveChildrenandRemoveChildrenIfremove several children in one call and take the sameparams,IEnumerable,List,SpanandReadOnlySpanoverloads asAddChildren.ToggleButtonGroupgets typedSetValue,AddValueChanged,RemoveValueChangedandSetLabeloverloads forToggleButtonGroupState, so calls such asAddValueChanged(evt => …)need no type arguments.RectIntFieldgets a typedSetLabel, soSetLabel("Area")needs no type arguments, as onRectField.SetRootItemsSelffills aTreeVieworMultiColumnTreeViewin a chain:tree.SetAutoExpand(true).SetRootItemsSelf(items).TextField,IntegerField,LongField,UnsignedIntegerField,UnsignedLongField,FloatField,DoubleFieldandHash128Fieldget chainable setters:SetMaxLength,SetMaskChar,SetDelayed,SetReadOnly,SetPassword,SetPlaceholder,SetHidePlaceholderOnFocus,SetKeyboardType,SetAutoCorrection,SetHideMobileInput,SetHideSoftKeyboard, and for text selectionSetSelectable,SetSelectAllOnFocus,SetSelectAllOnMouseUp,SetDoubleClickSelectsWord,SetTripleClickSelectsLine,SetCursorIndex,SetSelectIndex,AddOnCursorIndexChange/RemoveOnCursorIndexChange,AddOnSelectIndexChange/RemoveOnSelectIndexChange. TheITextEditionandITextSelectionsetters do not reach these fields. Other value types useTextInputBaseFieldExtensionsandTextInputBaseFieldTextSelectionExtensions.- Added
AndApplyWithoutUndocounterparts for everySerializedPropertysetter with immediate application, includingSetValueoverloads, object references, enums, and array size helpers. - Analyzer
AFT0009(warning) — two[TypeSelector]base types have no type in common, so the selector is empty. - Analyzer
AFT0010(warning) — athis.Marker()call opens no profiler marker because the generator cannot support its type: the type isprivateorprotected(or nested in such a type), or it reuses a type parameter name of a containing type. - Analyzer
AFT0011(warning) — the scope ofthis.Marker()is discarded (this.Marker();as a statement,_ = this.Marker();, a local nothing reads), so the sample it begins never ends. - 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 trailingorigincolumn,overridefor these rows.
Changed
- The Agent Skills for this package moved from the
aspid-fasttoolsClaude Code plugin in Aspid.Claude.Plugins into this repository (skills/). Install them into Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI or another agent withnpx skills add VPDPersonal/Aspid.FastTools; the plugin is no longer published. - Renamed
GetScriptName()toGetDisplayName()andGetScriptNameWithIndex()toGetDisplayNameWithIndex(); update existing calls to the new names. Both methods now returnstring.Emptyfor 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;AddStyleSheets/RemoveStyleSheets→AddStyleSheet/RemoveStyleSheet,AddStyleSheetsFromResource/RemoveStyleSheetsFromResource→AddStyleSheetFromResources/RemoveStyleSheetFromResources;SetImageFromResource,SetSpriteFromResource,SetVectorImageFromResource,SetBackgroundImageFromResource→…FromResources;MarkDirtyLayout→MarkDirtyLayoutSelf:IMGUIContainer.MarkDirtyLayout()hid the old extension, so the call returnedvoid; the new name chains.
- Renamed the extension classes
BaseFieldExtensionsSetLabel<Type>toBaseField<Type>Extensions(BaseFieldExtensionsSetLabelInt→BaseFieldIntExtensions) andProgressBarExtensionstoAbstractProgressBarExtensions. Extension-method calls are unaffected; only calls through the class name change. SetShowMixedValueno longer defaults its argument totrue; pass the value explicitly.SetDirection,SetFill,SetInverted,SetPageSizeandSetShowInputFieldnow return the slider's own type (Slider,SliderInt) instead ofBaseSlider<TValue>, so a chain keeps the slider's members. They acceptBaseSlider<float>andBaseSlider<int>; the openBaseSlider<TValue>overloads are gone. TheBaseSlider<int>overloads live in the newSliderIntExtensionsclass: extension-method calls are unaffected, but a call throughSliderExtensions.on aSliderIntmust switch toSliderIntExtensions..- The parameterless constructors of
SerializableType/SerializableType<T>are no longer public: create a wrapper withnew SerializableType(type)ornew SerializableType<T>(type)(nullgives an empty one).SerializableMonoScript/SerializableMonoScript<T>have no public constructors: declare them as serialized fields and pick the script in the Inspector. [TypeSelector]on a[SerializeReference]field now offers only types assignable to every attribute type — the rulestringandSerializableTypefields already follow; it used to offer types matching any one of them. The same applies tobaseTypesofSerializeReferenceEditorGUI.CreateField,CreateListandDrawFieldLayout. A list of alternatives such astypeof(Pistol), typeof(Rifle)now leaves the selector empty and triggersAFT0009: give the allowed classes a common interface or base class and pass that instead.AFT0005now checks all attribute types together.- 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 aSerializedObjecton every repaint. - In the Inspector of a runtime object, the type picker no longer offers types from editor-only assemblies (
UnityEditor, Editor asmdefs andEditorfolders): a player cannot resolve them, so the value silently becamenullor a missing reference in a build. Fields of editor windows and other editor-only objects still offer every type. - The unconstrained type picker (
SerializableTypewithoutT,[TypeSelector]on a string,TypeField) reuses its type list between openings instead of rebuilding it from every loaded type each time. SerializeReferenceIMGUIList.Drawnow throwsArgumentNullExceptionfor anullproperty andArgumentExceptionfor a property that is not a list of managed references, likeSerializeReferenceEditorGUI.CreateList; it used to draw nothing. Anulllabel now shows the property's display name; passGUIContent.noneto hide it.- The generated
this.Marker()code now declares its marker fields only underENABLE_PROFILER, like theMarker()body that reads them: builds without the profiler no longer create every marker in a static constructor. ProfilerMarkerExtensionsForGenerator.Marker(this object)is nowMarker<T>(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. Athis.Marker()call inside an expression tree no longer compiles (CS0854), and a method group now needsFunc<int, AutoScope>.AFT0010now reports everythis.Marker()call that opens no marker, not only unsupported types: a receiver of another type (other.Marker(), calls in static classes), a default interface method, an explicit argument (this.Marker(5)) or type argument,this?.Marker(), the static call form, a method group and a call inside an expression tree. The generator no longer emits dead markers for such calls.- A generic class names nested type arguments the way C# writes them (
Foo<List<Int32>>.Run (line),Foo<Outer<Int32>.Inner>.Run (line)instead ofFoo<List`1>,Foo<Inner>). A generic struct gets one marker per call site for all its closed types, namedJob<T>.Execute (line), because Burst cannot run the per-type label. - The generated
Marker()dispatches on the line with aswitch, so its cost no longer grows with the number of call sites in a type. - The generated
Marker()takes a struct byin, sothis.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 Sample Themes window hooks the editor update loop, camera rendering and scene saving only while a Light or Dark preview is on; in the default Authored mode it adds no editor callbacks.
Aspid.FastTools.VisualElements.Mathis no longer compiled as an empty assembly in projects withoutcom.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 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 override still layers on top of either palette. [TypeSelector]on an array orList<T>field now applies to the collection itself (applyToCollection): its drawer draws the list and a picker for each element.PropertyFieldandEditorGUILayout.PropertyFieldon such a list now get the picker-backed + in UI Toolkit and IMGUI, and aPropertyFieldon a single element of it no longer shows the picker.SerializeReferenceIMGUIList.DrawandSerializeReferenceEditorGUI.CreateListadd the constraints of a[TypeSelector]on the list field tobaseTypes. Managed-reference lists drawn by the package now honor[NonReorderable].
Removed
- Removed
SetExposedReferenceAndApply()fromSerializedPropertyextensions; callSetExposedReference()instead. Without anIExposedPropertyTablecontext, Unity'sexposedReferenceValuesetter 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 theMonoScriptasset; no public accessor for the asset remains. The type is still available throughTypeor the implicit conversion toType. - Removed
AddMakeItem/RemoveMakeItemofListViewandTreeView, andAddMakeHeader/AddMakeFooter/AddMakeNoneElementofBaseListViewwith theirRemove*pairs; the view keeps one factory, so callSetMakeItem,SetMakeHeader,SetMakeFooterorSetMakeNoneElement. - Removed the runtime
Aspid.FastTools.StringExtensions.ToKebabCaseandAspid.FastTools.TypeExtensions.GetMembersInfosIncludingBaseClassesfrom the public API, without a replacement.
Fixed
- The
SHAREDbadge 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.
GetDisplayName()andGetDisplayNameWithIndex()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 analyzersAFT0006–AFT0008already 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. AFT0007no longer fails compilation on aType?member under#nullable enable, and it now reports a property without a getter, which the Inspector cannot read.AFT0004now also reports aUnityEngine.Object?field.AFT0005no longer warns about a generic field or base type (IState<Enemy>,Base<int>,typeof(IFoo<int>)) that has a closed or open generic implementation, or about an implementation throughout/invariance, which also no longer triggersAFT0003. Neither warns about a field of a type parameter (TinSlot<T>). An unboundtypeof(Base<>)no longer triggersAFT0003orAFT0005when an open generic implementation such asImpl<T> : Base<T>can fill the field.[field: TypeSelector]and[field: SerializeReference, TypeSelector]on an auto-property are now checked byAFT0001–AFT0009, andAFT0003now also coversSerializableType<T>andSerializableMonoScript<T>fields.- 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.
- 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.
- 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 withoutuseForChildren, 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. - The per-user settings reset no longer lists the removed "Dropdown without [TypeSelector]" option in its tooltip and confirmation dialog.
ComponentTypeSelectornow 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 itsOnValidatefinds them. It used to leave the object without the required components or with duplicates.- Create New Script… on a
[SerializeReference]field suggestsNewInteractableforIInteractable(wasNewnteractable) andNewEffectforIEffect<T>or a generic base class (was the invalidNewEffect`1, rejected on accept). - 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.
- Excluded scan folders accepts only
Assetsand folders under it, the only ones project scans walk; a folder underPackages/or elsewhere was saved but excluded nothing. - Type picker search no longer matches the assembly part of a type name: short queries such as
Key,Token,verornullused 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.
- For a missing type the type picker no longer highlights
<None>, so Enter right after opening does not erase the stored name. - In a UI Toolkit Inspector, choosing
<None>now clears aSerializableMonoScriptwhose type is missing; the field used to keep showing<Missing …>. - + 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 throwInvalidOperationExceptionand add nothing. - + of an array whose elements contain a
[TypeSelector][SerializeReference]field (such asWeaponSlot[]in the sample) 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
EnumValuesInspector no longer rewrites keys while drawing: a row whose key the enum cannot parse (after switchingEnumValues<TValue>to another enum, or renaming or deleting a member) shows its key as, for example,<Missing Frozen>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<None>and is skipped with an error until you pick a member; it used to get the first member automatically. - Populate Missing Enum Members now works when the value is an array or a
List<T>; 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. - An
EnumValuesrow of a[Flags]enum based onlongorulong, or onuintwith 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. - In the UI Toolkit Inspector the key dropdown of an
EnumValuesrow now follows Undo, Revert and Paste, and the table header shows the label passed toPropertyFieldinstead of always the field name. - 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. - 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. - Fields drawn in a regular Inspector, UI Toolkit or IMGUI, now follow the light editor skin: the
EnumValuesdrawer 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.
- The Welcome tab of the FastTools window takes the theme override too; it kept the built-in palette.
- The theme override 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. - 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. - 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. - 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
<None>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<None>elements, the saved file doesn't say which one it was: the guard keeps the<None>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 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.
- 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.
- A
[SerializeReference]field of a prefab variant, nested prefab or scene instance whose type is missing now shows Missing type instead of an empty<None>; 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-srGateRequiredand the References windows. - 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 (
PistolandRifleinWeapons.cs) and nested types (Outer.Inner); it used to check only the class named after the file. Apartialtype counts only when no remaining script declares another part of it. - 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.
- A
[TypeSelector(Required = true)]array or list in a scene is no longer reported as unset by-srGateRequiredand 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.
- The required-field sweep of
-srGateRequiredand Scan Project now unloads the prefabs and assets it loaded, so its memory no longer grows with the size of the project. - Assign Required for a
SerializableMonoScriptfield 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<T>orSerializableMonoScriptfield 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,
SerializableMonoScriptnow 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 getsnullbefore its asset is saved again. SerializableTypeandSerializableMonoScriptnow cache a failed lookup as well: reading.Typeof a missing type no longer callsType.GetTypeevery time, and the cache resets when the stored name changes.- 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. - 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.
- 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.
this.Marker()inside aprivateorprotectednested 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, andAFT0010reports it — make the typeinternalorpublicto profile it.this.Marker()in a type nested in a generic type (Outer<T>.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 namedType.Indexer (line)andType.StaticCtor (line).this.Marker()in an event accessor is now named after the event, like a property accessor:Type.Changed (line)instead ofType.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<T>/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<T>andFoo<T1, T2>in one namespace no longer share one generated class in which only the first type got markers; the package's ownEnumValues<TEnum, TValue>markers now open.- A
this.Marker()call split over several lines or under a#linedirective 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
InternalsVisibleTonow gets markers of its own; its calls used to bind to the base type's overload and open nothing. WithName($"Br{{ace}}")givesBr{ace},WithNametext with U+2028, U+2029 or U+0085 compiles, and a user's ownWithNameextension no longer renames the marker.Persistent()no longer leaks theSerializedObjectit creates when the property path no longer exists on the targets; it disposes that object before returningnull.AddChildren,InsertChildrenand their…Ifvariants with anIEnumerableno longer throwInvalidOperationException("Collection was modified") when givenChildren()of another element:target.AddChildren(source.Children())moves every child.- Types sample: the
Enemy Typepicker no longer offers the abstractEnemy, which spawned empty capsules and an error per enemy; the rename step of the README now uses the IDE's Rename refactoring, soArmoredGruntkeeps compiling. - SerializeReferences sample: no more CS0414 warning on import, and deleting the Training Dummy in Play Mode no longer throws
MissingReferenceExceptionon 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.
- 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.
- Samples no longer import ten unused screenshots (about 1 MB) as textures.
Persistent()keeps thecontextof the sourceSerializedObject, so anExposedReferenceread or written through the copy resolves in the same table (for example aPlayableDirector) 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. - 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 asPistolMk2or aPistolfrom another namespace. A typedsr: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<Single>or its[TypeSelectorDisplay]name; they used to showModifier`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<None>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.
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<T>—[Serializable]wrapper overSystem.Type, lazy resolution, implicit conversion toType,Type-taking constructor,AssemblyQualifiedName.SerializableMonoScript/SerializableMonoScript<T>— the same, referenced through the script asset so renames and moves do not break it; the player serializes the name alone.SerializableTypeBaseandISerializableTypefor polymorphic access to any wrapper.[TypeSelector]— a hierarchical type picker onstring,SerializableType/SerializableMonoScriptand[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,Hiddenfor a type's row in the picker.ComponentTypeSelector— swaps a siblingComponentin place through a type dropdown.TypeSelectorWindowwith a publicShow(...)API: namespace tree, search, keyboard navigation, Favorites and Recent,TypeSelectorFilter(Predicate,AdditionalTypes,HideNoneOption).TypeField/InspectorTypeFieldUI 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
MonoScriptto 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 andSHAREDbadges, inline Fix, Clear for orphans, Open Source Prefab. - Project References —
Scan ProjectoverAssets/, 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:
IPreprocessBuildWithReportplus headlessSerializeReferenceCiGate.RunCheckwith-srGateReport,-srGateRequired,-srGateWarnOnly,-srGateFail; severityOff/Warn/Failand excluded folders in the committedProjectSettings/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) —Allowon a managed reference is ignored.AFT0003(warning) — base type shares no concrete type with the field.AFT0004(error) —[SerializeReference]on aUnityEngine.Objecttype.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()— aProfilerMarkerunique to the call site.ProfilerMarkersGenerator— emits one marker field per call site; supports lambdas, local functions,.WithName(...)and$"..."names; compiled out withoutENABLE_PROFILER.
EnumValues
EnumValues<TValue>— serializable enum-keyed dictionary with a default value and[Flags]support.EnumValues<TEnum, TValue>— 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*Ifvariants, style presets. - Helpers for
Button,BaseField<T>(SetLabelfor 29 types),Focusable,Foldout,HelpBox,Image,IMGUIContainer,IMixedValueSupport,INotifyValueChanged,IStyle,ICustomStyle, list views,Manipulators,ProgressBar,Slider,TextElement. - Editor:
BindTo/UnbindFrom,BindPropertyTo,SetBindingPath,SetLabelforPropertyField,AddOpenScriptCommand,GetOwnerWindow. Aspid.FastTools.VisualElements.Math—SetValue/ValueChangedforUnity.Mathematicstypes, compiled only withcom.unity.mathematics.
SerializedProperty extensions
- Typed
Set*/Set*AndApplysetters,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-fasttoolsClaude Code plugin in Aspid.Claude.Plugins.upm/upm/<version>for stable releases,upm-previewfor prereleases. Until the first stable release, theupmbranch still holds the oldercom.aspid.fasttoolspackage (1.0.0-rc.2).- EditMode tests for the YAML editor and the CI-gate scan.