HUD System
A HUD is a set of anchored elements bound to real game data through authored chains — built visually, validated automatically, and zero-migration as it evolves.
What the system is for
A Unity HUD usually starts as a handful of Text and Image components updated from scattered Update() calls, one per gameplay system that needs to show something. Health, ammo and timers each get their own bespoke wiring, and adding a new element means writing new binding code instead of authoring one.
Serenity's HUD system treats a HUD as authored data instead of hand-wired components. Each element anchors to one of nine positions with grow direction as a separate axis, optionally mirrors per player, and binds to live game data through a chain of reads over Serenity's snapshot-shaped services — authored visually in the HUD Builder and edited directly in the HUD Preview.
The Unity problem
Hand-wired HUD elements couple UI code directly to gameplay services, so every new element means new C# and every renamed method means a silent runtime break. Placing an element for a second player usually means duplicating the layout by hand, and an element that can't resolve its data source typically throws or renders nothing, with no indication of why.
Without a shared representation for how a value is drawn, health bars, ammo counters and timers each reinvent formatting — precision, padding, capacity — and a designer who wants to move an element half a pixel to the left has to go through a programmer to do it.
How Serenity approaches it
A HUD element's placement uses the nine-way UiAnchorType with grow direction as an independent axis, so a bottom-right ammo counter can extend right-to-left. Elements can be scoped to a player and mirrored automatically — P1 bottom-left becomes P2 bottom-right without authoring it twice. A binding is a source plus an ordered chain of reads with authored constant arguments over Serenity's snapshot-shaped services; Try-style methods contribute their out value, a service source resolves lazily and latches only on success, and an unresolvable binding shows the element's fallback text and reports why instead of throwing.
Seven representations cover the ways a value gets drawn: text, number (precision, zero padding, thousands grouping), time (including the arcade MM'SS"CC style), stack, segmented, gauge and icon set. The three that draw an empty part alongside the filled part require a capacity binding, and that rule is enforced in one shared place the builder, the runtime and the validator all read.
How it fits into Serenity
HUD Builder (Tools ▸ Serenity ▸ Create ▸ UI ▸ HUD Builder) authors and edits HUD assets with a guided member picker: each step's dropdown is built from the type the previous step produced, so a chain can only be authored into shapes that actually resolve. A dedicated hud-bindings validator catches bindings that no longer resolve, representations missing their capacity binding, and duplicate ids — interactively or headlessly in CI.
HUD Preview renders the HUD through the real runtime element views at a chosen resolution, theme and backdrop, and is a direct-manipulation editing surface: drag to move, corner or edge handles to scale (free deform by default, Shift constrains proportions), a lollipop handle or just-outside-a-corner to rotate, Ctrl to snap, Alt to center, Escape to cancel — every gesture a single Undo step. Rotation and per-axis Stretch are zero-migration for existing assets, and mirroring keeps a true mirror image. Each theme can supply a HudElementTemplate slot to skin elements in its own visual language.
Practical workflow
- Open HUD Builder and add elements, anchoring each with UiAnchorType and a grow direction.
- Author a binding per element as a chain: pick a source service, then chain reads using the guided member picker until the chain resolves to a displayable value.
- Choose a representation — text, number, time, stack, segmented, gauge or icon set — and set a capacity binding for the representations that need one.
- Scope player-specific elements and let mirroring generate the opposite-side layout automatically instead of authoring it twice.
- Open HUD Preview to drag, scale and rotate elements directly at the target resolution and theme, with every gesture recorded as a single Undo step.
- Run the hud-bindings validator, interactively or in CI, to catch unresolvable bindings, missing capacity or duplicate ids before they reach players.
What you get
- Nine-way UiAnchorType placement with grow direction as an independent axis
- Player-scoped elements with automatic mirroring — author once, both sides work
- Binding chains over snapshot-shaped services with lazy, latch-on-success resolution
- Fallback text and reported reason instead of an exception for unresolvable bindings
- Seven representations: text, number, time (incl. MM'SS"CC), stack, segmented, gauge, icon set
- HUD Builder with a type-driven guided member picker for authoring binding chains
- HUD Preview as a direct-manipulation surface — drag, scale, rotate, all in one Undo step
- hud-bindings validator for unresolved bindings, missing capacity and duplicate ids, interactive or CI
When to use this
- Games that need health bars, ammo counters, timers or any live stat on screen without hand-writing per-element update code.
- Split-screen or local multiplayer HUDs that need a mirrored second-player layout without duplicating authoring.
- Teams that want a designer-editable HUD — placement, binding and skin — without a programmer in the loop for every tweak.
- Projects that want CI to catch a HUD binding broken by a rename before it ships as a blank element.
Related systems
Use Serenity when you want a HUD that is authored data instead of scattered UI code — bound to real services, editable by dragging, and validated before it ever reaches a player.
English
Español
Català