RadialProgressBar is a circular progress indicator that renders arcs using UI Toolkit's mesh generation API. It supports multi-segment displays (like Overwatch-style health bars), smooth animations, and indicator overlays.

Attributes

Radial Progress Bar Inspector

AttributeDescription
Animation Settings
Instant PositiveIf enabled, positive value changes are shown instantly without animation.
Instant NegativeIf enabled, negative value changes are shown instantly without animation.
Update FrequencyInterval in milliseconds between animation updates.
StepHow much the progress bar moves per update (0-1 range).
First DelayDelay before the first bar starts moving. Which bar moves first depends on whether the change is positive or negative.
Second DelayDelay before the second bar starts moving.
Segment Settings
ProgressArray of progress segments. Each has CurrentValue, TargetValue, and Color. Set via UXML to define segments with colors.
IndicatorIndicator segment shown behind progress segments.
Cell Settings (Optional)
Cell SizeValue each cell represents. Set to 0 to disable cells.
Max ValueMaximum total value for cell calculation.
Cell Gap DegreesGap between cells in degrees.
Appearance
ThicknessWidth of the circular arc line.
Color BGBackground circle color.
Indicator Auto ColorWhen enabled, indicator color automatically switches between positive/negative colors.
Color Indicator PositiveIndicator color when showing a positive change.
Color Indicator NegativeIndicator color when showing a negative change.

Progress Segment Attributes

Each element in the Progress array has:

AttributeDescription
CurrentValueCurrent fill value (0-1). Don't edit directly—use TargetValue instead.
TargetValueTarget fill value (0-1). Set this to change the fill level.
ColorColor of this progress segment.

Custom USS Properties

Customize appearance by overriding these USS properties in your stylesheet.

For quick styling, add predefined color classes like primary. See colors for options.

PropertyDescription
--radial-progress-bg-colorBackground circle color.
--radial-progress-progress-colorColor of the main progress arc.
--radial-progress-indicator-positive-colorIndicator color for positive changes.
--radial-progress-indicator-negative-colorIndicator color for negative changes.

Public Methods

PlayProgress

Starts the animation to visually apply current Progress values.

csharp
public void PlayProgress()

PlayIndicator

Starts the animation to visually apply the Indicator value.

csharp
public void PlayIndicator()

RebuildSegments

Must be called after changing SegmentCount. Recreates the internal Progress array.

csharp
public void RebuildSegments()

GetTotalCurrentValue / GetTotalTargetValue

Helper methods for multi-segment bars. Returns the sum of all segment values.

csharp
public float GetTotalCurrentValue() public float GetTotalTargetValue()

UXML Usage

Single Segment (Default)

xml
<CupkekGames.Luna.RadialProgressBar name="health-radial" thickness="8" style="width: 100px; height: 100px;" />

Multi-Segment with Colors (UXML)

Set segments directly in UXML using the progress attribute. Format: CurrentValue|TargetValue|ColorHexRGBA| separated by commas.

xml
<CupkekGames.Luna.RadialProgressBar name="health-radial" thickness="10" max-value="1000" cell-size="100" cell-gap-degrees="4" progress="1|1|53E653FF|,0|0|4CDCFFFF|,0|0|FFD933FF|" style="width: 120px; height: 120px;" />

This creates 3 segments:

  • Segment 0: Green (#53E653) - Health
  • Segment 1: Cyan (#4CDCFF) - Shield
  • Segment 2: Gold (#FFD933) - Armor

C# Examples

Basic Single Segment

csharp
using UnityEngine; using UnityEngine.UIElements; using CupkekGames.Luna; public class RadialProgressDemo : MonoBehaviour { private RadialProgressBar _healthBar; private void Start() { var root = GetComponent<UIDocument>().rootVisualElement; _healthBar = root.Q<RadialProgressBar>("health-radial"); // Initialize without animation _healthBar.InstantPositive = true; _healthBar.InstantNegative = true; _healthBar.Progress[0].TargetValue = 1f; _healthBar.Indicator.TargetValue = 1f; _healthBar.PlayProgress(); _healthBar.PlayIndicator(); // Enable animation for future changes _healthBar.InstantPositive = false; _healthBar.InstantNegative = false; } public void TakeDamage(float amount) { _healthBar.Progress[0].TargetValue -= amount; _healthBar.Indicator.TargetValue = _healthBar.Progress[0].TargetValue; _healthBar.PlayProgress(); _healthBar.PlayIndicator(); } }

Multi-Segment (Overwatch Style)

When using UXML to define segments with colors, the code becomes simpler:

csharp
using UnityEngine; using UnityEngine.UIElements; using CupkekGames.Luna; public class OverwatchHealthBar : MonoBehaviour { private RadialProgressBar _healthBar; private int _health = 1000; private int _shield = 0; private int _armor = 0; private const int BaseMaxHealth = 1000; private void Start() { var root = GetComponent<UIDocument>().rootVisualElement; _healthBar = root.Q<RadialProgressBar>("health-radial"); // Segments and colors are already set via UXML progress attribute UpdateHealthBar(); } public void TakeDamage(int damage) { // Damage order: Armor → Shield → Health if (_armor > 0) { int armorDamage = Mathf.Min(_armor, damage); _armor -= armorDamage; damage -= armorDamage; } if (damage > 0 && _shield > 0) { int shieldDamage = Mathf.Min(_shield, damage); _shield -= shieldDamage; damage -= shieldDamage; } if (damage > 0) { _health = Mathf.Max(0, _health - damage); } UpdateHealthBar(); } private void UpdateHealthBar() { float total = BaseMaxHealth + _shield + _armor; _healthBar.MaxValue = total; // Calculate normalized values float healthNorm = _health / total; float shieldNorm = _shield / total; float armorNorm = _armor / total; // Update segments (colors already set from UXML) var segments = _healthBar.Progress; segments[0].TargetValue = healthNorm; segments[1].TargetValue = shieldNorm; segments[2].TargetValue = armorNorm; _healthBar.Data.Indicator.TargetValue = healthNorm + shieldNorm + armorNorm; _healthBar.PlayProgress(); _healthBar.PlayIndicator(); } }

How Multi-Segment Rendering Works

When SegmentCount > 1, the RadialProgressBar draws consecutive arcs in a single element:

  1. Segment 0 starts at 12 o'clock (top)
  2. Segment 1 starts where Segment 0 ends
  3. Segment 2 starts where Segment 1 ends
  4. And so on...

Each segment's TargetValue represents its portion of the full circle. The total of all segments should typically equal 1.0 (full circle), but can be less for partial fills.

Single RadialProgressBar with SegmentCount = 3 ┌──────────────┐ / Segment 2 \ ← Blue (shields) / ┌──────────┐ \ │ / Segment 1 \ │ ← Yellow (armor) │ │ ┌────────┐ │ │ │ │ │Segment0│ │ │ ← Green (health) │ │ └────────┘ │ │ │ \ / │ \ └──────────┘ / \ / └──────────────┘ All segments are drawn as consecutive arcs in the SAME circle, not stacked rings.

Note: This is different from stacking multiple RadialProgressBar elements with different sizes (concentric rings). The multi-segment feature draws all segments in a single arc on the same circle.

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