Unity Helpers

repository·main·Indexed 41 days ago

https://github.com/ambiguous-interactive/unity-helpers

A utility library for Unity (v3.6.0) providing high-performance tools, inspector enhancements, and automation. Features include declarative attributes for inspector tooling (WGroup, WShowIf, WButton), a high-performance PRNG implementation, data-driven effects using ScriptableObjects, Unity-aware serialization, and O(log n) spatial queries. Includes a RandomQuality host for running statistical tests on IRandom implementations.

Tokens
241.7K
Snippets
540
Records
844
Agent score
48%

What's inside Unity Helpers

  1. Overview of Unity Helpers features

    main

    Unity Helpers is a collection of tested utilities designed to reduce boilerplate and improve performance in Unity development. Key capabilities include:

    • Inspector Tooling: Declarative attributes for grouping, buttons, conditional display, and toggle grids (similar to Odin Inspector).
    • High-Performance Randomness: A PRNG implementation that is 10-15x faster than Unity.Random in benchmarks.
    • Component Auto-wiring: Reduced boilerplate for component wiring using attributes.
    • Data-Driven Effects: A designer-friendly system for buffs/debuffs using ScriptableObjects.
    • Spatial Queries: O(log n) spatial queries for efficient searching.
    • Editor Automation: Over 30 tools to automate sprite and animation workflows.
    • Unity-Aware Serialization: Simplified serialization for Unity types.
  2. Overview of Unity Helpers Editor Tools

    main

    Unity Helpers provides over 30 batch editor tools designed to automate repetitive asset management tasks in Unity. These tools allow you to process folders of assets at once rather than one by one. Most tools are accessible via the Unity menu at Tools > Wallstop Studios > Unity Helpers.

    Key capabilities include:

    • Texture & Sprite Management: Batch cropping, resizing, and applying import settings.
    • Animation Workflow: Creating clips from naming conventions, splitting sprite sheets, and editing animation events.
    • Project Validation: Checking for broken prefabs, missing lifecycle overrides, and non-serialized fields.
    • Testing & Automation: Exporting failed test outputs and detecting asset changes.
  3. Overview of WUH### Analyzers

    main

    The WUH### analyzers are designed to report allocations or common 'footguns' in code that is syntactically correct and functional.

    Key Characteristics:

    • Severity: Always reported as a Warning.
    • Build Impact: They will never fail your build (unless your project is specifically configured to treat warnings as errors).
    • Default State: Most are enabled by default, except for WUH010, WUH013, and WUH018, which are opt-in because their patterns are frequently used correctly.

    | Id | Reports | Default | | | :--- | :--- | :--- | | WUH001 | A lookup factory passed as a method group | On | | WUH002 | A nested collection Unity does not serialize | On | | WUH003 | ?. / ?[] / ?? / ??= / is null on a UnityEngine.Object | On | | WUH004 | An NUnit null assertion that passes over a destroyed object | On | | WUH005 | UnityEngine.Random (non-replayable in tests) | On | | WUH006 | A discarded EffectHandle | On | | WUH007 | A discarded coroutine handle | On | | WUH008 | A TryXxx out value read without testing the call | On | | WUH009 | A teardown's base call that is not last | On | | WUH010 | A dictionary indexer read | Off | | WUH011 | A comparer mode changed after collection construction | On | | WUH012 | A serialized row dereferenced without a null test | On | | WUH013 | A counting loop that could be a foreach | Off | | WUH014 | A disposable struct whose Dispose assigns | On | | WUH015 | An invalid Unity lifecycle signature | On | | WUH016 | A Unity callback hides an ancestor callback | On | | WUH017 | A GetComponent compared against null | On | | WUH018 | String equality without an explicit policy | Off |

  4. Overview of Asset Validation

    main

    Asset Validation allows you to write custom project-wide checks (e.g., "every enemy prefab must have a spawn point") and run them across your entire project without freezing the Unity Editor.

    Unlike standard menu commands that load all assets at once and lock the editor, this system runs rules incrementally, only loading the specific assets a rule requests. Findings are grouped in an Issues view by asset, severity, rule, and fix details, supporting both Dark and Light editor skins.

  5. Performance features and benchmarks

    main

    Unity Helpers is optimized for high-performance Unity development across several domains:

    • Random Number Generation: Thread-local instances that are 10-15x faster than Unity.Random with zero GC pressure.
    • Spatial Queries: QuadTree2D provides $O(\log n)$ complexity, significantly outperforming linear $O(n)$ searches for large datasets.
    • Memory Management: Zero-allocation buffering and object pooling for collections and arrays to minimize GC spikes.
    • Reflection: Cached delegates that outperform raw System.Reflection (up to 320x for typed access) and are safe for IL2CPP/AOT.
    • List Sorting: A suite of adaptive algorithms (e.g., Ghost, Meteor, Pattern-Defeating QuickSort) tuned for various dataset types and sizes.
  6. Compare Unity Helpers with Unity Default and Odin Inspector

    main

    Unity Helpers provides a free (MIT) alternative to Odin Inspector, offering declarative attributes for inspector customization and specialized serialization types that Unity does not support natively.

    Key feature mappings:

    • Grouping/Boxes: Use [WGroup] (instead of Odin's [BoxGroup] or Unity's Custom Editor).
    • Foldouts: Use [WGroup(collapsible: true)] (instead of Odin's [FoldoutGroup]).
    • Method Buttons: Use [WButton] (instead of Odin's [Button]).
    • Conditional Display: Use [WShowIf] (instead of Odin's [ShowIf]).
    • Enum Toggles: Use [WEnumToggleButtons] (instead of Odin's [EnumToggleButtons]).
    • Complex Data: Use SerializableDictionary<K,V>, SerializableHashSet<T>, SerializableType, or SerializableNullable<T> to handle types Unity cannot natively serialize.
    | Feature                 | Unity Default | Odin Inspector        | Unity Helpers                 |
    | ----------------------- | ------------- | --------------------- | ----------------------------- |
    | **Grouping/Boxes**      | Custom Editor | `[BoxGroup]`          | `[WGroup]`                    |
    | **Foldouts**            | Custom Editor | `[FoldoutGroup]`      | `[WGroup(collapsible: true)]` |
    | **Method Buttons**      | Custom Editor | `[Button]`           | `[WButton]`                   |
    | **Conditional Display** | Custom Drawer | `[ShowIf]`           | `[WShowIf]`                   |
    | **Enum Toggles**       | Custom Drawer | `[EnumToggleButtons]` | `[WEnumToggleButtons]`        |
    | **Dictionaries**       | Not Supported | `[ShowInInspector]`   | `SerializableDictionary<K,V>` |
    | **Sets**                 | Not Supported | Custom               | `SerializableHashSet<T>`      |
    | **Type References**     | Not Supported | Custom               | `SerializableType`            |
    | **Nullable Values**     | Not Supported | Custom               | `SerializableNullable<T>`       | 
    | **Cost**                | Free          | $55-$95              | Free (MIT)                    |
  7. Explore Unity Helpers Feature Index

    main

    The Unity Helpers repository provides a wide range of tools for Unity developers, including editor tooling, data structures, math extensions, and an effects system. Use the alphabetical feature index to navigate to specific documentation for features such as:

    • Editor Tools: Animation creation, sprite tools, and validation.
    • Data Structures: Binary heaps, bitsets, cyclic buffers, and spatial trees (KdTree, OctTree).
    • Math & Extensions: Geometry helpers, color utilities, and collection extensions.
    • Effects System: Data-driven buffs, debuffs, and status effects using Attribute and AttributeEffect.
    • Utility Components: Components for oscillation, collision proxying, and transform matching.
    • Visual Components: Enhanced UI elements like EnhancedImage and LayeredImage.
  8. Configure Relational Component search options

    main

    Relational attributes support several options to control how the hierarchy is traversed and how results are filtered:

    Traversal Control

    • OnlyAncestors = true: Excludes the current GameObject from the search, looking only at parents/grandparents.
    • OnlyDescendants = true: Excludes the current GameObject from the search, looking only at children/grandchildren.
    • MaxDepth: Limits how many levels the search traverses. For example, MaxDepth = 1 with OnlyDescendants = true targets only immediate children.

    Filtering and Constraints

    • TagFilter: Filters components by their Unity Tag.
    • NameFilter: Filters components by their name.
    • MaxCount: Limits the number of items collected into a collection (e.g., List or HashSet).
    • Optional = true: Prevents errors if no matching component is found (the field remains null).

    Resolution

    • Interface/Base-type resolution: The attributes automatically resolve fields to interfaces or base classes if specified.
  9. How VContainer and Unity Helpers work together

    main

    The VContainer integration solves the problem of manual hierarchy reference management (e.g., GetComponent, GetComponentsInChildren) when using Dependency Injection.

    While VContainer handles service dependencies (like IHealthSystem), Unity Helpers automatically wires up relational component fields (like Animator or Rigidbody2D) immediately after DI injection completes. This allows you to replace repetitive Awake() boilerplate with declarative attributes, providing automatic validation and reducing runtime errors.

    public class Enemy : MonoBehaviour
    {
        [Inject] private IHealthSystem _healthSystem;
    
        [SiblingComponent] private Animator _animator;
        [SiblingComponent] private Rigidbody2D _rigidbody;
        [ChildComponent] private Collider2D[] _childColliders;
    
        // No Awake() needed for GetComponent calls; fields are auto-wired.
    }
  10. Understand the runner-preflight diagnostic job

    main

    The runner-preflight job runs on ubuntu-latest before any self-hosted Unity matrix jobs. It validates that the repository has visible, accessible, and correctly labeled runners available in the organization.

    Key Behaviors

    • Fail Closed: The job will fail if there are missing reader credentials, API failures, no visible runner groups, or no online runners matching the required runs-on labels.
    • Success Criteria: A green preflight confirms that the dispatcher has a valid path to the runners. Busy runners are still considered "eligible" because GitHub can queue the job until they become idle.
    • Security: It uses an organization-level GitHub App (the "reader App") with Self-hosted runners: read permissions. It requires the following organization secrets to be exposed to the repository:
      • BUILD_LOCK_READER_APP_ID
      • BUILD_LOCK_READER_APP_PRIVATE_KEY

    If the preflight passes but jobs remain queued, the issue is likely a GitHub dispatcher bug rather than an access issue.

  11. Configure WInLineEditor display modes

    main

    You can control how the inline editor appears using the WInLineEditorMode enum passed to the attribute constructor:

    • WInLineEditorMode.AlwaysExpanded: Always shows the inline inspector without a foldout.
    • WInLineEditorMode.FoldoutExpanded: Shows a foldout that starts in the expanded state.
    • WInLineEditorMode.FoldoutCollapsed: Shows a foldout that starts collapsed (this is the default behavior).

    If no mode is specified, the attribute uses the global setting defined in Unity Helpers Settings.

    using UnityEngine;
    using WallstopStudios.UnityHelpers.Core.Attributes;
    
    public sealed class AbilityConfig : ScriptableObject { }
    
    public class WInlineEditorModes : MonoBehaviour
    {
        [WInLineEditor(WInLineEditorMode.AlwaysExpanded)]
        public AbilityConfig alwaysVisibleConfig;
    
        [WInLineEditor(WInLineEditorMode.FoldoutExpanded)]
        public AbilityConfig expandedByDefault;
    
        [WInLineEditor(WInLineEditorMode.FoldoutCollapsed)]
        public AbilityConfig collapsedByDefault;
    }
  12. Implement data-driven effects with the Effects System

    main

    The Effects System allows you to create AttributeEffect (ScriptableObjects) that modify stats, apply tags, and trigger cosmetic behaviors.

    Core Components:

    • AttributeEffect: Bundles stat changes, tags, and duration.
    • EffectHandle: A unique ID returned when applying an effect; used to remove or refresh specific stacks.
    • AttributesComponent: Base class for components exposing modifiable Attribute fields.
    • TagHandler: Manages string tags (e.g., "Stunned") for gameplay gating.
    • CosmeticEffectData: Container for visual/audio behaviors (prefabs) shown while an effect is active.

    Modifier Durations:

    • ModifierDurationType.Instant: Permanent application; returns null handle.
    • ModifierDurationType.Duration: Temporary; expires automatically.
    • ModifierDurationType.Infinite: Persists until RemoveEffect(handle) is called.

    Attribute Modification Order:

    1. Addition $\rightarrow$ 2. Multiplication $\rightarrow$ 3. Override.
    using WallstopStudios.UnityHelpers.Tags;
    
    // 1) Define stats on a component
    public class CharacterStats : AttributesComponent
    {
        public Attribute Health = 100f;
        public Attribute Speed = 5f;
    }
    
    // 3) Apply and later remove
    GameObject player = ...;
    AttributeEffect haste = ...; // ScriptableObject reference
    EffectHandle? handle = player.ApplyEffect(haste);
    if (handle.HasValue)
    {
        // Remove early if needed
        player.RemoveEffect(handle.Value);
    }
    
    // Query tags anywhere
    if (player.HasTag("Stunned")) { /* disable input */ }