3.3.0
·
170 commits
to refs/heads/main
since this release
Changelog
Added
- Failed Tests Exporter: New editor utility that hooks into the Unity Test Runner to automatically capture test failures and export them to timestamped text files
- Automatically records test name, failure message, and stack trace for each failed test
- Configurable output directory with a visual folder picker — defaults to the project root if not set
- Path validation on every use: falls back to the project root if the configured directory is missing, invalid, or outside the project
- Menu items under
Tools > Wallstop Studios > Unity Helpersto export or clear captured failures - Disabled by default — enable via
Project Settings > Wallstop Studios > Unity Helpers
Fixed
- Editor asset import-loop pressure from unchanged metadata saves:
ScriptableObjectSingletonMetadataandAttributeMetadataCachenow skipSetDirty/SaveAssetswork when regenerated metadata is unchanged. This prevents initialize-on-load and explicit singleton ensure passes from repeatedly re-saving identical assets during Unity test runs or editor refreshes, reducing the chance of Unity's "infinite import loop" detector tripping on native runs. AssetPostprocessorDeferraldedup regressing structurally-equal-but-distinct drains:AssetPostprocessorDeferral.Schedulenow dedups pending drains viaReferenceEqualsinstead ofList<Action>.Contains(which invokesDelegate.Equals). The prior structural-equality behavior silently coalesced two distinct delegates that shared the sameMethod+Target-- common when a local helper returns a lambda that captures only outer-method variables -- so a self-rescheduling drain could be dropped entirely. Matches the documented intent in the AssetPostprocessor safety skill and is pinned by the newScheduleStructurallyEqualButDistinctDelegatesAreNotDeduplicatedregression test- WButton conflict warnings hidden in collapsed foldouts: Fixed group conflict warnings (placement, priority, and draw order) not rendering when foldout groups are collapsed. Conflict warnings now render in the group header area regardless of foldout expansion state, and warning cache population is validated across collapsed, expanded, and always-open foldout behavior.
- Spurious "SendMessage cannot be called..." warnings from asset processors: Eliminated spurious "SendMessage cannot be called during Awake, CheckConsistency, or OnValidate" warnings from
DetectAssetChangeProcessorand related editor processors (LlmArtifactCleaner,SpriteLabelProcessor) by deferring callback invocation out of Unity's asset-import phase via a sharedAssetPostprocessorDeferralhelper backed byEditorApplication.delayCall. The prior synchronous path calledAssetDatabase.LoadAllAssetsAtPath/GetComponentsInChildren/ user callbacks during the import phase, which triggered Unity's internal sprite/renderer lifecycle relays and produced per-import warning storms. A new opt-out setting (Project Settings > Wallstop Studios > Unity Helpers > Detect Asset Changes, option Defer Post-process Callbacks, default on) restores the old synchronous behavior for users who require it. (#234) - Pool auto-purge throttle dropping real purges: Fixed
WallstopGenericPool<T>.PurgeInternalCoreletting the 1-secondMinAutoPurgeIntervalSecondsthrottle blockMaxPoolSizeenforcement. A Rent/Return that advanced_lastAutoPurgeTimeon a healthy-pool scan would block a subsequent same-tick call that pushed the pool pastMaxPoolSize, silently skipping theCapacityExceededpurge and dropping the matchingOnPurgenotification. The throttle now has two orthogonal rules: (1) when the pool is observably overMaxPoolSize, the throttle is bypassed entirely so a burst of returns cannot accumulate beyond capacity within a single clock tick; (2) otherwise the throttle still rate-limits scans (preserving the O(1) amortized fast path for healthy pools under contention). The multithreaded variant also guards the timestamp advance with CAS max-semantics so concurrent out-of-order writes cannot regress the throttle clock. Applies to both the multithreaded and SINGLE_THREADED pool variants - Pool performance regression from O(n) usage tracking: Fixed
RollingHighWaterMark(used by pool purge system) performing O(n) operations on every pool rent/return, causing 100x slowdowns under sustained load. ReplacedList<Sample>withCyclicBuffer<Sample>for O(1) add/remove, added incremental running sum for O(1) average computation, and added a monotonic deque for O(1) amortized peak tracking. Previously, 100K rent/return cycles took 20+ seconds; now completes within 200ms budget - TexturePlatformOverrideEntryDrawer render-phase mutations: Fixed
OnGUIwriting toSerializedPropertyvalues every frame withoutBeginChangeCheck/EndChangeCheckguards. Direct assignments likeapply.boolValue = EditorGUI.ToggleLeft(...)andnameProp.stringValue = EditorGUI.TextField(...)dirtied theSerializedObjecton every repaint, corrupting undo history. Also removed a redundant render-phase writeback of the computed display label to the platform name property - TexturePlatformOverrideEntryDrawer GenericMenu undo and Custom handling: Fixed
GenericMenucallback not callingUndo.RecordObjectsbefore mutation and not handling the "Custom" menu option. Selecting "Custom" from the dropdown now correctly sets the platform name tostring.Empty(triggering custom mode), and all selections are undoable - SourceFolderEntryDrawer render-phase mutation: Fixed
EnumFlagsFieldfor selection mode writing tomodeProp.intValueevery frame without aBeginChangeCheck/EndChangeCheckguard - AttributeMetadataCache generator path mismatch: Fixed
AttributeMetadataCacheGenerator.GetOrCreateCache()using hardcoded asset paths that did not match the[ScriptableSingletonPath("Wallstop Studios/Unity Helpers")]attribute onAttributeMetadataCache. The generator was creating and loading the cache asset fromAssets/Resources/Wallstop Studios/instead of the correctAssets/Resources/Wallstop Studios/Unity Helpers/path, causing cache generation to silently fail when the singleton was already loaded at the correct path - IntDropDown invalid value handling: Fixed
IntDropDownDrawerto properly handle property values that fall outside the configured options. Invalid values (values not in the options array) are now preserved without modification during render and clearly displayed with an "(Invalid)" suffix. Previously, invalid values were displayed as-is without any visual indication. The UI ToolkitIntDropDownSelector.GetDefaultValue()now returns the first option instead of 0 - Linux dropdown rendering phantom rows: Replaced all
EditorGUI.Popupusage withGenericMenu-based dropdowns to eliminate phantom empty rows when selected index is -1 on Linux. Affected drawers:WValueDropDownDrawer,IntDropDownDrawer,StringInListDrawer,TexturePlatformOverrideEntryDrawer(standard variants), andWValueDropDownOdinDrawer,IntDropDownOdinDrawer,StringInListOdinDrawer(Odin Inspector variants). Odin drawers now always useGenericMenuregardless of the page limit setting, sinceGenericMenuhandles all list sizes correctly without the rendering issues that required the threshold (#209) - Multi-object editing for WValueDropDown: Added typed
SerializedPropertysetters for Unity-native types (Vector2,Vector3,Vector4,Color,Rect,Bounds,Quaternion,AnimationCurve,Hash128, and theirIntvariants) inWValueDropDownDrawer.ApplyOptionto avoid the reflection fallback for known property types. The generic reflection path now iterates over allserializedObject.targetObjectsfor proper multi-object editing support instead of only updating the first selected object - SerializableSet undo not working for add, clear, sort, and commit operations: Fixed
TryClearSet,TryAddNewElement,TryCommitPendingEntry,AppendNullPlaceholderEntry, andTrySortElementsinSerializableSetPropertyDrawernot callingUndo.FlushUndoRecordObjects()after direct object mutation. These methods usedUndo.RecordObjectsto snapshot pre-change state but never finalized the undo record, causingUndo.PerformUndo()to silently do nothing - GUIContent GC pressure in drawer OnGUI: Fixed per-frame
GUIContentallocations inIntDropDownDrawer.DrawGenericMenuDropDownandPoolTypeConfigurationDrawer.OnGUIthat created avoidable garbage collection pressure in the Inspector. Both drawers now reuse staticGUIContentinstances (consistent withWValueDropDownDrawerandStringInListDrawerwhich already followed this pattern)
Pull Requests
- 3.3.0 Release (#252) Eli Pinkerton (@wallstop)
- Show WButton group conflict warnings when foldouts are collapsed (#251) @copilot-swe-agent[bot]
- Fix release-drafter auto-tag to use normalized semver version instead of hash (#250) @copilot-swe-agent[bot]
- Fix semantic sorting for benchmark Speed/Quality columns on GitHub Pages (#249) @copilot-swe-agent[bot]
- Fix SendMessage Warnings (#248) Eli Pinkerton (@wallstop)
- Various Bug Fixes (Undo, Pool Auto-Purge) (#247) Eli Pinkerton (@wallstop)
- Enable UPM inline changelog rendering, fix meta-lint CI regression, and harden changelog packaging contract test (#241) @copilot-swe-agent[bot]
- Add explicit unsigned UPM signature metadata and enforce it via regression test (#240) @copilot-swe-agent[bot]
- Fix devcontainer publish failures on arm64 and harden regression contract checks (#239) @copilot-swe-agent[bot]
- Group Dependabot updates into weekly per-ecosystem grouped PRs (#236) Eli Pinkerton (@wallstop)
- fix: pool performance regression + purge system improvements + devcontainer Unity CI (#227) Eli Pinkerton (@wallstop)
- Remove Stale Issues Bot (#223) @copilot-swe-agent[bot]
- Second pass attempt at fixing WValueDropDown + Various Bug Fixes (#216) Eli Pinkerton (@wallstop)
Contributors
@Copilot, Dependabot (@dependabot)[bot], Eli Pinkerton (@wallstop), copilot-swe-agent[bot] and dependabot[bot]