Masking is a technique used to control which portions of a UI element are visible. Within UI Toolkit, you can apply the USS property overflow: hidden to hide any parts of an element that extend beyond its parent.

Unity Documentation

Refer to the official Unity documentation.

Unity Masking Documentation

Overwatch-Style Progress Bar

This tutorial focuses solely on implementing the masking technique—not on creating the entire progress bar.

1 - Install the Vector Package

To enable masking with custom shapes, you'll use SVG. To apply an SVG image as a background, you must install the com.unity.vectorgraphics package.

The SVG background image will be applied to the parent element.

Below is the SVG used in this example. Feel free to download and use it:

overwatchCell

Import settings of the SVG:

svgimport

2 - Create the Visual Elements

Let's set up simple parent-child elements for the masking example:

html
<engine:VisualElement class="progress-container"> <engine:VisualElement class="progress-fill" /> </engine:VisualElement>

3 - Style with Background-Repeat

css
.progress-container { flex: 1; overflow: hidden; background-image: url('overwatchCell.svg'); background-repeat: repeat-x; background-position-x: left 0px; background-position-y: top 0px; background-size: 20px 100%; /* Control the width and height; the width determines how many times the background image repeats. */ } .progress-fill { height: 100%; width: 80%; /* Determines the fill amount */ }

4 - Controlling Background with Script

Use these functions to adjust the background image size, which in turn determines the number of repeats. And set the width of the fill element to control the fill amount.

csharp
private void SetBackgroundImageWidth(int widthInPixels) { // Update the background size of the progress container. // Set the width in pixels and the height to 100% of the container. _progressContainer.style.backgroundSize = new BackgroundSize( new Length(widthInPixels, LengthUnit.Pixel), Length.Percent(100) ); } public void SetBackgroundImageRepeatAmount(int repeatAmount) { // Retrieve the current width of the progress container. float width = _progressContainer.contentRect.width; // Ensure the width is valid (not NaN and greater than zero). // The contentRect is not calculated at first frames, so be careful. // You might have to manually call SetBackgroundImageWidth if you need to set the width at the start. if (float.IsNaN(width) || width <= 0) { return; } // Calculate the width for a single background cell, rounding to the nearest pixel. int cellWidth = (int)(width / repeatAmount + 0.5f); // Apply the calculated cell width to update the background image size. SetBackgroundImageWidth(cellWidth); } public void SetFillAmount(float fillAmount) { // Make sure fillAmount is within the range [0, 1]. fillAmount = Mathf.Clamp01(fillAmount); // Update the width of the fill element. _progressFill.style.width = Length.Percent(fillAmount * 100); }

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