Unity 6 ships no form validation for UI Toolkit. UGUI's CharacterValidation.EmailAddress only filters which characters can be typed — it does not validate the final string is a valid email. UITK's regex attribute on TextField evaluates per-character: try a full-email or full-IP pattern and all input is blocked because no single character satisfies the full-string pattern. This asset is the runtime validation layer that fills the gap.
Forms are plain C# — no GameObject pollution.
Form.For(VisualElement) and Form.For(UIDocument) give you a plain C# form object — no MonoBehaviour wrapping, no required components, no hidden inspector toggles. Register fields fluently from a controller's OnEnable and drop multiple forms into a single UI sub-tree without GameObject contortions.
Fluent schema with two equivalent styles.
Wrap any UI Toolkit control via its value-change surface — TextField, Toggle, Slider, IntegerField, DropdownField, EnumField, custom controls. Register fields atomically or as chained specs:
form.RegisterText("email")
.WithRule(Rules.Required())
.WithRule(Rules.Email());
form.RegisterText("username")
.WithRule(Rules.Required().MinLength(3).MaxLength(20))
.WithRule(Rules.Regex("[a-zA-Z][a-zA-Z0-9_]*"))
.WithMessage("3–20 characters, must start with a letter.");
Both styles produce the same result. WithMessage overrides per-rule error text.
14 built-in rules.
Required, MinLength, MaxLength, Regex (auto-anchored with ^...$ so full-string patterns actually work), Email, Url, Range<T>, MinValue<T>, MaxValue<T>, OneOf<T>, NotEqual<T>, Custom, MatchesField, RequiredIf. Extend with your own rules via the standard rule interfaces.
Async validation with stale-result protection.
Rules.CustomAsync<T>(handler, debounceMs) wraps any awaitable into a validation rule with built-in cancellation. Field-level debounce defaults to 300ms when any async rule is present. The framework defends against late-arriving results from two directions at once: cancellation tokens stop in-flight work on every new value change, and a generation counter discards stale-but-completed results even when a rule ignores its cancellation token. Bind a spinner to the form's IsValidating flag for "Checking availability..." UI with one line.
Cross-field rules with cycle detection.
MatchesField("password") and RequiredIf("over18", v => v == true) ship built-in. Declare custom cross-field rules with the standard rule interface. The framework runs cycle detection at form-build time — any circular dependency is logged with the full cycle path before validation runs, so the framework never hangs on a cyclic graph. Dependents re-validate when their source field changes without resetting touched/dirty state and without applying their own debounce.
Form-level state aggregation.
Each field cycles through clean, dirty, touched, validating, and valid/invalid states with predictable transitions. Roll the field state up into form.IsValid, form.IsDirty, and form.IsValidating for one-line button-enabling, "save in progress" indicators, and dirty-form prompts. Errors display after first blur by default so empty forms aren't pre-shouted at on first paint — configurable per field.
Three error display strategies.
Inline error labels (default) auto-create a sibling label per field, or honor a buyer-supplied label. A summary-panel strategy appends one label per error into a top-of-form container. The interface is open for custom strategies (banner, accessibility aria, toast). Swap globally via a single static assignment.
Async submit pipeline.
form.OnSubmit(async ctx => ...) registers your handler. await form.SubmitAsync() validates every field (sync rules + async rules immediately, bypassing debounce), then dispatches to the handler with a submit context that carries the values dictionary, a cancellation token, and a server-error sink. Return Success, Failure(serverErrors), or let it throw — exceptions become an Errored result and the form moves on. Failed submits trigger focus-fir
Description sourced from the Unity Asset Store listing.