One component for Unity UI. Add a UIShape to any UI element and you get rounded, squircle, octagonal or slanted shapes with fill, gradients, textures, drop shadow, inner shadow, glow, outline, bevel and background blur, plus soft masking, progress wipes and per-state button styling. No sprites, no 9-slices, no render textures. Everything stays crisp at any resolution.
Demo scenes live in UI Shapes/Demo/, one folder per pipeline, each with a full showcase scene and a Background Blur scene.
To make it interactive, click Add Button or Add Toggle next to the Selectable field at the top of the inspector. See Button States.
UIShape as a decorator: leave Fill off and put it on (or beside) an existing Image to wrap it in a shadow, glow or outline.Each effect is a collapsible module, styled like Unity's Particle System. The checkbox in the module header is the on/off switch, and clicking the bar expands the settings. A module you expand while it's off shows its settings read-only.
Most effects share the same handful of controls at the top of their module, described once under Common Controls. Each effect's section below lists only its own settings.
All sizes and distances are in canvas units, and all angles are in degrees.
| Field | What it does |
|---|---|
| Corner Style | Sharp (default) is a plain rectangle, and hides the radius controls since they don't apply. Rounded gives circular corner arcs. Octagonal cuts each corner off as a straight 45° chamfer. Squircle gives superellipse arcs, the continuous corner familiar from iOS and Figma, with Squareness setting how square they are.
Sharp
Rounded
Octagonal
Squircle
|
| Border Mode | How the corner radius is shared out. Uniform uses one radius for all four corners. Round auto-sizes it to half the short side, so squares become circles and long rectangles become pills. Free gives a separate radius per corner.
Uniform
Round
Free
|
| Squareness | Squircle only. How square the corner arcs are, from 0 to 1. At 0 the arc is a plain circle, identical to Rounded; around 0.5 sits the familiar iOS and Figma look; 1 is a nearly square corner that still meets the edges smoothly. Animatable, and it blends smoothly between button states. |
| Corner Radius | The arc radius on Rounded and Squircle, or the chamfer size on Octagonal. Radii that would overlap along an edge scale down together, the same way CSS border-radius does. |
Fill, outline, shadows, glow and bevel all follow the corner style, so the shape keeps one silhouette. Style and radii animate and can be overridden per button state. Transitions between Sharp, Rounded and Squircle morph the corners rather than popping, because squareness 0 is exactly the Rounded arc.
Pick a style by looks. Sharp, Rounded and Octagonal all cost the same. Squircle costs a little more, mostly on the soft effects, and only on the shapes that use it. That difference never registers on PC or console, and on mobile ordinary squircle buttons and panels are fine. The case worth profiling is a whole screen of squircle panels each carrying a drop shadow.
Turn the Skew module on to slant the shape like italic text. It's purely visual, so the RectTransform, layout and anchoring don't change, and every effect slants with it, still anti-aliased.
| Field | What it does |
|---|---|
| Skew Axis | Horizontal or Vertical. |
| Skew Angle | The slant in degrees. 0° is upright. |
| Skew Mode | Parallel: both edges share the angle, giving a parallelogram. This is the classic italic slant, and the default. Mirrored: the opposite edge takes the negative angle, giving a symmetric trapezoid. Good for banners, ribbons and fake-perspective panels. Custom: an angle per edge (Left and Right, or Bottom and Top on a vertical skew) for an asymmetric trapezoid. Parallel
Mirrored
Custom
|
The module has its own on/off switch, so you can keep an angle set and switch the slant per button state, where it fades in and out smoothly.
A trapezoid narrows as the angle grows and stops before the edges cross, settling into a clean triangle. How steep you can go depends on the element's proportions: a tall element takes a much steeper angle than a short one.
Soft masks, Background Blur and click detection all follow the slanted outline.
These four settings appear on most effect modules. Each effect section below says which of them it has, then lists its own specific fields.
| Field | What it does |
|---|---|
| Color Mode | Whether the effect uses a Single Color or a gradient. See below. |
| Opacity | 0 to 1, fading that effect alone. Layers on top of the color's own alpha. |
| Blend Mode | How the effect composites over what's beneath it. Normal covers, Additive brightens (good for glows and bevel highlights), and Multiply darkens (good for bevel shadows and tinted overlays). |
| Intensity | 0.1 to 10, an alpha multiplier. Values above 1 make a soft effect's core denser without making it any bigger, which is the difference between a faint haze and a solid core at the same radius. Only the three soft effects have it. |
Wherever Color Mode offers a gradient, the choices are Vertical (top to bottom), Horizontal (left to right), or Custom Angle, which adds an Angle slider (0° puts the end color on the right, 90° on top).
Fill uses Unity's own gradient editor: click the Gradient field and add as many color and alpha stops as you like, anywhere along the ramp. Set the gradient's own mode to Fixed for hard-edged bands instead of a smooth blend. Every other effect (Texture, Drop Shadow, Inner Shadow, Glow, Outline) keeps a simpler start and end color, which is what those effects are normally used for.
Colors carry alpha, so a transparent stop gives a clean fade-out, and alpha stops can sit at different positions from the color stops. Colors blend the way they do in Photoshop, Figma and CSS. Gradients cost nothing extra to draw, and state transitions cross-fade them, including between a single color and a gradient, or between two gradients with different numbers of stops.
The shape's interior, as a single color or a multi-stop gradient.
Common controls: Color Mode and Opacity. Fill has no blend mode or intensity of its own, since it's the bottom layer everything else composites over. Textures are a separate module, covered next.
A sprite drawn on top of the Fill and clipped to the shape's corners. It has its own on/off switch, so you can use it with Fill off. With no sprite assigned it draws a plain white rect, which the tint turns into a flat colored layer.
Common controls: Color Mode, Blend Mode and Opacity. The color here is a tint: it multiplies the sprite's own colors rather than replacing them, like Image.color. White, the default, leaves the sprite untouched, and a grayscale or white sprite can be recolored freely. A gradient Color Mode tints across the shape, so one sprite can fade between two colors. The tint's alpha multiplies with Opacity.
| Field | What it does |
|---|---|
| Texture | The sprite to draw. Leave it empty to draw nothing. |
| Texture Fit | How the sprite fits the rect when the aspect ratios don't match. See the table below. |
| Pixels Per Unit Multiplier | Constant Size only. Scales the tile's on-screen size, matching Image.pixelsPerUnitMultiplier. |
| Grayscale | Strips the sprite's color before the tint is applied. On its own it grays an image out, which is what you want on a Disabled state. Combined with a tint it recolors the image through that single color. |
Texture Fit handles mismatched aspect ratios:
| Mode | Behavior |
|---|---|
| Stretch (default) | Scales to fill, ignoring aspect ratio. |
| Aspect Fit | Keeps aspect and fits inside the shape. The margin is transparent, like Image.preserveAspect. |
| Aspect Fill | Keeps aspect, scales up to cover the shape, crops the overflow. |
| Constant Size | A fixed on-screen texel size, tiled to cover the rect. Needs a non-atlas sprite with Wrap Mode: Repeat, and the inspector warns if the sprite doesn't qualify. The tile size comes from the sprite's Pixels Per Unit, the Canvas's Reference Pixels Per Unit, and the multiplier above. |
Every fit works from the sprite's full authored size, including any transparent border, so artwork sitting off to one side keeps its intended aspect and position. A sprite packed into a trimmed Sprite Atlas is the exception: the border no longer exists there, so the fit uses the trimmed artwork. Set the sprite to Mesh Type: Full Rect if you need the border preserved in an atlas.
Textures always render upright. They never shear with a skewed shape, though the silhouette still clips them. The tint gradient does follow the shape, so it stays aligned with the fill's gradient.
Every Texture field animates and can be overridden per state, so a state can swap the sprite, the fit, the tint or the opacity. Grayscale is on or off rather than an amount, so it switches at the start of a state transition instead of fading across it, like Texture Fit and the blend modes.
A soft shadow behind the element.
Common controls: Color Mode, Opacity, Blend Mode and Intensity.
| Field | What it does |
|---|---|
| Radius | Blur distance. |
| Distance | How far the shadow is offset from the shape. |
| Angle | Which way it's offset. 0° is right, 90° is up. |
| Spread | Grows or shrinks the shadow before blurring. |
The shadow is cut out of the shape's interior, so a semi-transparent glass panel never shows its own shadow through itself.
A soft shadow drawn inside the shape's edge, for a recessed look. It covers the outer edge completely, so no rim of fill color peeks through.
Common controls: Color Mode, Opacity, Blend Mode and Intensity.
| Field | What it does |
|---|---|
| Radius | Blur distance. |
| Distance | How far the shadow is offset inside the shape. |
| Angle | Which way it's offset. 0° is right, 90° is up. |
| Spread | Positive values thicken the shadow on all sides. |
A halo around the shape, additive by default. It's centered, so unlike the shadows it has no distance or angle, and like the drop shadow it renders only outside the shape.
Common controls: Color Mode, Opacity, Blend Mode and Intensity.
| Field | What it does |
|---|---|
| Radius | How far the glow reaches out from the shape. |
| Spread | Grows or shrinks the glow before blurring. |
A stroke on the shape's edge.
Common controls: Color Mode, Opacity and Blend Mode. The outline is a hard-edged effect, so it has no intensity.
| Field | What it does |
|---|---|
| Placement | Inside, Outside or Centered on the edge. |
| Width | Stroke thickness. It stays even on skewed shapes. |
| Softness | 0 for a crisp stroke, higher to feather it. |
| Distance | Pushes the stroke further out, for a detached ring. |
On a sharp-cornered shape, Outside and Center strokes miter to a point. With a radius, the outer edge grows to radius + width, the way design tools stroke a rounded rectangle.
A Photoshop-style inner bevel: a lit band along the edge, with a highlight on the light-facing side and a shadow opposite, wrapping around rounded corners.
Bevel has no single color of its own. Instead the highlight and the shadow each get their own Color, Opacity and Blend Mode, so you can tune the two halves independently. The defaults are additive white and normal black; set the shadow to Multiply for the classic Photoshop look.
| Field | What it does |
|---|---|
| Width | The band size. |
| Depth | Shading strength. |
| Softness | Feathers the band and flattens the shading where two edges meet: a square corner's miter line, an octagon's facet joins, and the ridge running inward from every corner. 0 gives a crisp chisel with hard miter joins. Measured in the same units as Width, so a Softness near the Width washes the facets out completely. |
| Angle | Light direction. The default 135° is Photoshop's up-left. |
| Invert | Flips the lighting so the shape reads as pressed in. Handy for a pressed button state. |
| Highlight Color Highlight Opacity Highlight Blend Mode | The lit side of the band. Additive white by default. |
| Shadow Color Shadow Opacity Shadow Blend Mode | The unlit side. Normal black by default. |
Frosted glass, blurring whatever is rendered behind the shape. Pair it with a semi-transparent Fill for tinted glass. It's clipped to the shape's corners, respects soft masks, and composes correctly where panels overlap.
Blur has none of the common controls. Its three settings are its own, and the tint comes from the Fill module underneath.
| Field | What it does |
|---|---|
| Radius | Blur strength. |
| Blur Opacity | Mixes between the sharp and the blurred background. 1 is fully blurred. This is a mix, not a fade to transparent, so lowering it lets the sharp background show through rather than making the panel see-through. |
| Quality | The blur's sample count: High (32 taps), Medium (16) or Low (8). Lower counts cost proportionally less and stay smooth even at large radii, with the difference showing mostly on busy, high-contrast backdrops. This is your main lever on mobile, so see Performance & Platforms before shipping. |
| Pipeline | Setup |
|---|---|
| Built-in | Works out of the box, and is the only pipeline that also blurs UI behind the panel, including elements on the same canvas. |
| URP | One-time setup: select your URP Renderer asset (under your URP Asset's Renderer List) and add the Renderer Feature UI Shapes Background Blur Feature. Until you do, blur panels stay invisible and the inspector shows a reminder. The feature costs nothing on frames with no blur panel, so it's safe to leave installed. Its Capture Resolution (default Half) is a second mobile lever, covered under Performance & Platforms. |
| HDRP | No setup. It's handled automatically. |
Reveal a fraction of the shape, like an Image's Fill Amount, for radial timers, linear bars and cooldown sweeps. Off by default; turn the module on with its header checkbox.
| Field | What it does |
|---|---|
| Amount | 0 to 1, how much shows. This is the value you animate or drive from script (ProgressAmount). |
| Method | Radial is a 360° sweep (pie or clock). Linear is a straight wipe. |
| Origin | Where the fill starts: the edge it grows from on Linear, or the starting angle on Radial. |
| Clockwise | Radial only. Reverses direction. |
| Targets | Which effects get trimmed: any mix of Fill, Outline, Glow, Drop Shadow, Inner Shadow and Bevel. Unticked effects always draw in full, so you can wipe the Fill while a static Outline frames the whole shape. Background Blur is never trimmed. |
The wipe has smooth anti-aliased edges, adds no draw calls, and works with masking, the Animator and button states. Gradients, textures and bevels are revealed exactly as far as the Amount.
A mask hides whatever its children draw outside it. Use one to keep a scrolling list inside its panel, or to make a square photo come out round.
| Mode | What it does |
|---|---|
| None | No masking. |
| Simple | Hard-edged clipping through Unity's own Mask component. Add that component to the same GameObject and keep Fill on. |
| Soft | Smooth-edged clipping, and any side can fade out. Replaces Mask and RectMask2D, so remove those from the object first. |
Soft also skips rows that scroll fully out of sight, so a long list only costs you what's on screen.
Soft mode adds two settings that reshape the clipped area:
Each takes four values, for Left, Right, Top and Bottom, so every side can differ:
| Field | What it does |
|---|---|
| Padding | Pulls that side inward. Negative values push it outward instead, letting children spill past the shape. Corner radii stay as they are. |
| Softness | Fades that side out over the distance you give it. Softening the top and bottom of a scrolling list is the classic use: rows dissolve at the edges, with no gradient overlay image. A side left at 0 keeps its crisp edge, and two soft sides meet cleanly in the corner between them. |
Both belong to the shape itself, so they stay the same across button states and aren't saved into a style. From script they're MaskPadding and MaskSoftness.
Maskable, the last field in the module, works in every mode. Turn it off to stop a mask further up the hierarchy from clipping this shape, so a large shadow or glow can spill outside a masked parent. It controls whether this shape is clipped, not whether it clips others.
Whether the shape catches pointer events is set at the top of the inspector, next to Selectable. Most shapes show a Raycast Target checkbox. A shape whose Selectable lives on a different UI Shape, such as a child checkmark, shows a Raycast Mode dropdown instead:
| Mode | What it does |
|---|---|
| Follow (default) | Catches nothing itself, but mirrors the parent shape's Highlighted, Pressed and Selected look across the whole parent. That's how a checkmark lights up with its toggle. |
| On | Hit-tests its own bounds and computes its own state. |
| Off | Inert, purely decorative. |
Hit-testing matches the shape you see, not its bounding rectangle. Rounded, squircle and octagonal corners, slant and taper are all accounted for, so a click just outside a corner falls through to whatever's behind. Drop shadow and glow aren't clickable.
This applies to the shape itself only. Children keep their own pointer behavior, so turning Raycast Target off makes the shape click-through without affecting anything parented under it.
A UI Shape can restyle itself per Selectable state, with no sprite swaps.
Selectable) to Selectable, or click Add Button / Add Toggle to add and assign one in a single step. UI Shapes then takes over the visuals: it sets that Selectable's Transition and Navigation to None and turns Raycast Target on. Switch Navigation back on if you need keyboard or controller support.An orange bar in the left gutter marks every property, module header and tab that differs from Normal, like Unity's prefab override lines, so you can see what a state changes without opening it.
The selected tab is the live preview: the element on screen shows that state while you edit it, and switching back to Normal shows the base look. Previews are never saved.
State precedence matches Unity's Selectable: Disabled > Pressed > Selected > Highlighted > Normal.
Assign a Toggle as the Selectable (or click Add Toggle) and an Off | On bar appears above the state tabs, so every interaction state can be authored separately for the unchecked and checked toggle.
SetIsOnWithoutNotify and Toggle Group (radio button) switching, are picked up automatically. There's nothing to call.Add Toggle also creates a ready-made child Checkmark UI Shape, gray when off and green when on, driven by the same Toggle, so a fresh toggle works immediately. Restyle or delete it freely.
That's the general pattern for shape checkmarks: give a child UI Shape the same Toggle as its Selectable and author its On/Off looks. Sharing the Selectable also makes the checkmark follow the parent's Highlighted, Pressed and Selected state across the whole parent, so hovering anywhere on the toggle lights the checkmark too (see Raycast Mode).
Any tab, Normal or a state, can save its settings as a style asset and load them onto other shapes. The Style field at the top of each tab is the picker.
.asset file and loads it.A style saved from Normal is a complete look, so loading it onto a state tab overrides every property there. A style saved from a state tab stores only that state's overrides. Load it onto another button and it changes just those properties, leaving the rest to follow that button's own Normal. That's what makes one shared hover or pressed style work across buttons that look nothing alike.
Styles are an authoring convenience only. Nothing reads them at runtime, so they cost nothing in a build, and deleting a style asset never breaks one.
Every setting is a plain serialized field, so the Animator can drive it directly: corner radius, colors, shadow distance, anything. Animated values sit under state overrides, so animation drives the base look and states override on top.
From code, everything lives in the PrizmGames.UIShapes namespace:
using PrizmGames.UIShapes;
var shape = GetComponent<UIShape>();
shape.CornerRadius = 24f; // properties push to the shader automatically
shape.FillColor = Color.white;
shape.Glow = true;
shape.ShadowOpacity = 0.6f;
shape.SetBorderMode(UIShape.BorderMode.Round);
shape.Progress = true; // radial timer
shape.ProgressAmount = timeLeft / duration;
CornerRadius, FillColor, ShadowRadius, TextureSprite, SkewAngle and so on) and mark the shape dirty on write.FillGradient (the mode), FillGradientColors (a standard UnityEngine.Gradient) and FillGradientAngle. Assigning FillGradientColors copies the gradient in, so the shape never shares your instance; if you instead mutate the returned gradient in place, call shape.SetDirty().ShadowGradient, ShadowColor2, ShadowGradientAngle, and likewise for InnerShadow…, Glow… and Outline…. The Texture tint follows the same pattern: TextureColor, TextureGradient, TextureColor2, TextureGradientAngle, plus TextureGrayscale.Set… method instead of a property (SetCornerStyle, SetBorderMode, SetSkewAxis, SetSkewMode, SetTextureFit, SetProgressMethod, SetProgressOrigin, SetProgressTargets), because a property would collide with the enum's own name.shape.CurrentState reads the active state. shape.GetStyle(state) returns an Off-column override block, and shape.GetOnStyle(state) the checked column's.shape.SetDirty() afterwards.Each enabled effect draws one quad in a single pass, and effects of the same kind batch together across the whole canvas. However many shapes a canvas holds, it costs at most one draw call per kind of effect in use. There are no blur passes, no render textures and no per-frame memory churn.
On PC, Mac, PlayStation and Xbox, UI Shapes is not a budget item. Every effect is too cheap to time reliably there, and that holds when you stack effects on a shape or fill a screen with shapes. Even Background Blur, the one effect worth thinking about on mobile, disappears into the noise at every quality setting.
Design for looks first. The charts below are for mobile and Switch, on a deliberately unforgiving scale. An orange bar means "the most expensive thing in this asset", not "expensive".
Typical UI built with UI Shapes, as a share of a frame's GPU budget. Here the full track is the whole frame, so short bars are the point:
Mobile and Switch have real budgets, so the rest of this section is written for them. The guidance is simple, and following it costs you nothing visually.
Relative GPU cost of each effect on its own, on a mobile-class GPU:
Bevel is the heaviest of the ordinary effects, because it draws two quads: a highlight and a shadow. The three soft effects, Drop Shadow, Inner Shadow and Glow, cost in proportion to their Radius, so read them as one band rather than a ranking. A big glow easily outweighs a small drop shadow. Everything below Bevel is cheap enough to use freely at ordinary button and card sizes, even on mobile.
Blur is the one effect that can dominate a mobile frame. On PC and console it's free in practice, but on a mobile-class GPU, Switch included, a large panel can cost more than every other effect combined. Your levers, in order of impact:
Blur suits menus and dialogs on any platform. Budget it before putting it on a permanent HUD.
On the same scale as the chart above:
Effects add up, plus a little: six on one shape cost about half again as much as the same six spread out, because each is another transparent layer over the same pixels. Two effects on many elements is cheaper than six on a few.
| As you add shapes | What happens |
|---|---|
| CPU | Flat. Going from a handful of shapes to a screen full of them, with all of them animating a color every frame, does not move CPU time noticeably. |
| Draw calls | Nearly flat. Shapes using the same effect batch together, so a screen of overlapping three-effect shapes adds far fewer batches than shapes. |
| GPU | Adds up with painted area. Transparent UI never occludes, so every effect pixel is paid for whether it ends up visible or buried. |
The count of shapes is rarely the problem. The total area your effects paint almost always is. A drop shadow on every row of a long list is the classic way to run out of budget on mobile; the same shadow on the list container costs a fraction of it.
| Symptom | Fix |
|---|---|
| "Shader not found" in the console | The files under UI Shapes/Shaders/ were moved or deleted. Reimport the package. |
| Background Blur does nothing on URP | Add the UI Shapes Background Blur Feature to your URP Renderer asset. The inspector shows the same reminder. |
| Background Blur shows a sharp background | Unity cached a stale shader compile. Right-click UI Shapes/Shaders and choose Reimport. |
| Background Blur doesn't blur other UI on URP / HDRP | By design, since the capture is taken after the camera finishes. Only Built-in blurs same-canvas UI. |
| Effects invisible in VR | The canvas is Screen Space – Overlay. Switch it to World Space. |
| Button states don't apply in play mode | Check that a Selectable is assigned and its own Transition is None. The inspector hints at both. |
| TMP text isn't clipped by a Soft mask | The TMP integration compiles only when a TMP package is installed. Check that TMP is present in the project. |
| Soft-clipped TMP text is missing bevel / glow / lighting | By design: clipped text uses a Mobile Distance Field shader, which keeps face, outline and underlay. Use Simple masking if you need the full feature set. |
| A child Image or RawImage isn't soft-clipped | Graphics with a custom material are skipped deliberately. Remove the custom material, or use Simple masking. |
A child isn't clipped by Simple masking, Mask or RectMask2D | Check Maskable on that child. Stencil and rect clipping only apply to graphics that have it on. |
Hidden objects named [UIShape] … | The internal effect renderers. They're never saved into your scene or prefab and rebuild automatically, so don't edit them. |
The UI Shapes folder is also a UPM package (com.prizmgames.uishapes). To reference it from another project, add this to that project's Packages/manifest.json:
"com.prizmgames.uishapes": "file:../path/to/UI Shapes/Assets/UI Shapes"
Questions, bug reports and feature requests are all welcome. Email support@prizmgames.net.
For a bug report, please include your Unity version, the render pipeline you're using (Built-in, URP or HDRP), the UI Shapes version, and the steps to reproduce the problem. A screenshot or a small repro scene helps a lot.