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.

| Attribute | Description |
|---|---|
| Animation Settings | |
| Instant Positive | If enabled, positive value changes are shown instantly without animation. |
| Instant Negative | If enabled, negative value changes are shown instantly without animation. |
| Update Frequency | Interval in milliseconds between animation updates. |
| Step | How much the progress bar moves per update (0-1 range). |
| First Delay | Delay before the first bar starts moving. Which bar moves first depends on whether the change is positive or negative. |
| Second Delay | Delay before the second bar starts moving. |
| Segment Settings | |
| Progress | Array of progress segments. Each has CurrentValue, TargetValue, and Color. Set via UXML to define segments with colors. |
| Indicator | Indicator segment shown behind progress segments. |
| Cell Settings (Optional) | |
| Cell Size | Value each cell represents. Set to 0 to disable cells. |
| Max Value | Maximum total value for cell calculation. |
| Cell Gap Degrees | Gap between cells in degrees. |
| Appearance | |
| Thickness | Width of the circular arc line. |
| Color BG | Background circle color. |
| Indicator Auto Color | When enabled, indicator color automatically switches between positive/negative colors. |
| Color Indicator Positive | Indicator color when showing a positive change. |
| Color Indicator Negative | Indicator color when showing a negative change. |
Each element in the Progress array has:
| Attribute | Description |
|---|---|
| CurrentValue | Current fill value (0-1). Don't edit directly—use TargetValue instead. |
| TargetValue | Target fill value (0-1). Set this to change the fill level. |
| Color | Color of this progress segment. |
Customize appearance by overriding these USS properties in your stylesheet.
For quick styling, add predefined color classes like primary. See colors for options.
| Property | Description |
|---|---|
| --radial-progress-bg-color | Background circle color. |
| --radial-progress-progress-color | Color of the main progress arc. |
| --radial-progress-indicator-positive-color | Indicator color for positive changes. |
| --radial-progress-indicator-negative-color | Indicator color for negative changes. |
Starts the animation to visually apply current Progress values.
public void PlayProgress()Starts the animation to visually apply the Indicator value.
public void PlayIndicator()Must be called after changing SegmentCount. Recreates the internal Progress array.
public void RebuildSegments()Helper methods for multi-segment bars. Returns the sum of all segment values.
public float GetTotalCurrentValue()
public float GetTotalTargetValue()<CupkekGames.Luna.RadialProgressBar
name="health-radial"
thickness="8"
style="width: 100px; height: 100px;" />Set segments directly in UXML using the progress attribute. Format: CurrentValue|TargetValue|ColorHexRGBA| separated by commas.
<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:
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();
}
}When using UXML to define segments with colors, the code becomes simpler:
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();
}
}When SegmentCount > 1, the RadialProgressBar draws consecutive arcs in a single element:
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)
Font Family
DM Sans
Wix
Inclusive Sans
AR One Sans
Direction