CellBar (luna:CellBar) is the celled combat bar: an Overwatch-style resource pool rendered as discrete slanted cells. Health, armor and shield stack in one strip, damage drains from the top of the stack with a white hit flash and a red ghost that lingers under fire, heals sweep in, pickups pop per cell, and the whole bar pulses faster and redder the closer you are to zero.

It shares the animation core with the rest of the family (see Architecture) but renders through the mesh painter, so cells, slant, gradients and the damage grammar are native. For a continuous meter with ruler ticks (League-style), use the linear Progress Bar instead: two idioms, two components.

Quick Start

xml
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:luna="CupkekGames.Luna"> <luna:CellBar name="Vitals" cell-size="25" slant="10" cell-gap="3" threshold="0.334" feel="../Presets/CellBarFeelOverwatch.asset" style="width: 280px; height: 16px;" /> </ui:UXML>
csharp
CellBar bar = root.Q<CellBar>("Vitals"); bar.SetResources(("health", 100f, 100f), ("armor", 50f, 50f)); bar.Damage(70f); // drains armor first, flash + ghost + drain play bar.Heal("health", 45f); // clamps to the resource max, sweep plays bar.Add("armor", 50f); // pickup, per-cell pop cascade plays

Values are units, never normalized fractions. cell-size is units per cell, so 150 total pool at 25 per cell renders 6 cells, and a 700 pool renders 28. The pool comes from SetResources; each entry is (id, current, max) in render order, and damage always drains the last resource first.

The damage grammar

Every mutation produces a delta that the component turns into motion:

BeatWhat plays
DamageThe lost span flashes white, the fill drains fast, and a red ghost holds at the pre-hit total before draining. New hits during the hold extend it (up to a cap), so a burst reads as one chunk.
HealThe positive indicator leads, the fill follows, and a bright band sweeps across the healed span.
Pickup (Add)Cells the gain completes pop with a white flash, staggered left to right; partial fills get only the sweep.
Low poolBelow threshold, fill colors pulse toward the low tint. Rate and intensity scale with severity: 0.9 Hz at the threshold, up to 2 Hz near zero.

The threshold evaluates on the animated values, not the raw data write: the pulse starts when the drain visually lands, which is what you want.

Feel assets

All grammar numbers live in a CellBarFeelAsset (Create > CupkekGames > Luna > Cell Bar Feel): fill/drain durations and easings, duration mode, ghost hold and cap, flash, sweep, pop and pulse settings. Assign it with the feel attribute (relative path in samples) or bar.Feel = asset; swapping the asset swaps the whole feel.

Two presets ship with the Showcase sample under ProgressBar/Presets/: CellBarFeelOverwatch (the reference numbers) and CellBarFeelSubtle (softer flash and pop, gentler pulse). Assigning a feel also zeroes first-delay/second-delay so the ghost hold is the only ghost timing authority.

Without an asset, the same values are settable directly: ghost-hold-ms and ghost-hold-cap-ms are UXML attributes; flash/sweep/pop/pulse settings are C# properties (FlashDurationMs, SweepColor, PulseRateMaxHz, LowTintColor, ...).

Geometry attributes

AttributeDefaultDescription
cell-size25Units per cell. Cell count is ceil(max-value / cell-size).
slant10Cell shear in degrees. 0 gives straight cells.
cell-gap2Pixels between cells.
sizing-modeStretchStretch fills the element's USS box. FixedCellWidth sizes the element from the pool.
cell-width18Cell width in pixels (FixedCellWidth only).
cell-height14Cell height in pixels (FixedCellWidth only).
max-row-width0FixedCellWidth wrap limit; 0 means a single row.
row-gap3Pixels between wrapped rows.
edge-cap-width2Bright cap at the leading fill edge; 0 disables.
threshold0Normalized low-pool threshold for the pulse and the cell-bar--below-threshold class.

FixedCellWidth with max-row-width gives the tank read: bar length is proportional to the pool and wraps to extra rows when it does not fit.

Styling

Colors resolve USS-first with attribute fallbacks:

css
.my-vitals { --cell-bar-color-0: #ECE8E1; /* resource run colors by index, 0..9 */ --cell-bar-color-1: #69F5EA; --cell-bar-bg-color: rgba(255, 255, 255, 0.08); --cell-bar-outline-color: rgba(255, 255, 255, 0.10); --cell-bar-indicator-negative-color: #ED3B4A; --cell-bar-indicator-positive-color: #BFF5EF; --cell-bar-edge-cap-color: rgba(255, 255, 255, 0.85); }

Attribute equivalents: color-background, color-outline, color-edge-cap, plus the family's shared color-indicator-positive / color-indicator-negative. Segment colors can also be set in code through bar.Progress[i].Color.

The cell-bar--below-threshold class toggles with the threshold, and the six external transition slots from the family (fill, drain, complete, pulse-below, filled) are available for element-level juice on top of the internal grammar.

Demos

The Showcase sample's ProgressBarOverwatchCelled scene is the flagship: the entire controller is button wiring and label updates, the component owns the rest. The sibling ProgressBarOverwatch scene keeps the manual approach on the linear bar for comparison, and the EsportLobby experience drives its match HUD vitals with a CellBar and an esl-skinned feel asset.

The CellBarLab scene pushes the same element into four less obvious shapes: an ammo grid using FixedCellWidth wrap (30 rounds in two rows, instant shots, pop-cascade reload), a versus split where the right bar is mirrored with scale: -1 1 so it drains toward the center, a rainbow combo meter charged by scripted Add ticks, and an extremes pair showing the same value on one 100-unit cell versus one hundred 1-unit cells. Everything in the lab is stock attributes plus the combat facade.

Settings

Theme

Light

Contrast

Material

Dark

Dim

Material Dark

System

Sidebar(Light & Contrast only)

Light
Dark

Font Family

DM Sans

Wix

Inclusive Sans

AR One Sans

Direction

LTR
RTL