StateSwitcher

Namespace: Vortex.Unity.UI.StateSwitcher Assembly: ru.vortex.unity.ui.misc

Purpose

State machine for visual and behavioral switching. UIStateSwitcher manages an array of named states, each containing a set of StateItem.

Capabilities:

  • Switching by index, name, or enum
  • 7 built-in StateItem types: GameObjects, Animator (bool/int), Colors (with animation), Sprites, Events, TweenerHub
  • StateSwitcherAttribute for enum binding with Inspector visualization
  • OnStateSwitch event on state change
  • Reentrancy protection
  • Alt+S / Ctrl+Alt+S hotkeys — add a UIStateSwitcher to an object or as a separate layer

Out of scope:

  • Transition animations between states (use TweenerHubSwitch, ColorsSwitch, or StateView<TEnum> from TweenerSystem when the states are animations)
  • State selection logic (layer 3/4)

Dependencies

Dependency Purpose
Vortex.Unity.UI.TweenerSystem TweenerHub — integration via TweenerHubSwitch
Vortex.Unity.UI.TweenerSystem.UniTaskTweener AsyncTween — color animation in ColorsSwitch
Vortex.Unity.EditorTools DrawingUtility, ToolsSettings — StateSwitcherDrawer rendering
Vortex.Unity.AppSystem.System.TimeSystem TimeController — frame-delayed switching in GameObjectsSwitch
Vortex.Core.ExtensibleEnumSystem ExtensibleEnum — Set(ExtensibleEnum) overload by Order
Odin Inspector [ValueDropdown], [ShowInInspector], [Button]

Architecture

StateSwitcher/
├── UIStateSwitcher.cs          # State machine (MonoBehaviour)
├── StateItem.cs                # Abstract behavior base
├── Items/
│   ├── GameObjectsSwitch.cs    # SetActive on GameObject array
│   ├── AnimatorBoolSwitch.cs   # SetBool on Animator
│   ├── AnimatorStateSwitch.cs  # SetInteger on Animator
│   ├── ColorsSwitch.cs         # Color (instant or animated)
│   ├── SpritesSwitch.cs        # Sprite on SpriteRenderer/Image
│   ├── EventFire.cs            # UnityEvent on activation
│   └── TweenerHubSwitch.cs     # Forward/Back on TweenerHub
└── Handlers/
    └── OnEnableStateRunner.cs  # Switch on OnEnable

UIStateSwitcher

MonoBehaviour with a StateData array. Each StateData is a named state with a StateItem[] array.

On switch:

  1. Calls DefaultState() on all items of the previous state (Danger point!)
  2. Calls Set() on all items of the new state
  3. Fires OnStateSwitch event

API

switcher.Set(0);                        // by index
switcher.Set("Active");                 // by name
switcher.Set(MyEnum.Active);            // by enum
switcher.Set((byte)2);                  // by byte
switcher.Set(myExtensibleEnum);         // by ExtensibleEnum (via Order, null → no-op)
switcher.ResetStates();                 // reset all items + initial state

int current = switcher.State;           // current state (-1 = none)
StateData[] all = switcher.States;      // all states array
switcher.OnStateSwitch += OnSwitch;     // event (StateData or null)
int index = switcher.GetState("name");  // index by name (-1 = not found)
Inspector Field Type Description
states StateData[] State array
stateOnEnable int Initial state (dropdown)
duplicateOnCreate bool Editor-only: clone items from last state when adding new one

StateItem

Abstract behavior class. On state activation — Set(), on deactivation — DefaultState().

Implementation Set() DefaultState()
GameObjectsSwitch SetActive(true) on array (optionally frame-delayed via onDelayed) SetActive(false) (optionally frame-delayed via offDelayed)
AnimatorBoolSwitch SetBool(name, true) SetBool(name, false)
AnimatorStateSwitch SetInteger(name, value) SetInteger(name, default)
ColorsSwitch Set color (instant or via AsyncTween) Revert to Color.white
SpritesSwitch Set sprite Set null
EventFire UnityEvent.Invoke() Nothing
TweenerHubSwitch tweener.Forward() tweener.Back()

ColorsSwitch

Supports SpriteRenderer, Graphic (Image, Text), Outline. Modes:

  • Instant color change
  • Animated via AsyncTween with configurable duration and curve
  • Optional start color: _useOwnStartColor = true — takes current color from the object, false — uses the _startColor field

Inspector button Get from... — captures current color from first object.


StateSwitcherAttribute

Attribute for binding UIStateSwitcher to an enum. Used with StateSwitcherDrawer.

[SerializeField, StateSwitcher(typeof(MyStatesEnum))]
private UIStateSwitcher switcher;

In Inspector displays a state table:

  • Index, description (from [Tooltip] / [LabelText]), name from switcher
  • Active state highlighting
  • Click to switch
  • Sync button — synchronizes state names with enum descriptions

Hotkeys

For selected scene objects or objects of an open prefab (UI/UIBuilder/Shortcuts/UIStateSwitcherShortcut.cs):

Shortcut Menu Action
Alt+S Tools/Vortex/UI/Add UIStateSwitcher Add a UIStateSwitcher to the object itself; skipped where one already exists
Ctrl+Alt+S Tools/Vortex/UI/Add UIStateSwitcher Layer A child layer [UIStateSwitcher] with a switcher: first in the hierarchy, at the zero point, on a plain Transform (RectTransform is removed); new layers are selected

Assets in the Project window are not affected. Undone in one step. The menu items live in the UIBuilder package together with the other layout hotkeys; adding the component and creating the layer is shared code in EditorTools/HierarchyTools/HierarchyLayers.cs, the same as for the TweenerHub hotkeys (Alt+T / Ctrl+Alt+T).


OnEnableStateRunner

MonoBehaviour — switches a UIStateSwitcher to a given state on OnEnable.

Field Type Description
_stateSwitcher UIStateSwitcher Target switcher
_stateToOpen int State index

Edge Cases

Situation Behavior
Set() with out-of-range index LogError, state unchanged
Set() with same index Skipped (state not reapplied)
Set() during transition Reentrancy guard (_isSwitching)
Set() before Awake State saved in _startState, applied in Awake
GetState("nonexistent") Returns -1
Set("nonexistent") LogError, then falls back to stateOnEnable — the switcher never sits in an undefined state
StateItem.Set() throws an exception A try/catch wraps the foreach: LogError + LogException, the remaining StateItems in this state are not applied (fail fast, do not mask the actual problem)
ColorsSwitch with _smoothChange and zero _duration Instant change (AsyncTween with duration ≤ 0)
Duplicate DropDownGroupName/DropDownItemName across StateItem classes LogError, duplicate skipped in dropdown